Functional Programming và state
functional
9
Scala
50
White

huydx viết ngày 29/05/2015

alt text

State là gì, tại sao nó xấu

Trong các ngôn ngữ imperative thông thường như java hay ruby, thì việc thay đổi "state" của một đối tượng là chuyện xảy ra như cơm bữa.
Chắc có nhiều bạn chưa hình dung thay đổi "state" là gì, mình có ví dụ đơn giản bằng ruby như sau

class Foo
 attr_accessor :bar

 def init
    bar = 5
 end

 def plus
   bar += 1
 end
end

foo = Foo.new
foo.plus.plus

Việc gọi hàm plus như ở trên mình vừa làm sẽ thay đổi state của đối tượng foo. Chắc các bạn sẽ thắc mắc rằng chuyện thay đổi đấy là "bình thường". Những bạn nào thắc mắc mình đoán chắc là chưa gặp phải những tình huống ức chế khi bug xảy ra do thay đổi state một cách bậy bạ và tùm lum ở nhiều nơi.
Giả sử object foo của bạn đột nhiên có giá trị bar không như bạn mong muốn. Bạn chửi tùm lum, và phát hiện ra là bạn gọi hàm .plus từ một thread khác...

Tóm gọn lại là thay đổi state là "nguồn gốc" của hầu hết các loại bug, mà điển hình là Heisen bug , hay là loại bug mà cứ mỗi lần bạn muốn debug thì nó ... biến mất =((.

Chắc các bạn lập trình java hay C++ mà phải xoắn nhiều về việc "truyền tham biến hay tham trị" sẽ hiểu cảm giác của Heisen bug.

State trong FP (functional programming).

Mình sẽ dùng scala để minh hoạ cho phần này.
Giả sử bạn có một object như sau:

class Foo { 
  var total : List[Int] = Nil   // Mutable List
  def sum(i:Int):Int = {
    total = i :: total  // SIDE EFFECT
    if(total.length > 1) 99 else  total.sum 
  }
}

Object này giống như ví dụ ruby ở trên, mỗi lần gọi hàm sum bạn thay đổi "state" của object được gọi.
Bạn sẽ thắc mắc rằng, vậy ngoài ra còn cách nào khác đâu?
Việc lưu giữ "state" của một object hay đoạn chương trình gần như là việc không thể thiếu trong lập trình hiện tại. Đoạn code của bạn không thể chỉ có nhận input và trả ra output.
Vậy chúng ta vừa muốn lưu state, lại vừa không muốn có side effect, chúng ta phải làm sao????

Ở thế giới của Functional Programming có một cách giải quyết thú vị chính là việc gói trạng thái vào trong Parameter hoặc là Type.

Có lẽ nhìn code sẽ dễ hiểu hơn

case class ImmutableSum(total : List[Int])

object ImmutableSum{ 
  def sum(i:Int)(b:ImmutableSum):(ImmutableSum,Int) = {
    val result = if(b.total.length > 1) 99 else  b.total.sum
     val newObject = b.copy(total = i :: b.total)
    (newObject, result)
  }
}

Bạn có nhận thấy sự khác biệt?
Ở đây chúng ta thay vì trả về cùng 1 object với nội dung thay đổi, chúng ta trả về một object mới, với một nội dung mới.

Điểm này có lợi gì nhỉ??
Bạn sẽ không bao giờ cùng một object foo bị thay đổi ở nhiều chỗ nữa, vì lúc này chúng ta sẽ có nhiều object foo ở nhiều chỗ khác nhau :D.

Để tìm hiểu một bug nào đó, chúng ta chỉ cần đi ngược lại xử lý được gọi là có thể tìm ngay ra nguyên nhân bug, thay vì như trước đây là chúng ta phải grep toàn bộ chương trình xem chỗ nào dùng và thay đổi foo.

Scalaz có một monad khá hay để giải quyết vấn đề này gọi là State monad. Các bạn có thể tham khảo về cách dùng ở trong bài viết:
http://eed3si9n.com/learning-scalaz/State.html

Functional Programming quả thật là không dễ, nhưng một chương trình được viết hoàn toàn theo FP thì khả năng giảm thiểu các lỗi khó cũng sẽ tăng lên, code flow cũng sẽ dế hiểu hơn nhiều.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

huydx

118 bài viết.
1244 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
222 20
Một ngày đẹp trời, bạn quyết định viết một dịch vụ web dự định sẽ làm thay đổi cả thế giới. Dịch vụ của bạn sẽ kết nối tất cả các thiết bị di động ...
huydx viết 2 năm trước
222 20
White
192 15
Introduction (Link) là một cuộc thi ở Nhật, và cũng chỉ có riêng ở Nhật. Đây là một cuộc thi khá đặc trưng bởi sự thú vị của cách thi của nó, những...
huydx viết 4 năm trước
192 15
White
151 15
Happy programmer là gì nhỉ, chắc ai đọc xong title của bài post này cũng không hiểu ý mình định nói đến là gì :D. Đầu tiên với cá nhân mình thì hap...
huydx viết hơn 5 năm trước
151 15
Bài viết liên quan
White
10 0
Kí tự Regex cơ bản Về cơ bản thì các sử lý matching của scala.util.matching.Regex sẽ được "phó thác" (delegate) cho java Regex. Bạn có thể tạo một ...
huydx viết hơn 5 năm trước
10 0
White
16 6
Người ta nói "nullable values" là cái "billion dollar mistake". Kể từ ALGOL, chúng ta không thể dùng nullable values/references như một value bình ...
Justin Le viết hơn 5 năm trước
16 6
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
118 bài viết.
1244 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!