Hacker News new | past | comments | ask | show | jobs | submit login
Grokking Simplicity: Taming complex software with functional thinking (bagerbach.com)
154 points by jasim on April 30, 2023 | hide | past | favorite | 32 comments



I'm getting seriously pissed off with articles like this. There is inadequate discussion of the real cost...

> Okay, so let's address the elephant in the room: performance. Yes. Immutable data structures do use more memory, and they are slower to operate on. However, they are fast enough

...and are presented in a way that gives the impression to people with not enough experience that this kind of thing is "the future of programming". Which then gets parroted back on HN by people who can't justify it – it's something they've read and they're sure it's true.

The problem I'm complaining about is not functional programming or anything else, but a people problem. IME that's where the problem is in programming, and functional programming is just as prone to being abused as any other kind.

Functional programming is not "fast enough". It can be and usually is, in my personal project I'm quite happy to waste memory and thrash the TLB and cache and whatever else to get the job done, but in other cases it's not and that needs to be understood. I've seen a commercial project brought to its knees by going all-in on functional programming done badly (the aforementioned people problem).

I'm going to say this really loudly: don't absorb articles like this and spout them back. They provide easy solutions that are often correct but sometimes very incorrect where it matters, or completely ignore – yet again – the people problem.

I have a lot of experience and I keep reading on HN that "functional programming is the right way" or that "you don't do that in SQL" but these people with the strongest opinions seem least able to back up their claims.

Programming is fundamentally a people problem and that fundamentally is where I've seen most of the problems come from. Functional programming/object-oriented programming/procedural programming... These are all good in the right place. They can all be abused. They can all be combined. They all have costs and benefits. Don't write them off, And equally, don't treat them as 'the solution', because they are tools, and will only ever be tools to be used in the right place, and that takes judgement.

End of rant.


When you boil it down like that, then all problems in the world is a people problem. They can also be a systems problem, an incentives problem, and often a training/cultural problem. These framings are all valid, and have their place. But certain framings can help solve certain situations better.

In the narrow confines of programming, a way of thinking where we structure problems as transformation of data from one shape to another and minimizing mutable state can help systems be more robust. It is not an object-oriented vs functional programming debate. It is just a good practical way of approaching problem solving.

Unfortunately that is a very high-level description bordering on woo-woo. Which is why the book discusses these ideas with concrete code examples. For a lot of us who've hit a wall with the kind of reliable systems we could build, and discovering this new approach, it is an understanding borne out of lived experience. There is a lot of tacit knowledge here that's difficult to unpack and even more difficult to transfer to others. This book, like many others, helps, but cannot be a substitute for doing the actual work of experimenting, making mistakes, and internalizing.

But all of that is moot unless folks care about it, and care about it in the right way (like not going all in on functional programming and deep copying and immutable values where tight zero-memory-copy zero-alloc zero-kernel-call code was necessary), all of which finally makes it a people problem I guess?


> But all of that is moot unless folks care about it ... all of which finally makes it a people problem I guess?

Nailed it.


Did you realise that this article is the author's notes on someone's else's book? Have you read that book? Does either actually take the absolute positions you appear to be criticising here? I didn't get that sense from them personally - more that the book presents some ideas that come from the mindset of functional programming and can be useful elsewhere as well - but YMMV.


Think about the cost dynamic ("interpreted") languages incur. They are an order of magnitude or two slower than native code. Nevertheless, they are used all the time, for their simplicity of starting and flexibility.

Human time costs way more than CPU time.

I remember that it was proven that any algorithm on mutable data can be implemented on immutable data paying no more than O(log N) cost for that. It may be a very reasonable cost for all the benefits immutable data bring, like absence of data races, and general simplicity of operation which makes programmers' job way easier. The general thrust towards functional and immutable in the industry is not (just) fashion but real benefits in the speed and quality of writing the code. See how React, with its pretty purist functional and immutable approach, took the world of web dev by storm.


> Human time costs way more than CPU time.

Few mantras have done more to damage the quality of software world than this one, sorry to say.

In the realm of commercial software that is rarely true. The cost of writing more performant (and/or more memory efficient) code is amortized among all the users and all the time the code will ever run.

It might seem silly to the programmer to spend a week to reduce runtime of some operation by a second. But if that operation is run once a day by merely a million customers, it actually saves 278 hours per day collectively so it is totally worth it.

Let alone if it is code that runs multiple times per minute and there are billions of users.

And that's just wallclock time. If the code runs on mobile devices, more efficient code will lead to longer battery life. (And even on machines always on A/C power we should give a thought to wasting CPU which means wasted electricity with the associated environmental impact if it's code running at a large scale.) More memory efficient code leads to less memory pressure and a more responsive pleasant system to use. And so on.


Thank you for saying it for me. I keep reading it here and it's so frustrating I'm starting to give up trying to correct it.

