In his session, Thinh will conduct a seminar on Relactive Programming – an asynchronous programming paradigm concerned with data streams and the propagation of change.
15. VS Traditional programming
SLIDE
15
REACTIVE
PROGRAMMING
var a = 1
var b = 2
var c = a + b
print(c)
let a: Variable<Int> = Variable(1)
let b: Variable<Int> = Variable(2)
let c = Observable.combineLatest(a, b)
c.subscribe { (value) in
print(value)
}
// c = 3
a = 5
print(c)
// c = 3
// c = 3
a.value = 5
// c = 7
{ $0 + $1 }
Trong thời đại công nghệ hiện nay, để đáp ứng được đòi hỏi cao của người dùng về các dịch vụ và ứng dụng, chúng ta phải luôn thay đổi và nâng cao chất lượng sản phẩm hướng tới trải nghiệm tốt nhất cho người dùng, đảm bảo tính liên tục và khả năng phản hồi cao đối với sự tương tác của người dùng. Để xây dựng được những hệ thống như vậy, hiện nay những công ty công nghệ đang áp dụng một phong cách lập trình mới và rất mạnh mẽ, giải quyết được nhiều vấn dề phức tạp, và đó là Reactive Programming
Hiện nay các công ty công nghệ lớn trên thế giới đã apply reactive programming, ví dụ:
Github sử dụng RP để viết ứng dụng Github for Mac OS
Microsoft cho ra đời bộ công cụ RxExtension cho .NET, và ngôn ngữ F#
Facebook thì cho ra đời ngôn ngữ lập trình Reflex
Đặc biệt là Netflix, thành lập một nhóm phát triển các sản phẩm live stream, video, movie hoàn toàn dựa vào phong cách lập trình RP
Vậy RP là gì mà tại sao các công ty công nghê lớn lại chú ý và áp dụng mạnh mẽ như vậy
Là phong cách lập trình, là cách để phân loại các ngôn ngữ lập trình dựa vào các đặc tính của chúng
Hiện nay có nhiều phong cách lập trình nhưng có thể chia thành 2 loại là imperative(mệnh lệnh) và declarative(khai báo), với imeprative chúng ta có 2 phong cách phổ biến nhất là procedure(thủ tục) và lập trình OO(hướng đối tượng), với Procedure chúng ta có các ngôn ngữ như Pascal và C, OO chúng ta có rất nhiều ngôn ngữ hỗ trợ như Java, C++ …
Với Declarative chúng ta có 2 phong cách phổ biến nhất là functional và logical với các ngôn ngữ Haskell, Scalar và Prolog
Trong bài present này mình sẽ dùng một vài đoạn code Swift để minh họa cho một số ví dụ
Vậy imperative là gì? -> Là lập trình mệnh lệnh, dùng các tập lệnh để thay đổi trạng thái của chương trình
Phong cách này tập trung vào câu hỏi “How” tức là nói cho máy làm gì đó bằng cách nào và kết quả mong đợi sẽ xảy ra là gì
Thể hiện logic tính toán mà không mô tả control flow của nó
Phong cách lập trình này tập trung vào câu hỏi “What”, tức là mô tả bạn muốn làm cái gì chứ không phải là phải làm nó như thế nào
Và một đặc điểm quan trọng của nó là không phụ thuộc vào ngữ cảnh
Bạn có thể hình dung là với Imperative Programming thì bạn quan tâm tới việc làm thế nào để giải quyết bài toán còn Declarative Programming quan tâm tới đầu vào và đầu ra của bài toán.
Nó không phải mới được đề xướng trong những năm gần đây, mà nó đã có từ rất lâu rồi, từ những năm 50 – thời sơ khai của máy tính hiện đại, đầu tiên với ngôn ngữ lập trình Lisp. Bao lâu nay nó vẫn tồn tại song song với Imperative mà chúng ta không hề hay biết.
Sự chậm chạp của máy tính thời đó không đủ điều kiện để Lisp phát triển và thế là Imperative lên ngôi, đặc biệt với sự ra đời của C. Đến thập niên 90, có thể coi là thời kỳ thịnh vượng của lập trình hướng đối tượng (OOP) với sự kết hợp mô hình Imperative Programming. Chúng ta trừu tượng hóa các vấn đề thành các đối tượng, đưa ra các phương thức mà đối tượng đó có rồi kết nối chúng lại để tạo ra một chuỗi các bước để đối tượng thực hiện giải quyết vấn đề (how). Hàng loạt các ngôn ngữ mới ra đời đi theo con đường multi-paradigm (OOP + Imperative): Java, C#, C++, Smalltalk, Python, Ruby, PHP…
RP là lập trình với dòng dữ liệu bất đồng bộ và sự lan truyền của sự thay đổi
Ở khái niệm trên, có hai điểm quan trọng chúng ta cần xem xét là Stream và Asynchronous
Stream: Khi thực hiện một tác vụ bất kỳ, chúng ta chỉ quan tâm tới 3 yếu tố: giá trị trả về từ tác vụ đó (data), lỗi (error – nếu có) và thời điểm tác vụ đó kết thúc (completed signed). Như vậy, ta thấy cần có một cơ chế giúp xác định các yếu tố này,RP giải quyết vấn đề này bằng cách sử dụng stream để truyền tải: dữ liệu trả về, lỗi và tín hiệu kết thúc của một tác vụ theo trình tự thời gian từ nơi phát ra tín hiệu (Producer) tới nơi lắng nghe (Subscriber).
Ví dụ như trong mô hình MVC, với bất kì sự thay đổi nào trong model(database) thì sẽ tự động reflect với View và ngược lại
Asynchronous: mục tiêu chính của RP là cung cấp cho chúng ta một phương tiện hữu hiệu để tương tác giữa các tác vụ bất đồng bộ, giúp các bên trong phần mềm có thể giao tiếp mà không cần quan tâm các vấn đề như: concurrence, thread-safety, error handling, …
Reactive Programming mang đến một phong cách lập trình mới khi làm việc với những app đòi hỏi tính tương tác cao. Ví dụ, mobile app hiện đại ngày nay đã phát triển vượt bậc: khi người dùng gõ vào khung search, hay kéo xuống để refresh, không có màn hình mới nào được chuyển đến cả, tất cả mọi UI event đều gọi đến data ở phía sau và phản ánh lại màn hình ngay lập tức.
Mọi thứ trong RP đều có thể là stream, chẳng hạn như biến, đầu vào của người dùng(ví như khi touch vào một button, hay là gõ text vào search bar…)
Một điểm đặc biệt khi tiếp cận với RP là overtime, tức là sự kiện được phát ra trong mỗi stream là bất đồng bộ và theo thời gian
Hãy mườn tượng với sự kiện gõ text vào search bar, liệu hệ thống có đoán biết được khi nào chung ta sẽ gõ kí tự tiếp theo, chung ta mô hình hóa tác vụ đó bằng một stream, các sự kiện gõ ký tự đó được phát ra một cách bất đồng bộ và phụ thuộc vào thời gian, có thể phát ra sự kiện gõ ký tự trong 1 hoặc 2 giây, hoặc là 10s …
Khi tiếp cận với RP, 2 khái niệm mà chúng ta sẽ bắt gặp đó là Observer và Observable
Observable, đơn giản nó là nguồn phát sự kiện
Observer là thực thể nhận sự kiện và xử lý các tác vụ khác khi nhận sự kiện
Observer đăng ký lắng nghe Observable
Nhiều Observer có thể đăng ký lắng nghe tới cùng một Observable
Sự tương tác giữa 2 thực thể này cũng là nguyên lý cơ bản và quan trọng nhất trong RP
2 khái niệm này xuất phát từ mô hình lập trình Observer pattern
Với lập trình truyền thống muốn cập nhất biến c chúng ta phải thực hiện lại phép toàn c = a + b, giả sử với trường hợp biến a được thay đổi ở rất nhiều nơi và nhiều lần thì chuyện gì xảy ra, thật là bất lợi
Nhưng với RP thì việc đó được xử lý rất gọn gàng và tiện lợi
Với lập trình truyền thống muốn cập nhất biến c chúng ta phải thực hiện lại phép toàn c = a + b, giả sử với trường hợp biến a được thay đổi ở rất nhiều nơi và nhiều lần thì chuyện gì xảy ra, thật là bất lợi
Nhưng với RP thì việc đó được xử lý rất gọn gàng và tiện lợi
Lợi ích đầu tiên là giúp cho việc lập trình bất đồng độ trở nên dễ dàng, nhanh chóng, lập trình viên không quan tâm tới thread safety, concurrency, …
Lợi ích đầu tiên là giúp cho việc lập trình bất đồng độ trở nên dễ dàng, nhanh chóng, lập trình viên không quan tâm tới thread safety, concurrency, …
Hiện nay RP xuất hiện trong hầu hết các ngôn ngữ, có một vài tổ chức và cá nhân đứng ra viết một số thư viện theo phong cách RP
Những thư viện này tạo các bộ công cụ tiện ích, một tập các phép toán giúp cho lập trình viên thuận tiện cho việc xử lý các bài toán theo phong cách RP một cách dễ dàng
Đến đây có thể nói rằng RP là một lựa chọn rất tốt cho các lập trình viên nhờ vào những ưu điểm của nó, cùng với sự hỗ trợ tốt từ các thư viện thì không có lý do gì chúng ta không adopt nó vào các dự án