Hacker News new | ask | show | jobs
by rdnetto 3386 days ago
> I can almost guarantee that code was not written by an inexperienced or low skill coder. > If it was, you'd have a large complex function that took large complex state as its input, and probably maintained some kind of hidden internal state in some kind of async deferred loop after it returned or some combination of the above. > Have you worked with inexperienced FP programmers? > It's not fun.

No pure FP language will allow you to do that without the function's type signature reflecting that - it would need to return its value in some kind of state/async monad.

Now, if you're talking about FP in a traditionally OOP language, then I agree with you, but that's an apples to oranges comparison.

> Inexperienced OOP is a lot easier to deal with, because the entity level API validation is all you care about; you don't care about how hideously the internals were implemented as long as the tests pass. There can be any number of bugs and spaghetti inside the object, but you don't care, because you don't see it (until it manifests as bugs; but then you just add more tests and make them go away until all the tests pass).

This approach doesn't work for things that are difficult to test. e.g. you can only ensure your types are thread safe by reasoning about their use of locks, volatile, etc., because any attempt to test this is dependent on the implementation details of your runtime (e.g. the JVM) and the amount of load its under. Best case you get a flaky test, worst case you miss a bug that blows up in production.

But this is a tangent, because TDD is not specific to OOP - it works just as well with FP.

> but the point here is that someone has to define the module level interface, and how it behaves as a state machine (regardless of if the state comes in 'pure' and is passed around or is encapsulated internally); and that's OOP, not an inheritance hierarchy.

Pure state is an oxymoron. The idea is not that you pass a mutable argument in, but that you don't have the ability to mutate data at all. At best, you can return some instructions on how to mutate (e.g. the state monad), but its the consumer of your code who decides what to do with that, which prevents you from hiding side-effects, and simplifies testing.

Defining a module level interface and behaviour is just API design, not OOP.