Contents
Chào bạn tới với một series mới của Fx Studio. Các bài viết lần này sẽ tập trung vào thư viện mới, được Apple ra mắt vào tháng 6/2019. Đó là Combine.
Nó là gì? Và mục đích nó đến với thế giới này là gì? … thì chúng ta sẽ tìm hiểu thông qua bài viết này.
Bắt đầu thôi!
1. Xu thế
Đã bao lâu rồi bạn chưa cập nhật code của mình trong project? Đã bao lâu rồi bạn chưa thay đổi phong cách code của mình? … thì bây giờ tới thời điểm bạn phải làm tất cả rồi.
Reactive programming is programming with asynchronous data streams.
Đó là câu định nghĩa cơ bản nhất cho Reactive Programming. Đây chính là xu thế mới trong giới lập trình hiện tại. Các ngôn ngữ, các nền tảng đều đã được hỗ trợ. Nhờ nó mà bạn không cần tốn quá nhiều thời gian để chuyển đổi một ngôn ngữ hay học thêm một nền tảng mới.
Quay lại câu định nghĩa trên để phân tích một chút. Ta thấy có 2 khái niệm quan trọng:
data stream
- Chính là luồng dữ liệu. Các giá trị sẽ được phát ra trên đó. Có 3 kiểu chính
- Value –> chứa giá trị
- Error –> lỗi
- Complete –> hoàn thành
- Chính là luồng dữ liệu. Các giá trị sẽ được phát ra trên đó. Có 3 kiểu chính
asynchronous
- Là các xử lý bất đồng bộ
Câu chuyện với bất động bộ thì không bao giờ là đơn giản. Và hầu hết các tương tác trong ứng dụng đều đến từ bất đồng bộ. Ví dụ như:
- Bạn có 1 button, mỗi lần nhấn vào nó thì bạn sẽ đếm 1 lần.
- Bạn không biết được thời điểm nào sẽ bấm? bấm bao nhiêu lần? và lúc nào kết thúc?
Đó chính là mô tả đơn giản nhất về luồng dữ liệu bất đồng bộ. Khi giải quyết chúng, thì ta sẽ không quan tâm tới các đối tượng. Chỉ quan tâm tới dữ liệu vào ra và phản ứng lại với từng giá trị trên stream. Nên bạn cũng sẽ phải tự tìm hiểu và bổ sung kiến thêm về Functional Programming.
Cơ chế giúp xác định được 3 yếu tố trên cả khi lập trình đồng bộ & bất đồng bộ. Funtional Reactive Programming giải quyết vấn đề này bằng cách sử dụng stream để truyền tải dữ liệu: nó có thể sẽ emit ra 3 thứ : 1 value, 1 error, 1 completed (tín hiệu kết thúc 1 task ) theo 1 trình tự thời gian từ nơi phát ra.
Tại sao nên dùng nó?
- Nếu chỉ dừng lại ở đó thì FRP cũng không có gì đặc biệt, điều tạo nên sức mạnh của FRP là việc áp dụng functional programming cho phép filter (filter, take, scan, …), chuyển đổi từ stream này qua stream khác (map, flatMap, reduce), hoặc merge nhiều stream thành một stream mới (combine, merge, zip, …) khá dễ dàng mà không làm thay đổi trạng thái của stream ban đầu.
- Việc sử dụng FRP sẽ cải thiện được trải nghiệm người dùng, khi chúng ta muốn ứng dụng phản hồi nhanh hơn. Lợi ích tiếp theo là giúp hạn chế lưu trữ, quản lý các state trung gian. Trong ví dụ clickStream trên, nếu như sử dụng cách lập trình thông thường, thì phải khai báo rất nhiều biến (state) để lưu trữ các bước trung gian. Ví dụ: timer, click count collection, … Trong FRP, các bước này là không cần thiết nhờ khả năng chuyển đổi stream (map, flatMap, reduce, ….).
- Một điểm mạnh khác của RP là giúp cho việc xử lý lỗi trong lập trình bất đồng bộ nhẹ nhàng hơn rất nhiều. Nếu bạn nào từng handle error khi lập trình bất đồng bộ, multiple thread, thì sẽ thấy việc này không hề dễ dàng. RP giúp tách biệt việc xử lý lỗi với logic. Việc này giúp cho code trong sáng hơn rất nhiều.
… vâng vâng và mây mây … có rất nhiều thứ hữu ích. Nhưng bài chúng ta sẽ không đề cập tới nó mà sẽ quay lại chủ đề chính. Đó là Apple không đứng ngoài cuộc chơi.
2. Combine Framework
Asynchronous Programming
Apple đã chuẩn bị từ rất lâu cho phong cách + xu thế lập trình mới này. Và họ gọi là Asynchronous Programming.
- Khi bạn thực hiện code của mình trên single-thread thì mọi việc rất đơn giản. Bạn nắm được tất cả các trạng thái và thứ tự thực thi của code. Nhưng với những những ngôn ngữ multi-threaded thì bất đồng bộ trong việc điều hướng UI Framework …
- Nó tuỳ thuộc vào môi trường thực thi của nó là như thế nào … nên khó mà đoán đươc khi các thread chaỵ đồng thời.
Dễ hiểu hơn, đối với các ứng dụng thì luôn tồn tại 1 thread là Main Thread để duy trì giao diện ứng dụng. Các tương tác xử lý như API, Location, Upload … để phải thực thi ở 1 Thread khác. Hoặc việc người dùng luôn tác động giao diện và ứng dụng ta phải phản ứng lại các tác động của người dùng … Tất cả chúng đều buộc chúng ta phải xử lý bất đồng bộ với nhau.
Combine không đơn giản chỉ là một framework duy nhất.
Foundation and UIKit/AppKit
- Apple đã âm thâm cải tiến và phát triển Asynchronous Programming trong nhiều năm.
- Họ đã tạo ra rất nhiều cơ chế mà bạn có thể sử dụng ở nhiều cấp độ khác nhau, để tạo và thực thi các mã bất đồng bộ.
- Một số thứ kinh điển như sau:
- NotificationCenter
- Thực thi 1 đoạn mã bất cứ khi nào sự kiện mà bạn quan tâm xảy ra
- The delegation pattern
- Cho phép bạn xác định 1 đối tượng hoạt động thay mặt hoặc phối hợp với một đối tượng khác
- Grand Cental Dispatch & OperationQueue
- Trừu tượng hoá trong việc thực hiện từng phần của công việc
- Lên lịch thực hiện từng phần, theo nhiều cách khác nhau trong ngăn xếp (tuần tự hay ưu tiên)
- Closures
- Tạo ra các đoạn mã có thể tách rời và chuyển cho các đối tượng khác thực thi ở một nơi nào đó
- NotificationCenter
Để viết 1 chương trình bất đồng bộ thì rất tốt. Nhưng về riêng code bất đồng bộ thì rất khó theo dõi, tái sử dụng và không đồng nhất về cú pháp …
Và tất cả những thứ riêng lẻ nằm trong khắp iOS đã kết hợp với nhau để tạo nên Combine Framework.
- Nhằm mục đích giới thiệu 1 ngôn ngữ mới trong hệ sinh tái của Swift, giúp bạn đêm lại trật tự cho thế giới hỗn loạn của lập trình bất đồng bộ.
- Apple đã tích hợp Combine vào sâu trong Foudation, từ Timer tới các cốt lõi như CoreData …
- Có thể tích hợp vào code riêng của
- Quan trong nữa là sự kết hợp ăn ý giữa SwiftUI & Combine
Combine là sự kết hợp, các api của nó với các api đã có. Nên sẽ không ảnh hưởng gì nhiều nếu code của bạn đã xây dựng bất đồng bộ bằng những thứ trước đây.
Tuy nhiên, chúng vẫn đảm bảo sự động tốt nhất cho dù cách mới hay cách cũ.
3. Combine vs. RxSwift
Cũng không ít bạn sẽ nghe tới Rx và RxSwift … định nghĩa đơn giản thì như thế này
RX = OBSERVABLE + OBSERVER + SCHEDULERS
Chúng ta xem nó là người tiền nhiệm của Combine. Khái niệm về nó thì mình tạm thời không bàn tới.
Foundation of Combine
- Về Declarative, Reactive Programming thì không còn mới nữa, nó đã ra đời cách đây khác lâu. Nhưng trong 1 thập kỉ gần đây thì đánh dấu sự trở lại lạnh mẽ của nó.
- 2009 Microsoft đã đưa ra khái niệm về Reative Extention
- 2012 Rx.Net ra đời, kéo theo 1 loạt sau đó như: RxJS, RxKotlin, RxScale, RxPHP …
- Với nền tảng Apple thì chúng ta có third-party là RxSwift
- Với Combine thì:
- Framework chính chủ
- Định nghĩa một chuẩn riêng
- Vẫn giống như Rx về cú pháp, bản chất và cơ chế
Combine sẽ giết chết RxSwift hay không?
Đó là câu hỏi khi mình tìm hiểu về Combine. Câu trả lời là có thể thôi. Dần dần việc sử dụng code Combine sẽ là phổ biến. Tới một lúc bạn không còn nhớ ra có Rx trên thế giới này.
Một thuyết âm mưu lớn được Apple manh nha. Khi bên cạnh sự ra mắt của Combine thì còn có thêm 2 framework khác.
- SwiftUI – xem như là một ngôn ngữ mới (nói hơi quá). Mục đích duy nhất của nó là bạn chỉ cần code 1 lần và chạy trên tất cả mọi nền tảng.
- Catalyst – nỗ lực đưa ứng dụng trên iPadOS lên trên MacOS
Cả 3 thư viện mới tạo nên 1 sức mạnh to lớn. Giúp lập trình viên và khách hàng không phải tốn nhiều chi phí phát triển cả một hệ thống. Bạn không cần tái sử dụng code của mình nữa. Vì nó đã có thể tự chạy trên mọi nền tảng và mọi ngôn ngữ lập trình rồi.
Simple Demo
Nói thì nhiều nhưng chưa vào chuyện chính. Mình sẽ demo một chương trình đơn giản với Combine Code.
import Combine var publisher = ["H", "e", "l", "l", "o", " ", "W", "o", "r", "l", "d", "!"].publisher var subscription = publisher .reduce("", +) .sink { value in print(value) }
Đoạn code trên in ra dòng chữ “Hello World!”. Bằng cách biến đổi 1 array string thành 1 publisher
và sử dụng thêm 1 toán tử reduce
để nối tất cả các giá trị được phát ra lại với nhau. Còn nó là gì chúng ta sẽ tìm hiểu ở các bài viết sau. Còn bây giờ thì mình xin kết thúc bài Hello khá dài này. 🙂
Cảm ơn bạn đã đọc bài viết này.
Tạm kết
- Combine là thư viện mới cho Reactive Programming
- Xử lý code và dữ liệu bất đồng bộ
- Khả năng tích hợp cao vào code trước đây và trong các mô hình (MVC, MVVM …)
Written by chuotfx
Hãy ngồi xuống, uống miếng bánh và ăn miếng trà. Chúng ta cùng nhau đàm đạo về đời, về code nhóe!
Leave a Reply Cancel reply
Fan page
Tags
Recent Posts
- Charles Proxy – Phần 1 : Giới thiệu, cài đặt và cấu hình
- Complete Concurrency với Swift 6
- 300 Bài code thiếu nhi bằng Python – Ebook
- Builder Pattern trong 10 phút
- Observer Pattern trong 10 phút
- Memento Pattern trong 10 phút
- Strategy Pattern trong 10 phút
- Automatic Reference Counting (ARC) trong 10 phút
- Autoresizing Masks trong 10 phút
- Regular Expression (Regex) trong Swift
Archives
- September 2024 (1)
- July 2024 (1)
- June 2024 (1)
- May 2024 (4)
- April 2024 (2)
- March 2024 (5)
- January 2024 (4)
- February 2023 (1)
- January 2023 (2)
- November 2022 (2)
- October 2022 (1)
- September 2022 (5)
- August 2022 (6)
- July 2022 (7)
- June 2022 (8)
- May 2022 (5)
- April 2022 (1)
- March 2022 (3)
- February 2022 (5)
- January 2022 (4)
- December 2021 (6)
- November 2021 (8)
- October 2021 (8)
- September 2021 (8)
- August 2021 (8)
- July 2021 (9)
- June 2021 (8)
- May 2021 (7)
- April 2021 (11)
- March 2021 (12)
- February 2021 (3)
- January 2021 (3)
- December 2020 (3)
- November 2020 (9)
- October 2020 (7)
- September 2020 (17)
- August 2020 (1)
- July 2020 (3)
- June 2020 (1)
- May 2020 (2)
- April 2020 (3)
- March 2020 (20)
- February 2020 (5)
- January 2020 (2)
- December 2019 (12)
- November 2019 (12)
- October 2019 (19)
- September 2019 (17)
- August 2019 (10)