Also @nine_k "...paying no more than O(log N) cost for that". Assuming this is true, and I've never heard of it, please consider by what metric that price is paid. In computing science terms things are usually given in numbers of operations but that's a terrible fit for modern CPUs.


I'm not sure about any, but a lot of the persistent data structures seem to fit within that limit, and it's what's used in FP languages like Clojure. There's also some compiler research of identifying when something won't be used anymore and simply doing the mutation in-place, which can reduce even further the costs incurred by immutability


Cost of addition: 1 cycle (I think).

Cost of a read or write to RAM: 150 to 200 cycles, and it gets worse from there if you have a TLB miss

It gets complex, but basically don't believe me or anything else you read without digging into it and asking why and what.


An extreme generalisation.

Only a small minority of software has enough users to justify that paradigm.


> Only a small minority of software has enough users to justify that paradigm.

You'd be surprised. Any legitimate commercial product (legitimate in the sense that it's trying to actually pay for it's costs and make a profit) is going to have thousands of users at a bare minimum.


Oh I agree.

Only, most software isn't customer facing commercial.


Functional versus imperative programming is a bit like socialism versus liberalism; the best solution is probably a combination of both.


If you like these notes, you should read the (very good) book:

https://www.manning.com/books/grokking-simplicity


I know this isn’t a very substantive comment, but I’d just like to second the recommendation! I really enjoyed the book too


Thirded. I also like Grokking Deep Reinforcement Learning a lot. OReilly's Grokking series is 2 for 2 for me. For those who don't know, OReilly stopped selling DRM free PDFs directly, but they still sell DRM free PDFs through other sources like ebooks.com, which I appreciate.


Grokking series is from Manning and do they sell PDF and ePub/mobi directly


You're right. I got mixed up. Manning has turned into a quality publisher as well IMO.


As a book reader, I always value recommendations, but you could choose to improve your comment by stating what made you like the book.


A good headline. It's important to remind that one should keep on improving their thinking to be a good engineer. All the techniques are secondary to the conceptual toolbox of your mind.


Among non-pure functions I can think of two interesting subclasses:

1. A functions with no side effects which (possibly) returns different values each time it's called, for instance a function which reads a global variable and returns its value

2. A function with side effects while running but which leaves the state of the program and its environment unaltered once it has returned, for instance a function which displays a dialog window and returns when the user clicks a button in it.

Are there any names for these classes of functions?


I think both #1 and #2 have side effects (interactions with external mutable state.)

1. The side effect here is an input, and affects the output value of the function.

2. The side effect here is an output (or "action"). Displaying a dialog window mutated something in the external state of the program.

Technically, I think "side effects" are undesired interactions. So #2 might just be an "effect" since it is presumably desired. So maybe:

1. Side effect

2. Effect


Thank you for sharing my notes!


I too find Reactive Programming appealing and have successfully used RxJS as you mention to build a fully reactive app - every action and data change can be observed and reacted to - its a fantastic library and it makes TS really powerful IMO (not to say other languages don't have this, just a powerful addition to an already versatile language).

With TS and RxJS I really like to do all the plumbing and housing a little more classically with some container classes that I call services who house and expose RxJS observables with an init() and a destroy() function where a service needs to manage its own subscriptions. So classes "services" group observables and there functionality, RxJS observables are the "plumbing" of the app, piping data around via events and then all the logic is in pure functions. I find programming like this leads to a clear data/event flow and neat seperation of concerns.


> & aims to avoid side effects by using pure functions

I think this has always been an incorrect framing. Functional programming does not _avoid_ side effects purposefully. It simply doesn't have them without explicitly modeling state, because it's based on math and logic which are stateless at their foundation. That's it.

We only bring up state because of how closely all of our languages are tied to stateful CPU designs - and for good reason btw, seeing as that's how all of our processors have been designed for all of the history of modern computing.

Said another way, functional programming doesn't try to do anything, it simply computes in a different way.


Imperative programming: write instructions for the computer to follow.

Functional Programming: model the instructions that you want the computer to follow.

Subtle difference. A model can be manipulated by other code in interesting ways.


> We only bring up state because of how closely all of our languages are tied to stateful CPU designs

I would rather say that we bring up state because almost all practical applications of computers have state to manage - to be honest, I can't think of many which don't have state.


It's strange. Most of the site displays fine on mobile except this link. I know we're not supposed to comment on it.

However, the left side of the readable content is truncated, so I do not know what word or words start each sentence.


Glad you did, thank you! Just pushed a fix. Should look fine on mobile now.


As a fun bit of trivia, the (book) author's brother is a well-known (and hilarious) stand up comedian.


That is how I exactly mastered Firefox and Chrome project code base ... from scratch.


How? Are you saying the Firefox and Chrome code bases are largely based on pure functions?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: