5 ms·
I think mixing the OO and FP is the crux of the problem. Type inference and subtyping (class based inheritance) don't mix well, and often require type annotatio
by dwhitney 6y ago
I think mixing the OO and FP is the crux of the problem. Type inference and subtyping (class based inheritance) don't mix well, and often require type annotations to help the compiler when types get somewhat complex. Eventually you develop an instinct for it, and it's not a problem, but the road to developing that instinct is littered with torn out hair. (edit: spelling)
- joshuapassos 6y agoMaybe the best approach is using a language with dynamic types ? (e.g: cloujure)
- weatherlight 6y agoI have found that languages that support both FP and OO paradigms its best to do things like data manipulation in FP, and use OO to encapsulate those processes and be limited to just passing messages to other objects. Avoid inheritance. Once an object is instantiated, don't change its internal state. etc.
- jdmichal 6y agoThis is my philosophy: Data types are object-oriented. They are responsible for ensuring that their internal state is consistent, and nothing more. They may inherit if it makes sense, but it usually doesn't and most of the time aggregation is more appropriate. Business rules are functional. There's just a bag of composable, pure functions that take the various data types and perform validations, transformations, etc. External services, such as a database, are contractual. This would be an interface in Java or C# defining the required operations of the service. This allows manipulation of these external services during testing. Unit testing would mock them; integration testing would not. Workflows or services are procedural. They combine everything else into an actual use-case. They read in a linear flow of what needs to happen when to meet the use-case.
- hderms 6y agoGreat breakdown. Seriously, I've had very similar ideas but never tried to build a coherent mapping like this. Thanks for writing it out!
- PopsiclePete 6y ago>Avoid inheritance. Once an object is instantiated, don't change its internal state. etc. Just embrace Clojure then. You get all that enforced for you, plus the entire Java eco-system.
- hota_mazi 6y agoYou lose static typing though, and that's a deal breaker with me. And no, core and other half-hearted attempts at gradual typing from Clojure don't even come close to hitting that mark.
- weatherlight 6y agoI'm not a huge fan of the Java ecosystem. Clojure does look really nice and Diatomic looks pretty slick. Have you used Clojerl? https://github.com/clojerl/clojerl https://github.com/clojerl/clojerl
- didibus 6y agoWhen you take away Java, the JVM ecosystem is actually really nice. It's ok if you don't like it, I'm just saying, I used to think the same, but since taking on Clojure I've completely changed my mind, and find the Java ecosystem one of the best out there. Clojure's ecosystem is even better, it improves on the Java one a lot, simplifying most of the warts with the Java one, and like you've brought up, it goes beyond the JVM in having quite a lot of active dialects. I haven't tried Clojerl beyond just REPL, but it seems quite complete, and the maintainer is very active. ClojureScript is also quite nice, if you prefer the JavaScript/Node ecosystem. You can also use ClojureCLR if you like the .Net ecosystem better. And finally there's Babashka which deserves a mention, if you want something more like Python. You also get to play with Clojure derivatives as well: Janet, Fennel, and Ferret can all be picked up in a day if you already know Clojure. For me Clojure was a great investment, and it's replaced all my needs in all areas: scripting, front-end, application development (mobile and desktop), command line tools, server side, big data, batch processing, ML, data visualization, etc. Only downside is you will exist within a niche, but that niche has everything I need.
- dwhitney 6y agoI agree you should avoid inheritance, but it’s the fact that Scala supports inheritance that makes type inference difficult (also null). Type inference in Haskell is much better, for example. I saw a great presentation on the topic by Thomas Wies. Here’s a paper he wrote if you are interested https://cs.nyu.edu/wies/publ/finding_minimum_type_error_sources.pdf https://cs.nyu.edu/wies/publ/finding_minimum_type_error_sour...
- hderms 6y agoYes this is the conclusion I've drawn. Often called "FP in the small, OOP in the large". Higher-level organizational patterns in pure FP style aren't familiar enough to replace the ergonomics of just using a few classes and DI to make things modular. Maybe tagless final or something similar will eclipse it eventually, but for now it seems like using "anemic style" OOP, with functional in the small is still the best we have for mainstream development.