thảo luận OOP hay FP

Các Voz Dev thuộc trường phái nào ?


  • Total voters
    596
carbon.png
carbon(2).png
 
Last edited:
Đây là lời giải bài Vehicle của mình viết bằng Haskell (FP), mọi người xem thử và nhận xét.

Cảm ơn mọi người nhiều.
 
Mình vừa code backend, vừa code big data job, mình có apply cả oop và fp, thì có nhận xét như sau.

Nếu mà code phải integrate nhiều service (3rd party vendor), đổi công nghệ (database), thay đổi theo layer (replications, distributed cache) dùng oop thực sự rất tốt ở vấn đề refactor.
Còn làm big data job liên quan đến parallel, batch process, mình viết bằng fp, apply parameters, dynamic resource allocation thì fp không chứa state là lựa chọn hàng đầu.
 
theo tôi cái gì cũng có tradeof, dùng fp thì đôi khi code khá dễ đọc dễ debug nhưng do mấy cái principle của nó nên đôi khi optimize hơi khó, oop mà cứ inherit loạn rồi có lúc cũng ra 1 class chứa 1 đống iherited method/property mà không dùng đến, cũng khoai, kể cả với composition cũng đôi khi gặp phải code duplication. Tôi thì không chuyên cái nào chỉ biết mấy sơ lược về 2 cái nên chỉ nhận xét như thế.
 
Cuối cùng thì vẫn không thấy ai đưa ra được ưu điểm vượt trội trong luận điểm của mình.4 năm rồi vẫn một cái vòng luẩn quẩn.Rốt cuộc thì OOP hơn FP ở mặt nào, Fp hơn OOP ở mặt nào.
 
Dân làm phần mềm gặp những bài toán giống nhau, nhưng lời giải của FP với OOP so ra rất khác nhau.

Thay vì đặt câu hỏi kiểu như:
  • Ê, làm thế nào để loop qua một collection?
  • Hey, làm sao để implement Strategy pattern?
hãy nhìn vào bản chất sâu xa hơn của vấn đề:
  • Êu, làm thế nào để thực hiện một action với từng phần tử của một collection?
  • Hey, làm sao để tham số hoá một hành vi (behaviour)?

Chìa khoá của FP paradigm là function có mặt ở khắp nơi, dùng cho mọi thứ.

Ví dụ, một app lớn được xây lên từ những viên gạch nhỏ hơn.
  • Trong OOP, những viên gạch này là class và object.
  • Trong FP, những viên gạch này là function.
Tôi cần giảm coupling giữa các component, tôi muốn tham số hoá một hành vi!
  • Theo cách tiếp cận của OOP, bạn xài interface và áp dụng dependency injection.
  • Bạn tiếp cận theo hướng FP ư, dùng function làm tham số.
Tớ muốn tuân thủ nguyên lí DRY để reuse code cho nhiều component.
  • OOP có nhiều kĩ thuật, tỉ dụ như dùng inheritance, Decorator pattern.
  • FP có mỗi chiêu nhất dương chỉ (xài hoài!): viết reusable code trong các function, rồi compose chúng lại với nhau. Nhạt nhẽo!
Mượn cái hình của bác Scott Wlaschin[1] cho thêm phần sinh động
1719073054873.png


[1] Functional Programming Design Patterns | F# for fun and profit (https://fsharpforfunandprofit.com/fppatterns/)
 
Last edited:
Cross-posted
Job F# vừa hiếm, vừa không có offer tốt ở HCM lẫn HN.

Dù học ngôn ngữ nào hay paradigm nào, cái mình nên học là ý tưởng để giải quyết vấn đề.

F# có vài điểm sáng nho nhỏ (về ý tưởng) mà C# đã học tập theo
  • LINQ (C# 3)
  • async/await (C# 5). Asynchronous programming trong F# ra mắt từ nửa cuối 2007[1]; C# 5 ra mắt khoảng cuối 2011 cùng với VS 2012 và .NET Fx 4.5.
  • Pattern matching (C# 7, 8, 9)
  • Tuple (C# 7)
  • Record (C# 9)
Mình chỉ liệt kê số lượng, không so sánh chất lượng và những khác biệt. So sánh sẽ khập khiễng.

Ngược lại, F# được hưởng lợi rất nhiều do nó là một phần trong hệ sinh thái .NET.


Mình biết rất ít về Python, nhưng có lẽ mình phần nào đồng tình với nhận xét về hệ sinh thái.

Domain modeling là cốt lõi của nhiều nghiệp vụ. Về mặt này, F# có lợi thế hơn C#. F# có discriminated union (DU) và units of measure mà C# thì không[2][3][4]. Trong khi với F#, người ta dùng DU để mô hình hoá (modeling) các lựa chọn; thì với C#, người ta dùng những công cụ như enum, inheritance với base/derived classes. Đứng từ góc độ một domain expert (non-technical people), đọc code F# dễ hiểu và dễ verify hơn type hierarchy bên C#.

Nếu bạn cho rằng OOP (C# nói riêng) là phương pháp tuyệt vời để làm domain modeling, hãy gạt thiên kiến đó qua một bên[5] để xem cách người ta làm với một functional language ra sao[6][7][8][9].

[1] Introducing F# Asynchronous Workflows (https://learn.microsoft.com/en-us/archive/blogs/dsyme/introducing-f-asynchronous-workflows)
[2] Champion "Discriminated Unions" · Issue #113 · dotnet/csharplang (https://github.com/dotnet/csharplang/issues/113)
[3] csharplang/proposals/discriminated-unions.md at main · dotnet/csharplang (https://github.com/dotnet/csharplang/blob/main/proposals/discriminated-unions.md)
[4] GitHub - mcintyre321/OneOf: Easy to use F#-like ~discriminated~ unions for C# with exhaustive compile time matching (https://github.com/mcintyre321/OneOf)
[5] Tách trà (https://trandinhhoanh.wordpress.com/2009/12/10/tach-tra/)
[6] Low overhead type definitions | F# for fun and profit (https://fsharpforfunandprofit.com/posts/conciseness-type-definitions/)
[7] The 'designing with types' series | F# for fun and profit (https://fsharpforfunandprofit.com/series/designing-with-types/)
[8] Domain Driven Design | F# for fun and profit (https://fsharpforfunandprofit.com/ddd/)
[9] Why type-first development matters (https://tomasp.net/blog/type-first-development.aspx/)
 
cái nào cũng là cách lập trình, tuỳ tình huống, ngôn ngữ mà xử lý, chả có cái nào tối ưu 100%, đến cả viết bằng ass chưa chắc đã tối ưu bằng c++, nên đừng có mà quan trọng hoá cái này làm gì
 
Back
Top