Hacker News new | ask | show | jobs
by jorgeleo 3355 days ago
What you are mentioning is one of the hardest things to do when moving into FP.

"OOP is more suited to model business because you can naturally extend existing types and apply existing operations to them (ie. pass a supermarket everywhere a shop was expected + things such as polymorphism)"

The reason why you feel is more suited is because you are thinking in an object oriented way. It is not a bad thing, but it is not functional.

"... extend existing types and apply existing operations to them". This means you have things, and you do things to them. This is the OOP way, not the FP way.

In FP the things are immutable, so you don't do things to them because they cannot change; instead, you create new things out of what you have.

In OOP this is what you have, this is what it can do, and you put all the gears (or objects) together and you get your engine.

In FP you have pipes, this is what I have and if I put it through this pipe it becomes something else.

When a local shop there is a sale, there is a function that takes a bunch of arguments and produces something called a sale, Maybe is the total, maybe is a tuple with the different pieces of the sale.

When you move that to a supermarket, then the question is: how what the shop owner calls a sale in the local shop is different from what the supermarket owner calls a sale? How my vocabulary changed? for a lot of things, you will see that the meaning is the same, just over more data; and also, there are new words that didn't exist in the smaller context. A sale is in both cases the sum of the quantity multiplied by the price of the groceries, apply the tax, spit out the result. But maybe the meaning of Tax changed, instead of been a fixed percent, it needs to be the lookup in a table depending on where the supermarket is.

If you need to constantly add switch cases, then probably you are using a functional language using an OOP mentality.

The way that I have introducing FP to people is using Excel. Think on this syntax:

A1: 1 B1: 2 C1: A1 + B2

You don't need new cells, C1 does not mean the same thing and the formula have to change... the formula or is it the function?

When you model the real world, you can focus on the objects, map them to types, and go from there. Or you can focus on the meaning of the words, then you need just a few types, see how those meanings compound, and go from there.

"But in this case I'd question if FP modelling really is the best tool to model real world business for which it is natural to define things as extensions of other things."

I agree, FP is bad at extending things... but it is not FP fault that you see the world as things that need to be extended.

A middle step between what you are saying and FP will be Flow Programming (https://en.wikipedia.org/wiki/Flow-based_programming). It is not FP, nor OOP, but somewhere in between.

1 comments

Many thanks for taking the time to explain this, I can see that you have a point.

>Or you can focus on the meaning of the words, then you need just a few types, see how those meanings compound, and go from there.

>I agree, FP is bad at extending things... but it is not FP fault that you see the world as things that need to be extended.

I should probably give another look to FP and continue to study the subject, I have likely been approaching it with a OOP mindset as you suggest. One last question though, what about code duplication ? If you focus on the meaning of words and compounding these meanings to create new things, wouldn't it most of the time create lot of duplicate code ? For example in the case of the local shop and the supermarket, wouldn't you have two functions (or a switch case) containing exactly the same code to calculate the quantity multiplied by the price of the groceries ? One would take a local shop as parameter, and the other one would take a supermarket.

Splitting the sale processing function in two parts - one summing up the groceries and the other one calculating the taxes - so that you can reuse the first function implies knowing in advance the existence of the supermarket structure (which you will only know many years after putting your product in production). Not doing it in advance either means duplicate code or refactoring every time you add an operation. The extension mindset initially comes from the need to avoid code duplication which is known to make maintenance difficult.

Now maybe the strongly-typed experience of FP and its compile-time checks are so convenient in practice that they make the maintenance of this kind of code easily manageable ? Maybe it's not even really duplicate code since what would be a basic number in OOP would be two different types here in FP ? Or maybe it's still thinking about FP from an OOP perspective ?

Very good example.

What goes through the sale function pipe is not the store and its size, it really does not matter for the meaning of sale were the sale happened. What matter for the sale is the cart. The cart might be more or less sofisticated because the size of the store, but is still a cart.

So the sale function is a pipe that eats a cart and spits out a receipt.

Or if you want to put it in another way, a sale is something that might happen to a cart over time. Functions are the clock on the system. In a functional system, times does not pass until a function is executed (does it sounds like lazy evaluation?)

In functional programming, we avoid duplication of code by appliying functions to the data so it spits what the next function needs. If you have a function sale that can eat a simple cart, but now you have a complex cart, one solution is to create a function that converts the complex cart into the simple one that the sale function needs; another way is to make the complex cart having the same data as the simpler cart. What you choose to do is proportional to how different the meaning of cart is, or maybe the cart remains the same. In general terms, this type of thinking tend to produce less lines of code needed per similar acomplishment.

So in OOP your are using objects to put together the store, while in FP your are descriving what happens in the store by connecting pipes betweem the different data. It is not about what can happen to the data, but what makes the data travel. It is not about what steps makes it work, but the fluidity of the data life span.

Many thanks jorgeleo ! I wasn't clear on how FP handles complexity management and the unknown. You've beautifully connected the dots and helped me shift my thinking, this is all clear now.

In particular your demonstration was very convincing from a DDD perspective. I can see that FP is not less natural than OOP for domain modelling while it approaches things from a very different angle. However FP brings to the table rich domain semantics, high correctness guarantees, and I feel productivity gains too. And with the mindset you've presented, it is also clear that the unknown seems to be accounted for in FP too. As an architect, this last point was the grey area and the deal breaker for me. However now I see no reason not to invest in heavily leveraging FP moving forward. Thanks again jorgeleo.