(If you are looking for English version, here you go: POP English)
Trong phần 2, mình sẽ trình bày cách sử dụng Protocol-Oriented Programming kết hợp với Struct để giải quyết một số vấn đề của Class đã trình bày trước đó.
–> Mục tiêu của phần này sẽ là:
- HOW CAN WE USE POP OVER OOP IN SWIFT?
a. Implicit Sharing Data:
Bản chất của Implicit Sharing Data chính là dựa trên cơ chế truyền tham chiếu của Class, do đó, chúng ta chỉ cần thay thế Class bằng Struct:
==> Kết quả:
Vì Parrot là Struct , mà Struct lại là Value Type, tức là nó truyền tham trị, copy và release, nên khi chúng ta thay đổi giá trị của hisParrot, thực chất là chúng ta chỉ thay đổi giá trị của một bản sao chép. Chúng ta có thể tưởng tượng như thế này: chúng ta có 1 con vẹt (myParrot) tên là Jack, trường hợp truyền tham chiếu ở Class, tương đương với việc chúng ta đưa Jack cho một người bạn khác, người bạn đó đặt lại tên Jack lại thành Sparrow –> con Jack của chúng ta bây giờ thành Sparrow. Ngược lại, trường hợp của Struct, chúng ta nhân bản Jack, và đưa con vẹt nhân bản đó cho anh bạn, anh bạn cũng đặt lại tên cho nó là Sparrow, tuy nhiên, con vẹt mà anh bạn đặt tên là con vẹt nhân bản, chúng ta vẫn giữ con Jack. Tức là bây giờ sẽ có 2 con vẹt, 1 con Jack (ta giữ), và 1 con Sparrow (anh bạn giữ).
Một thay đổi nhỏ chuyển từ Class sang Struct –> không còn memory leak, không còn implicit sharing data, không còn deadlock,…. Cool, phải không. Rõ ràng, tâp trung vào Class (tức hướng về OOP) không phải là ý kiến hay.
b. Inheritance problem:
Quay trở lại bài toán về chú chim cánh cụt ở phần trước: chim cánh cụt không có lông vũ, cũng như không thể bay, nhưng chú vẫn thuộc họ nhà chim.
Vậy giờ làm thế nào nhỉ ?
- Decouple ra 2 class: Bird và PenguinBird –> Không ổn, sai hẳn nguyên lý của OOP.
- Tạo một Protocol mới chỉ hành động Fly –> Phải viết lại code rất nhiều.
- Đặt lại static func fly() –> trong trường hợp có nhiều Object thì sao? Rồi còn vấn đề về Concurrency, multi threading,…
Welcome to Protocol-Oriented Programming:
Mình chuyển Bird từ Class sang Protocol, và decouple phương thức fly() và thuộc tính feather thành 2 protocol : Flyable (dành cho những loài chim có thể bay), Featherable (dành cho những loài chim có lông vũ). Nhờ vào tính năng Extension (Category trong Objective-C), mình có thể tùy biến mở rộng Protocol đã khai báo trước đó, các struct không cần phải implement lại phương thức fly() và thuộc tính feather nếu không thực sự cần thiết. –> 3 vấn đề trên của Class đã được giải quyết.
Chú chim cánh cụt giờ có thể vui vẻ được rồi :D.
( Giả sử giờ có thêm chim đà điểu, một loài thuộc họ nhà chim, có lông vũ, nhưng không thể bay –> cách phân tách ra các protocol đã phát huy được tác dụng)
c. Classes Relationship Problem (hay Type Relationship Lost):
Vấn đề của lost relationship của classes đó là việc chúng ta liên tục phải ép kiểu (casting) lại các subclass mỗi khi chúng override. Để giải quyết vấn đề này, chúng ta có thể chuyển đổi từ việc sử dụng Class sang Struct và Protocol:
AbstractComparation từ Class đã chuyển thành Protocol, và các subclass của nó được chuyển thành struct. Việc chuyển từ Class thành Protocol giúp cho AbstractComparation linh hoạt hơn, như ví dụ trong hình là việc inject Dependency vào, nhờ đó, mình không còn cần phải ép kiểu nữa.
- Summary:
Dựa vào những điểm yếu đó, Apple đã tập trung phát triển Protocol và Struct, cuối cùng đưa ra khái niệm mới về Protocol-Oriented Programming. Ví dụ điển hình nhất trong số những vấn đề mình đã trình bày chính là ví dụ về giải quyết vấn đề kế thừa trong Class (ví dụ về Chim cánh cụt). Hiển nhiên cái này chỉ là nguyên lý, còn áp dụng hay không thì phụ thuộc vào bài toán và kinh nghiệm của các bạn. Hi vọng bài viết đã giúp các bạn có được cái nhìn về POP trong lập trình Swift.
Một số link tham khảo:
- Link gốc của Apple: https://developer.apple.com/videos/play/wwdc2015/408/
- Ứng dụng POP: https://realm.io/news/appbuilders-natasha-muraschev-practical-protocol-oriented-programming/
- Link Raywenderlich: https://www.raywenderlich.com/109156/introducing-protocol-oriented-programming-in-swift-2
- Link đưa ra lập luận phản bác, do chính cộng tác viên với tác giả của Apple đưa ra: http://blog.metaobject.com/2015/06/protocol-oriented-programming-is-object.html. Link này viết rất hay, tuy khó hiểu, nhưng nếu ngồi phân tích lại thì lập luận mà tác giả đưa ra cực kì sắc sảo.
Hết.