[HN Gopher] Ideas from "A Philosophy of Software Design"
       ___________________________________________________________________
        
       Ideas from "A Philosophy of Software Design"
        
       Author : fagnerbrack
       Score  : 214 points
       Date   : 2024-12-18 23:03 UTC (3 days ago)
        
 (HTM) web link (www.16elt.com)
 (TXT) w3m dump (www.16elt.com)
        
       | noelwelsh wrote:
       | I come from an FP background, and this book was interesting to me
       | as the author very clearly has a very different (imperative,
       | systems) background. In some cases we have very different
       | opinions, in some cases I'm completely agreed (e.g. "define
       | errors out of existence" is extremely common in FP, usually under
       | the term "make illegal states unrepresentable"), and in other
       | cases I feel they were half-way to FP but couldn't quite get all
       | the way there (e.g. the editor example is a classic interpreter,
       | but they didn't make the connection IIRC.) I only skimmed the
       | book and would like to go back for a more detailed review.
       | Curious if anyone else with an FP background had the same or
       | different experience.
        
         | ninetyninenine wrote:
         | I thought the book was stupid. Rehashed a bunch of obvious
         | ideas. It's a bit harsh, I know, but that's my honest opinion
         | and I respect other people who like his book.
         | 
         | I too have a fp background and I felt the author is unqualified
         | to talk about complexity without knowing fp. Elimination of
         | procedures and mutations is a formal and concrete reduction of
         | complexity while the authors definition of complexity is hand
         | wavy. Someone should know about what fp is before writing a
         | book like this.
         | 
         | Why? Because fp is a basically like a formal structure for
         | software design and the author tried to talk about philosophy
         | without knowing some hard formal rules that are well known in
         | the industry. Not saying these rules are absolute but you can't
         | talk about design without talking about this.
         | 
         | The book talks about modularity and things of that nature too
         | and totally skips out on understanding the separation between
         | statefulness and logic. The author completely misses this
         | design concept of how how IO and mutation should be separated
         | from declarative operations. Imperative shell/functional core
         | is a central design philosophy that he doesn't touch upon. The
         | book is woefully incomplete without talking about this. Whether
         | the authors philosophy aligns with it is open for debate but
         | you can't talk about what he talks about without mentioning
         | this in a big way.
        
           | shinycode wrote:
           | Interested if you can give other books/resources on the
           | subject (not fp though)
        
             | ninetyninenine wrote:
             | Can't because fp is in itself basically a design philosophy
             | that can be explained in 3 axioms.
             | 
             | Segregate mutation from logic
             | 
             | Segregate IO from logic
             | 
             | Eliminate procedures from logic.
             | 
             | The third axiom is sort of for free as it falls out
             | automatically when someone enforces the first two. That's
             | basically imperative shell/functional core design
             | philosophy which is basically identical to the rules of
             | pure functional programming.
             | 
             | https://medium.com/ssense-tech/a-look-at-the-functional-
             | core...
             | 
             | With fp you can think of these rules enforced as a
             | language. Outside of fp we call it functional core /
             | imperative shell and these rules can be enforced in an
             | imperative language as a core design philosophy.
        
               | kfreds wrote:
               | Thank you. I found this comment illuminating. I too am
               | very interested to hear any book recommendations you have
               | on the topic.
               | 
               | What are your favorite books on software design,
               | functional programming, and/or computing generally? What
               | are your favorite papers on the topic of complexity (as
               | FP defines it)?
        
               | BoiledCabbage wrote:
               | "Domain Modeling Made Functional" is a great read and
               | sits next to a lot of these topics. Very easy to follow
               | and learn from even if you don't know (and never intend
               | to use) the language.
        
               | rramadass wrote:
               | I would like to echo the user kfreds sibling comment. I
               | don't have a FP background either and hence would very
               | much like to hear your recommendations on
               | books/videos/articles to understand FP and design the "FP
               | way".
        
               | analog31 wrote:
               | I also found this useful. I'm not a software developer,
               | but use programming for problem solving and prototyping.
               | Still, things that "look like software" sometimes leak
               | out of my lab. FP always set off my BS alarm, because in
               | my simplistic view, _the whole world has state_. But even
               | for my crude work, a sort of  "separation of powers"
               | helps clean up my programs a lot, and code that doesn't
               | _need_ to have side effects can be a lot cleaner if it 's
               | not mixed with code that does.
        
               | skydhash wrote:
               | FP does not deny state, it merely segregate it between
               | the before and the after, and everything that is in
               | between is transient. Then you combine all the individual
               | functions, piping them into each other and the whole
               | reflect the same structure. Then, it becomes easier to
               | reason about your logic as you only have two worry about
               | 2 states: the input and the result. No need to care about
               | individual transformations and ordering like you do in
               | imperative.
        
             | vendiddy wrote:
             | I disagree with the op and found the book to be very good.
             | If you haven't read it, I would recommend reading it and
             | judging for yourself.
        
           | UniverseHacker wrote:
           | If this is so stupid and obvious, why does apparently 99.99%
           | of software designed by professional engineers seem to be
           | designed by people completely oblivious to these ideas and
           | considerations?
           | 
           | Following these philosophical principles themselves- it seems
           | like a simpler and more accessible treatment of these ideas
           | would be vastly more effective then a more rigorous and
           | complete one- because the ideas are indeed simple.
        
             | ninetyninenine wrote:
             | > If this is so stupid and obvious, why does apparently
             | 99.99% of software designed by professional engineers seem
             | to be designed by people completely oblivious to these
             | ideas and considerations?
             | 
             | It's similar to why a big portion of the world believes in
             | Christianity and another portion believes in Buddhism.
             | Basically only one or none of these religions is correct
             | rendering at least one population of people believing in a
             | completely made up fantasy concept.
             | 
             | Much of what is preached in software is religion and what
             | is preached by the majority can be completely ludicrous.
             | The majority believing or not knowing something doesn't
             | mean anything.
        
               | UniverseHacker wrote:
               | Religious "truths" are not factual truths- they are
               | better thought of as psychological technology or
               | techniques, and are "true" if they work for the intended
               | purpose. Many conflicting religious "truths" are all
               | "true." Even calling them truths is only done to make the
               | religions accessible to people that can't mentally
               | process nuance, and the techniques only work for them if
               | labeled as truth. Intelligent religious scholars
               | understand this well- for example Mahayana and Vajrayana
               | Buddhism both teach nearly opposite and factually
               | incompatible perspectives on almost everything, yet are
               | often both used by the same religious teachers for
               | different pupils as appropriate.
               | 
               | The same is true for software design- an approach is not
               | literally true or false, but either works for its
               | intended purpose or does not. Conflicting philosophies
               | can both be "true" just with different underlying goals
               | or values.
               | 
               | To circle back here, my point is that this information is
               | presented in a simple way that will let people reading it
               | design better software. Saying they have no right to
               | present it without a much less accessible and more
               | complex framework that would likely make it less useful
               | to the intended audience does not make sense to me.
               | 
               | FWIW, I am also a functional programmer, but would love
               | to see people that are not follow some of these ideas.
        
               | drdeca wrote:
               | 1 Corinthians 15:13-19 (NIV) : " If there is no
               | resurrection of the dead, then not even Christ has been
               | raised. And if Christ has not been raised, our preaching
               | is useless and so is your faith. More than that, we are
               | then found to be false witnesses about God, for we have
               | testified about God that he raised Christ from the dead.
               | But he did not raise him if in fact the dead are not
               | raised. For if the dead are not raised, then Christ has
               | not been raised either. And if Christ has not been
               | raised, your faith is futile; you are still in your sins.
               | Then those also who have fallen asleep in Christ are
               | lost. If only for this life we have hope in Christ, we
               | are of all people most to be pitied."
               | 
               | ----
               | 
               | There is only one kind of truth. "All truths are God's
               | truths."
               | 
               | If Christianity is not true, then it is false. If
               | Christianity and Buddhism strictly contradict each-other,
               | then at most one of them is true.
               | 
               | Christianity is not meant to be a, what, psychological
               | trick? It makes claims, and these claims should be
               | believed if true and disbelieved if false.
        
               | UniverseHacker wrote:
               | It's no trick, it's a spiritual path that can't be
               | understood without following and practicing it- the path
               | very much leads to something real that cannot be
               | experienced or explained any other way. Everything
               | Christianity teaches is true in the sense that I mean
               | here. You are not understanding what I am saying and I do
               | not personally know how to explain it more clearly[1],
               | which, as I explained above, is why religions
               | pragmatically also offer this view you hold as the
               | official explanation to lay people, despite being obvious
               | nonsense as an objective truth to anyone that thinks very
               | hard about it.
               | 
               | I posit almost all intelligent monastics and religious
               | people are smart enough to tell the difference between
               | objective truth and religious truth- but it is taboo to
               | explain this to lay people as they will be confused and
               | think it means the religion is "fake" or a "trick",
               | however I don't feel the need to respect said taboo.
               | Perhaps I will learn to respect it by trying to explain
               | it to people unsuccessfully.
               | 
               | [1] David Chapman may be able to:
               | https://vividness.live/visionary-and-objective-truths
        
               | graemep wrote:
               | > I posit almost all intelligent monastics and religious
               | people are smart enough to tell the difference between
               | objective truth and religious truth- but it is taboo to
               | explain this to lay people as they will be confused and
               | think it means the religion is "fake" or a "trick",
               | however I don't feel the need to respect said taboo.
               | 
               | That is positing a conspiracy theory level of deception.
               | 
               | At least as far as Christianity goes, the "intelligent
               | monastics and religious people" write down their beliefs,
               | and have done so for millennia, and they read each others
               | writings. What you suggest might be possible with an oral
               | tradition, but not with a written one. Christianity is
               | very much concerned with objective truth, and one of the
               | distinguishing characters of it (and some other religions
               | too) is a belief that there is an objective truth.
        
               | UniverseHacker wrote:
               | It's no great conspiracy for a religion to have tiers of
               | understanding and nuance reserved for people more
               | intelligent and dedicated in practice- that is one key
               | purpose of having a distinction between lay people and
               | monastics. The mystique of this is openly part of the
               | draw for people to sign up for it.
               | 
               | There's no deception- it's something that (as this
               | discussion shows) is very subtle and dangerous to the
               | religions when misunderstood- but not dangerous when
               | understood correctly. It is written down repeatedly in
               | religious texts, in a subtle way with plausible
               | deniability, but clear to those that can read between the
               | lines. Writing in that way was the essential basic art of
               | any intellectual until very recently, it is only now
               | (sort of) safe to plainly state nuanced philosophical and
               | religious concepts without facing persecution. Nietzsche
               | argued you still should not do so even if you can.
               | 
               | It's also both quite obvious and relatively unimportant
               | on its own to people that would be capable of
               | understanding nuance, and could be quite harmful to the
               | faith and the stability of the religion of those not able
               | to understand.
        
               | graemep wrote:
               | > It is written down repeatedly in religious texts, in a
               | subtle way with plausible deniability, but clear to those
               | that can read between the lines.
               | 
               | Can you give me an example of what you mean? From
               | Christianity, as its the religion I know most about.
        
               | UniverseHacker wrote:
               | I'm not a scholar of Christian literature (or a
               | Christian), and I don't speak Latin, so it would hardly
               | be appropriate for me to pull out a specific quote and
               | insist "this is what they really meant." In truth, my
               | original source for this was my own understanding being
               | raised in a Christian church- and voicing this
               | perspective out loud in church as a young kid didn't go
               | over well, as you might imagine. To me as a young kid, it
               | was immediately obvious that there were deeper ethical
               | principles being explained in these stories, and one had
               | to be an idiot to be worried about if they were objective
               | factual details or not, when the point was clearly to
               | understand and embody the message- to practice and live
               | it. One was called to have faith that living these
               | principles wholeheartedly was the right thing to do and
               | would lead to real spiritual growth, not to have faith
               | that some particular guy built a particular boat- such
               | things are irrelevant.
               | 
               | However St. Augustine is someone that I am particularly
               | certain had a clear understanding of this, and I can see
               | it in how he frames most of his ideas.
               | 
               | Another example, would be that ancient religious texts
               | are not careful at all to avoid making numerous
               | objectively factual contradictions- as the anti-christian
               | crowd loves to point out over and over while also
               | completely missing the point. If the people writing them
               | thought that was important, they would have avoided doing
               | so- contrary to modern opinion, ancient theologians and
               | philosophers like St. Augustine were not idiots.
               | 
               | William Blake is a more modern person that, while just
               | about the furthest thing from a monastic, clearly had a
               | deep understanding of what I am talking about. Carl Jung
               | also extensively understood and discussed a lot of
               | esoteric things in Christianity including this, and wrote
               | about them in a relatively clear modern way.
        
               | graemep wrote:
               | > However St. Augustine is someone that I am particularly
               | certain had a clear understanding of this, and I can see
               | it in how he frames most of his ideas.
               | 
               | Can you give me an example of one?
               | 
               | > To me as a young kid, it was immediately obvious that
               | there were deeper ethical principles being explained in
               | these stories, and one had to be an idiot to be worried
               | about if they were objective factual details or not
               | 
               | Again, an example? You are suggesting for example that
               | there is no redemption or afterlife but they convey some
               | point?
               | 
               | > If the people writing them thought that was important,
               | they would have avoided doing so- contrary to modern
               | opinion, ancient theologians and philosophers like St.
               | Augustine were not idiots.
               | 
               | Does Augustine contradict himself? In a single work
               | (different views in different works could be a change of
               | mind)?
        
               | UniverseHacker wrote:
               | Look at Wikiquote for some of St Augustines most well
               | known quotes with what I am saying in mind- if you can't
               | see a dozen examples you're not going to agree with a
               | specific one I point out either. I am refusing to give a
               | specific example for a reason- you will almost certainly
               | disagree immediately with the specific example - because
               | they are written with an alternate interpretation
               | possible on purpose - and then think my whole premise
               | must be wrong as a result without looking at the bigger
               | picture, and seeing how often this plausibly deniable
               | concept keeps coming up.
               | 
               | > You are suggesting for example that there is no
               | redemption or afterlife
               | 
               | I am suggesting no such thing, only that dwelling on this
               | issue is to miss the point, and even worrying about it
               | would be an obstacle. One must deeply feel these ideas
               | and practice accordingly to follow this spiritual path-
               | even getting stuck on arguing that they are true would be
               | an obstacle to that.
        
               | UniverseHacker wrote:
               | I am curious where you are coming from- are you a
               | religious person that feels like my distinction between
               | religious and objective truth undermines your beliefs, or
               | are you a non-religious person that dislikes the idea
               | that religion may still have value, even if the beliefs
               | are not based on objective physical truth?
               | 
               | Myself, I would say I am non-religious, but have a lot of
               | respect for the purpose and value religions offers
               | people, and that one benefits greatly by understanding
               | and filling those roles and needs in other ways even if
               | not practicing a religion. I very much dislike the
               | Richard Dawkins follower crowd that hate religion with a
               | passion, but have no understanding of it, and have no
               | connection to or understanding of their own emotions,
               | unconscious, or spirituality to their own detriment.
        
               | roenxi wrote:
               | You might enjoy this comic:
               | 
               | https://www.smbc-comics.com/comic/2010-06-05
               | 
               | It makes a humourous and compelling argument that a big
               | part of Christianity is encouraging its adherents to
               | follow the game-theoretic optimum in a way that will
               | convince someone even if they are a bit credulous.
               | 
               | If you approach the bible with a good knowledge of
               | negotiation and game theory, a lot of it can be
               | interpreted in that light. There is a lot of good advice
               | to get people to move to the global optimums that can be
               | reached _if_ everyone cooperates. It isn 't subtle about
               | it. There is no conspiracy to hide that it is good advice
               | even to someone who doesn't particularly believe in
               | afterlives, miracles or god-given ethics. There is a very
               | neat division between the common read and the read of
               | someone with a good grasp of social dynamics, negotiation
               | and game theory. No conspiracies. Just a lot of people
               | who can't handle complex social negotiation.
        
               | graemep wrote:
               | Its hardly a new idea. One problem is that there is a lot
               | more to religion than ethics. It also assumes that
               | religious rules of behaviour are global optimums. It
               | fails to explain why religions spread too - why would
               | people believe in the religion that promotes cooperation,
               | rather than one another one? In fact, I would argue,
               | that, in the west, far more people are moralistic
               | therapeutic deists than Christians.
               | 
               | There is also a lack of evidence it works. I do not think
               | Christians are consistently greatly more socially
               | cooperative than atheists. Maybe more inclined to help
               | people on the fringes of society - e.g. running food
               | banks here in the UK, very active in poverty charities
               | globally but while good, I cannot believe it has a
               | sufficient consistent effect to provide an advantage to a
               | society that follows it.
               | 
               | Fear of hell as a motivator is limited to some Christian
               | denominations but is not often mentioned by other
               | denominations (I am mostly familiar with Catholic and
               | Anglican churches) or in the Bible, or Christian
               | writings, or in sermons or in religious discussions.
               | Christian universalists and others do not believe in any
               | form of hell at all!
               | 
               | It might work with a religion once established (religious
               | societies do better because of that cooperation) but it
               | does not explain how religions spread in the first place.
               | Its a lot more likely to apply to a religion that has
               | been long established in a relatively stable setting so
               | it is credible as an explanation of much of ancient
               | Jewish law that seems strange to us now (e.g. what to
               | eat, not plucking fruit from young trees etc) that often
               | seems off from a modern perspective.
        
               | Izkata wrote:
               | > so it is credible as an explanation of much of ancient
               | Jewish law that seems strange to us now (e.g. what to
               | eat, not plucking fruit from young trees etc) that often
               | seems off from a modern perspective.
               | 
               | One example theory I remember reading at some point was
               | the prohibition against eating shellfish: In the area the
               | religion arose, it would have most likely gone bad by the
               | time it was brought that far inland.
        
               | UniverseHacker wrote:
               | That seems like a very forced theory. By the time
               | shellfish is bad enough to present a health risk, it
               | smells, looks, and feels repugnant, one doesn't need a
               | religious system to know not to eat it.
               | 
               | Shellfish are susceptible to harmful algal blooms like
               | red tide, that can make them very dangerous.
               | 
               | Coastal foraging cultures that don't have bans on eating
               | shellfish, instead have complex knowledge about when,
               | where, and how to prepare and eat them. It's the same
               | with mushrooms- cultures either universally ban them, or
               | deeply educate everyone about them. All cultures globally
               | with access to these foods have a system here- it's not
               | unique to Judaism.
        
               | UniverseHacker wrote:
               | The comic isn't saying this is the main point of
               | religions, it's only saying it's one thing that happens
               | within religions. For example, religious communities have
               | their own social norms that are fundamental to the
               | religion, and allow for coordinated actions you don't see
               | elsewhere, like an Amish barn raising.
               | 
               | I take a Jungian view that a major useful thing religions
               | offer is a framework for relating to the unconscious. One
               | key part of that is to have a clear sense of ethics, and
               | to align ones actions with it, which is generally good
               | for your mental health.
        
               | graemep wrote:
               | There would definitely need to be many people who are are
               | deliberately deceitful. Those who both know how to "read
               | between the lines" and who clearly seek to persuade
               | others in the objective facts of Christianity.
               | 
               | Take CS Lewis as an example. He write strong and clear
               | defences of the incarnation, miracles etc. as objective
               | facts. He was either trying to deliberately deceive or he
               | did not actually understand older writing, and the latter
               | is not really credible given he was the professor of
               | mediaeval and renaissance literature at Oxford.
               | 
               | > The mystique of this is openly part of the draw for
               | people to sign up for it.
               | 
               | Not in my experience of priests, monks and nuns and
               | people who consider becoming clergy.
        
               | UniverseHacker wrote:
               | I haven't read any of CS Lewis's writing for adults, but
               | unfortunately, it is not at all unusual for academic
               | liberal arts scholars to have only a very shallow surface
               | understanding of the ideas in literature they formally
               | study.
               | 
               | Another possibility is that if you get what I'm saying
               | here, you might re-read CS Lewis and have a very
               | different perspective on what he was actually saying-
               | because those Christian "truths" are extremely important,
               | and exist for a good reason - and one can write a strong
               | clear defense of them from the perspective I am coming
               | from.
               | 
               | I read a lot of old philosophy and religious texts
               | translated and commented on by "well respected" scholars,
               | and it is not uncommon at all that I can tell they are
               | seeing only the surface of the ideas... which can make it
               | frustrating and difficult to read when the translator
               | wasn't 'getting it.' The level one needs to be at to be a
               | well respected philosopher, and just to succeed as an
               | academic are not close at all, and there is no guarantee
               | that the latter will be capable of fully grasping the
               | ideas of the former - it is probably the norm that they
               | cannot. If they could they would not be just a translator
               | or scholar, but a powerful philosopher in their own
               | right.
               | 
               | An intelligent person whose mind is fundamentally
               | oriented towards communicating deeper meaning, does not
               | operate on the level of obsessing over banal binary
               | verification of facts- and they need to be able to assume
               | their reader is already capable of thinking abstractly in
               | this way as well. To put it simply one must assume
               | intelligence in the reader to communicate deep ideas and
               | meaning, and neglecting to "explain how to be
               | intelligent" is not deception- when it is not even
               | something that can be explained.
        
               | bccdee wrote:
               | > If Christianity is not true, then it is false.
               | 
               | It might be better to think of it as a potentially useful
               | fiction. Our culture is full of those.
               | 
               | Morality doesn't exist in any objective sense, which
               | means "murder is wrong" is not, strictly speaking,
               | _true._ That doesn 't mean it isn't useful for us to
               | collectively treat it as if it's true. You might even
               | argue that that's the nature of all shared truth.
        
               | AnimalMuppet wrote:
               | The passage drdeca quoted _explicitly_ denies you the
               | space to treat Christianity as a  "useful fiction". (I
               | mean, lots of people _do_ , but they have to ignore what
               | it _actually teaches_ in order to do so. You have to
               | create a fictionalized version if you want a useful
               | fiction, which I guess shouldn 't surprise me...)
        
               | musicale wrote:
               | Good explanation, really. Imperative systems programmers
               | reject one or more of the fp commandments (perhaps
               | finding them impractical), and are probably heretics in
               | the eyes of the fp cult.
        
               | graemep wrote:
               | > It's similar to why a big portion of the world believes
               | in Christianity and another portion believes in Buddhism.
               | Basically only one or none of these religions is correct
               | rendering at least one population of people believing in
               | a completely made up fantasy concept.
               | 
               | You have picked religions with as little as possible in
               | common. It would be rather different if you had picked
               | any two monotheistic religions for example: one could be
               | entirely right, and that would mean the other was
               | partially or mostly right.. Despite your choice, there
               | are many things in common: a path to redemption,
               | monasticism, wealth being a barrier to redemption,
               | meditation and mysticism... its quite possible those
               | common elements might be right.
               | 
               | The same with software. Some things that are widely
               | believed may be true and other false.
        
               | vouwfietsman wrote:
               | No, its not similar at all.
               | 
               | Parent is telling you: "if A is so simple and obvious,
               | why does nobody do A", your counter argument: "if many
               | people believe A it does not mean it is true". This is
               | entirely unrelated, the point is that these things are
               | NOT obvious to the average programmer, he/she would
               | benefit from learning this, and claiming that these
               | things are broadly "stupid and obvious" is petty and
               | false.
               | 
               | Also, the things you're saying just don't add up with
               | your criticism that the author is _missing_ some
               | fundamental part of software philosophy. If the author is
               | only _missing_ something, then it still makes sense for
               | the majority to learn the things he _is_ saying, at
               | least, as explained by your parent.
               | 
               | Finally, if anything can be compared to religion, it
               | surely is the evangelism of functional programming
               | zealots.
        
               | Mikhail_Edoshin wrote:
               | Well, there is a parable of seven blind men who met an
               | elephant, touched different parts of it and later
               | described the animal in wildly different terms. Listening
               | ot these different tales can we say that only one of
               | these men is right and all others are wrong? Or maybe all
               | are wrong? Or all are right? Also, do contradictions in
               | their tales mean that the elephant does not exist?
        
             | markgoho wrote:
             | sturgeon's law
             | 
             | also, just because someone writes poor code doesn't mean
             | they don't know how to write good code - intent isn't
             | always clear, and it's a mistake to assume ignorance based
             | only on the output
        
           | musicale wrote:
           | > Someone should know about what fp is before writing a book
           | like this.
           | 
           | 1. Are you quite sure John Ousterhout (who invented Tcl[1],
           | comparing it to Lisp in section 7 of the original paper)
           | doesn't "know about what fp is" as you say?
           | 
           | 2. Do you think that the main reason functional programming
           | hasn't taken off in systems programming is that practitioners
           | are ignorant, or do you think there might be issues with fp
           | systems that prevent its adoption?
           | 
           | [1] https://web.stanford.edu/~ouster/cgi-bin/papers/tcl-
           | usenix.p...
        
             | ninetyninenine wrote:
             | The book needs to talk about those issues and trade offs.
             | 
             | Fp with lisp is only a fraction of fp. I of course am
             | talking more along the lines of pure fp which lisp is not.
        
               | musicale wrote:
               | Sure, fp in Lisp might not always be true (scotsman) fp.
               | ;-)
               | 
               | But omitting fp in the book is not evidence that
               | Ousterhout is ignorant of fp, and there is certainly
               | evidence to the contrary.
               | 
               | The likely explanation, given that he's developed a
               | number of systems from Sprite to Tcl/Tk to RAMCloud to
               | HOMA, is that he is addressing the current practice of
               | systems programming, which remains primarily imperative.
        
           | vendiddy wrote:
           | I too write FP code but I found this book very valuable in
           | how he treats complexity and his concept of "deep modules".
           | 
           | I acknowledge that he does not cover purity and mutations as
           | a source of complexity (and they are big sources of
           | complexity) but I don't think that merits dismissing the
           | entire book on those grounds.
        
             | ninetyninenine wrote:
             | I'm not dismissing the entire book. It has merit in what it
             | mentions but it's missing core foundational concepts.
             | 
             | Because it misses these concepts the book isn't good in my
             | opinion.
        
               | WillAdams wrote:
               | In what ways could these concepts be discussed in the
               | structure of the book in terms of currently prevalent
               | programming practices?
        
           | kfreds wrote:
           | The book plainly states that it is a philosophy for software
           | design. Philosophy in this context is closely related to
           | strategy, which is the art of reducing reality to heuristics,
           | so that we might easier figure out how to reach our goals in
           | a complex environment.
           | 
           | If the book had been titled "Formal methods for software
           | design" the lack of algorithms for reducing complexity would
           | have been surprising. As it is about philosophy it should not
           | be surprising that it focuses on heuristics.
        
             | ninetyninenine wrote:
             | Applying formal methods derived from functional programming
             | is a design heuristic.
             | 
             | It's a core heuristic and philosophy that is foundational
             | in my opinion. The author failing to mention this makes the
             | book missing a fundamental issue central to software
             | design.
        
               | kfreds wrote:
               | Well put. This comment makes your criticism of the book
               | much more clear to me at least.
               | 
               | I agree with you that the separation of Church and state
               | is a foundational idea of software design and even
               | computing generally. I find it quite beautiful how it
               | manifests in hardware as the two categories of digital
               | logic - combinatorial and sequential. And if we zoom in
               | on the logical expression of memory we see it again - a
               | latch is simply two feedback loops and some combinational
               | logic.
               | 
               | For what it's worth I thought the book was brilliant. Its
               | ideas weren't all obvious to me before I read it. It also
               | inspired me to read Parnas, Wirth, Hoare, and study the
               | Go runtime and compiler.
               | 
               | What should be obvious is this: the fact that the ideas
               | were obvious to you doesn't mean they are obvious to
               | everyone.
               | 
               | Secondly, complexity has many meanings. Managing
               | complexity is incredibly important in the realm of
               | security. I've been dabbling in security for 25 years,
               | but I would certainly not claim to have a deep
               | understanding of functional programming. Nevertheless I
               | understand complexity quite well. I think that's what
               | bothered me the most about your original comment - the
               | idea that people without a background in FP are
               | unqualified to talk about complexity.
        
               | mrkeen wrote:
               | > I would certainly not claim to have a deep
               | understanding of functional programming.
               | 
               | From a philosophy-of-complexity perspective it's not
               | needed, all you need to ask is: will my code give the
               | same output given the same input? (And if not, there's
               | your complexity!)
               | 
               | Of course, this is a _big ask_ of a programmer. Leaving
               | determinism up to the programmer in an imperative setting
               | is like leaving memory-safety up to the programmer in a C
               | setting.
        
           | rubiquity wrote:
           | FP weenies gone wild 2024. You design web apps with monads.
           | Ousterhout has made systems of actual consequence where
           | mutation is a reality not a fantasy you try to pretend
           | doesn't exist.
        
         | Darmani wrote:
         | "Define errors out of existence" might sound like "make illegal
         | states unrepresentable," it's actually not. Instead it's a
         | pastiche of ideas rather foreign to most FP readers, such as
         | broadening the space of valid inputs of a function. One of his
         | examples is changing the substr function to accept out of
         | bounds ranges.
         | 
         | You might be interested in my review. I'm a Haskeller at heart,
         | although the review draws more from my formal methods
         | background. Spoiler: his main example of a deep module is
         | actually shallow.
         | 
         | https://www.pathsensitive.com/2018/10/book-review-philosophy...
        
           | alpinisme wrote:
           | I haven't looked at the substr function but is that not
           | similar to how you can `take 5 [1,2,3]` or `zip [1,2,3] ['a',
           | 'b', 'c', 'd']`
        
           | musicale wrote:
           | Nice and seemingly balanced review.
           | 
           | Defining errors out of existence should be mandatory for all
           | golang programs.
        
             | fuzztester wrote:
             | err, are you serious, sir?
        
           | hyperpape wrote:
           | Does Ousterhout actually say modules must always have a
           | longer implementation than their spec, or just that this is a
           | generally desirable feature?
           | 
           | If he did, I agree with you, he was wrong about that. I also
           | agree that the unix file API is probably not a good example.
           | 
           | But whether or not he did, I think the dissection of edge
           | cases would be better off emphasizing that he's got something
           | importantly right that goes against the typical "small
           | modules" dogma. All else being equal, deeper modules are good
           | --making too many overly small modules creates excessive
           | integration points and reduces the advantages of modularity.
           | 
           | P.S. While I'm here, this is not really in response to the
           | parent post, but the example in the article really does not
           | do justice to Ousterhout's idea. While he does advocate
           | sometimes just inlining code and criticizes the pervasive
           | idea that you should shorten any method of more than n lines,
           | the idea of deep modules involves more than just inlinining
           | code.
        
             | lgas wrote:
             | > Does Ousterhout actually say modules must always have a
             | longer implementation than their spec, or just that this is
             | a generally desirable feature?
             | 
             | I mean the spec is a lower bound on the size of the
             | solution, right? Because if the solution were shorter than
             | the spec, you could just use the solution as the new
             | shorter spec.
        
               | Darmani wrote:
               | Not necessarily. The implementation is very often more
               | defined than the specific. If the implementation is the
               | spec, then it means that even the smallest change in
               | behavior may break callers.
        
             | Darmani wrote:
             | I'd say he's in between -- he strongly recommends that most
             | modules be "deep."
             | 
             | I agree that blindly making lots of tiny things is bad, but
             | his criteria for how to chunk modules is flawed.
        
           | philosopher1234 wrote:
           | Your review is great! But I think the idea that it's in
           | opposition to PoSD is not right, I think it's a further
           | development and elaboration in the same direction of PoSD
        
             | Darmani wrote:
             | My review has a bit of a negative vibe, but when when I
             | look through my paper copy of PoSD, the margins are full of
             | comments like "Yes!" and "Well said."
        
           | noelwelsh wrote:
           | Nice review. It reminded me of some of the WTF moments from
           | the book :-) I should go back to it and write my own.
        
           | Mawr wrote:
           | > his main example of a deep module is actually shallow.
           | 
           | It's not, you're just ignoring what he said:
           | 
           | "A modern implementation of the Unix I/O interface requires
           | hundreds of thousands of lines of code, which address complex
           | issues such as: [... 7 bullet points ...] All these issues,
           | and many more, are handled by the Unix file system
           | implementation; they are invisible to programmers who invoke
           | the system calls."
           | 
           | So sure, the `open` interface is big in isolation but when
           | compared to its implementation it's tiny, which is what
           | you've badly missed.
           | 
           | The book also brings up another example right after this one,
           | that of a Garbage Collector: "This module has no interface at
           | all; it works invisibly behind the scenes to reclaim unused
           | memory. [...] The implementation of a garbage collector is
           | quite complex, but the complexity is hidden from programmers
           | using the language". Cherry picking, cherry picking.
           | 
           | Then you proceed to not mention all the other key insights
           | the book talks about and make up your own example of a stack
           | data structure not being a deep abstraction. Yes, it's not.
           | So? The book specifically emphasizes not applying its advice
           | indiscriminately to every single problem; almost every
           | chapter has a "Taking it too far" section that shows
           | counterexamples.
           | 
           | Just so you don't attempt to muddy the waters here by
           | claiming that to be a cop-out, the very point of such books
           | is provide advice that applies in general, in most cases, for
           | 80% of the scenarios. That is very much true for this book.
           | 
           | Overall, your formal background betrays you. Your POV is too
           | mechanical, attempting to fit the book's practical advice
           | into some sort of a rigid academic formula. Real world
           | problems are too complex for such a simplified rigid
           | framework.
           | 
           | Indeed, a big reason why the book is so outstanding is how
           | wonderfully practical it is _despite_ John Ousterhout 's
           | strong academical background. He's exceptional in his ability
           | to bring his more formal insights into the realm of real
           | world engineering. A breath of fresh air.
        
             | Darmani wrote:
             | Hi Mawr,
             | 
             | I don't have much to say to most of your comment --- a lot
             | of the text reads to me like a rather uncharitable
             | description of the pedagogical intent of most of my
             | writing.
             | 
             | I'll just respond to the part about deep modules, which
             | brings up two interesting lessons.
             | 
             | First, you really can't describe an implementation of the
             | Unix IO interface as being hundreds of thousands of lines.
             | 
             | That's because most of those lines serve many purposes.
             | 
             | Say you're a McDonalds accountant, and you need to compute
             | how much a Big Mac costs. There's the marginal ingredients
             | and labor. But then there's everything else: real estate,
             | inventory, and marketing. You can say that 4 cents of the
             | cost of every menu item went to running a recent ad
             | campaign. But you can also say: that ad was about Chicken
             | McNuggets, so we should say 30 cents of the cost of Chicken
             | McNuggets went to that ad campaign, and 0 cents of
             | everything else. Congratulations! You've just made Big Macs
             | more profitable.
             | 
             | That's the classic problem of the field of cost accounting,
             | which teaches that profit is a fictional number for any
             | firm that has more than one product. The objective number
             | is contribution, which only considers the marginal cost
             | specific to a single product.
             | 
             | Deciding how many lines a certain feature takes is an
             | isomorphic problem. Crediting the entire complexity of the
             | file system implementation to its POSIX bindings --
             | actually, a fraction of the POSIX bindings affected by the
             | filesystem -- is similar to deciding that the entire
             | marketing, real estate, and logistics budgets of McDonalds
             | are a cost of Chicken McNuggets but not of Big Macs. There
             | is a lot of code there, but, as in cost accounting, there
             | is no definitive way to decide how much to credit to any
             | specific feature.
             | 
             | All you can objectively discuss is the contribution, i.e.:
             | the marginal code needed to support a single function. I
             | confess that I have not calculated the contribution of any
             | implementation of open() other than the model in SibylFS.
             | But Ousterhout will need to do so in order to say that the
             | POSIX file API is as deep as he claims.
             | 
             | Second, it's not at all true that a garbage collector has
             | no interface. GCs actually have a massive interface. The
             | confusion here stems from a different source.
             | 
             | Programmers of memory-managed languages do not use the GC.
             | They use a system that uses the GC. Ousterhout's claim is
             | similar to saying that renaming a file has no interface,
             | because the user of Mac's Finder app does not need to write
             | any code to do so. You can at best ask: what interface does
             | the system provide to the end-user for accessing some
             | functionality? For Finder, it would be the keybindings and
             | UI to rename a file. For a memory-managed language, it's
             | everything the programmer can do that affects memory usage
             | (variable allocations, scoping, ability to return a heap-
             | allocated object from a function, etc), as well as forms of
             | direct access such as finalizers and weak references. If
             | you want to optimize memory usage in a memory-managed
             | language, you have a lot to think about. That's the
             | interface to the end user.
             | 
             | If you want to look at the actual interface of a GC, you
             | need to look at the runtime implementation, and how the
             | rest of the runtime interfaces with the GC. And it's
             | massive -- GC is a cross-cutting concern that influences a
             | very large portion of the runtime code. It's been a while
             | since I've worked with the internals of any modern runtime,
             | but, off the top of my head, the compiler needs to emit
             | write barriers and code that traps when the GC is
             | executing, while the runtime needs to use indirection for
             | many pointer accesses (if it's a moving GC). Heck, any user
             | of the JNI needs to interface indirectly with the GC. It's
             | the reason JNI code uses a special type to reference Java
             | objects instead of an ordinary pointer.
             | 
             | If you tally up the lines needed to implement either the GC
             | or the POSIX file API vs. a full spec of its guaranteed
             | behavior, you may very well find the implementation is
             | longer. But it's far from as simple a matter as Ousterhout
             | claims.
        
           | Dansvidania wrote:
           | the example you quote for "Define errors out of existence",
           | while indeed it does not follow "make illegal states
           | unrepresentative" does follow what IMO also is an FP
           | principle: "a total function is better than a partial one"
        
         | zusammen wrote:
         | I read a few chapters and had the same feeling.
        
         | 0xDEAFBEAD wrote:
         | I read most of the book a couple years ago, and I thought it
         | was very good. I wonder if you (or anyone else) can recommend
         | an alternative book that does a better job of describing your
         | perspective?
        
       | vkazanov wrote:
       | In the oop age of arch I felt like I had no mouth (and I had to
       | scream).
       | 
       | This book, as well as the data oriented design approach, is what
       | made things right for me.
        
       | onemoresoop wrote:
       | I love this website's format, it seems very pleasant to read.
        
         | asimpletune wrote:
         | I came here to say the same. Having the navigation on the
         | bottom is great too, with it appearing when you scroll up.
         | Kudos to the owner.
        
           | amenghra wrote:
           | It's not great when it conflicts with the system's default
           | behavior :/
           | 
           | My screen recording: https://streamable.com/gvz68h
        
       | WillAdams wrote:
       | Agreed.
       | 
       | I read this book recently, one chapter at a time, and after each,
       | reviewed the code for my current project, applying the principles
       | to it in a re-write --- it helped a lot.
       | 
       | Highly recommended.
        
       | bvrmn wrote:
       | Sadly article's author doesn't touch the main idea of the book:
       | component's public API should be narrow as possible. John makes a
       | great deal of that with concrete examples.
        
         | ilrwbwrkhv wrote:
         | This. That is the biggest idea and also the most applicable and
         | the easiest to understand when your complexity is going through
         | the roof.
         | 
         | For example in Ruby land it is very common to make a class and
         | then make a lot of small tiny methods which are one liners or
         | two liners.
         | 
         | I had asked him directly about this and his answer was to avoid
         | doing it.
         | 
         | Since then my Ruby and Common Lisp code has become much better.
         | 
         | I have since moved to rust, but the point still applies.
        
           | theonething wrote:
           | > make a lot of small tiny methods which are one liners or
           | two liners.
           | 
           | I'm presuming you mean _public_ tiny methods? Having private
           | ones like that can be good if makes sense to do so
           | (encapsulates logic, increases readability, etc)
        
             | ilrwbwrkhv wrote:
             | Yes public "deep" methods. But even private methods I have
             | been more conservative.
             | 
             | It is after all an API for you!
             | 
             | Basically the idea that you shouldn't have long methods is
             | something I don't believe in anymore. Even Carmack made a
             | similar point: http://number-
             | none.com/blow/blog/programming/2014/09/26/carm...
        
               | lll-o-lll wrote:
               | I _never_ believed this, even when I was compelled to do
               | it.
               | 
               | What are we achieving in these plethora of small methods?
               | There are many potential negative patterns that
               | eventuate.
               | 
               | - Lifting variables into "global" (object) state. In more
               | complex classes, it's often hard to even identify that
               | this has happened. Is this permanent object state, or
               | just an internal temporary variable that made it easier
               | to leap around methods?
               | 
               | - Making code harder to change as variables must be
               | lifted into method parameters (so changing a variable, or
               | adding a new one leads to multiple modifications).
               | Method1 calls Method2 calls Method3 with a "dependency"
               | that Method2 never needs.
               | 
               | - Poor naming leading to obtuse code. DoThingPart1,
               | DoThingPart2
               | 
               | - Harder to follow code by having to jump around the file
               | (or worse, multiple files).
               | 
               | There are better and worse ways to structure code to make
               | it easier to read and reason about, however blind metric
               | approaches are not the way.
        
               | nyrikki wrote:
               | I don't remember anything about lifting state up in the
               | clean series, was it perhaps a react specific book?
               | 
               | To me that would violate the dependency inversion
               | principle that most of the books leverage heavily.
               | 
               | I know that some languages like .net encourage those
               | Singleton classes, but I would appreciate being pointed
               | at where the clean series sells this.
               | 
               | I am of the bounded context camp for component sizing in
               | general so it is likely I skimmed and dumped the concept,
               | like I did with the over reliance on polymorphisms, which
               | is a sometimes food in my mind.
        
               | whstl wrote:
               | To quote from Clean Code:
               | 
               |  _" The function is a bit too long and the variables are
               | used throughout. To split the function into smaller
               | pieces we need to create a GuessStatisticsMessage class
               | and make the three variables fields of this class."_ -
               | Add Meaningful Context, Page 28
               | 
               | EDIT: And then right below there's an example where the
               | author _lifts variables into object state_.
               | 
               | EDIT 2: Funny enough, ChatGPT managed to refactor to
               | something even much shorter and IMO much clearer than
               | both examples in the book:                   private void
               | printGuessStatistics(char candidate, int count) {
               | if (count == 0) {                 print("There are no " +
               | candidate + "s");             } else if (count == 1) {
               | print("There is 1 " + candidate);             } else {
               | print("There are " + count + " " + candidate + "s");
               | }         }
        
               | nyrikki wrote:
               | Thank you for doing the work to find that for me.
               | 
               | I still don't see that as:
               | 
               | > "Lifting variables into "global" (object) state"
               | 
               | It is simply the inversion and extraction method that is
               | commonly used. The value of it is lost here as his
               | example is poor IMHO as I find that cleaning up deep
               | nested arrow code is where it is.
               | 
               | This method on page 28 is about refactoring to improve
               | readability, and the location where the variables are
               | declared are still in the same class.
               | 
               | Nothing has changed in that example except adding named
               | private methods in place of logic inside an if-elif-else
               | ladder.
               | 
               | So this:                   if (count == 0) {
               | number = "no";            verb = "are";
               | pluralModifier = "s";            }          else if
               | (count == 1) {            number = "1";            verb =
               | "is";            pluralModifier = "";            }
               | else {            number = Integer.toString(count);
               | verb = "are";            pluralModifier = "s";
               | }
               | 
               | Is changed to this:                   if (count == 0) {
               | thereAreNoLetters();            }         else if (count
               | == 1) {            thereIsOneLetter();            }
               | else {            thereAreManyLetters(count);
               | }
               | 
               | Remember this chapter is about "name things" not flow
               | control or even data flow.
               | 
               | It actually is intended to help with most of the concerns
               | above and has nothing to do with the react style anti-
               | parameter drilling style of 'lifting'
               | 
               | If you go to page 97 he goes over the 'The Law of
               | Demeter' and argues against exactly what was above and
               | actually cites Martin Fowlers refactoring book which is
               | written in a far better style and tries to call out
               | nuance.
               | 
               | So my opinion that he gives semi-helpful advice that he
               | over sells as received wisdom still holds. Obviously the
               | cost of calling a private method in your language and how
               | that impacts your use case matter here.
        
               | whstl wrote:
               | _> This method on page 28 is about refactoring to improve
               | readability, and the location where the variables are
               | declared are still in the same class._
               | 
               | Same class, but method-scope local variables were
               | unnecessary turned into long-lived instance variables.
               | This is what GP means by _" Lifting variables into
               | "global" (object) state"_. Their phrasing, not mine.
               | 
               | This unnecessary usage of _state_ for what could be a
               | simple variable binding is what GP is criticizing, and
               | they 're arguing that is problematic for maintenance and
               | readability. I agree with them.
        
               | nyrikki wrote:
               | Original (labeled bad by the book):
               | private void printGuessStatistics(char candidate, int
               | count) {            String number;            String
               | verb;            String pluralModifier;
               | 
               | Modified version:                   public class
               | GuessStatisticsMessage {            private String
               | number;            private String verb;
               | private String pluralModifier;
               | 
               | Once again, it was presented in the context of naming
               | things....not object or data structures.
               | 
               | Often one has to resort to spherical cows to explain
               | things.
        
               | nyrikki wrote:
               | Ya looking into this more this is a react hyper
               | correction to the Law of Demeter, related to language
               | limits vs broad concepts.
               | 
               | Not being a UI guy, I am not the one to say how universal
               | this is, but the react context API seems to use stamp
               | coupling and has to propagate those changes globally and
               | is expensive.
               | 
               | Good example of where context is King with tradeoffs.
        
       | recroad wrote:
       | Here's a recent interview with the author
       | https://youtu.be/bopwQ_YV06g?si=S2YOVbXj3MJ2NlEG
        
       | sarchertech wrote:
       | It's a great book. I feel like a lot of the midlevel engineers
       | I've worked with over the years who read clean code and stopped
       | there would benefit greatly from it.
        
       | ricardobeat wrote:
       | While I heartily agree with limiting complexity as a ground rule,
       | the example given is not a great one.
       | 
       | First, it's more about repetition/poor design than complexity.
       | Second, creating a separate service class for applying a discount
       | is _adding_ unnecessary complexity. You'll end up with a pile of
       | _DiscountService_ , _TaxService_ , _ShippingCostsService_ , and
       | so on, and they will be sewn together like patchwork. It seems to
       | be a common pattern in Java but surely there are better ways?
        
         | marcosdumay wrote:
         | > You'll end up with a pile of DiscountService, TaxService,
         | ShippingCostsService, and so on
         | 
         | This seems reasonable. If you get a lot of complexity on each
         | one of those, and their behavior is controlled by different
         | areas of your business, there's nothing bad in segregating
         | them.
        
       | indoorcomic wrote:
       | I disagree with the examples in the second idea. The "bad"
       | example is easier to understand and maintain at a glance in my
       | opinion. Looking at the RegisterUser method, I can immediately
       | see the steps it takes to register a user, whereas the "good"
       | example I have to think about it a bit more. Of course, this is a
       | simple example so not much thinking needs to be done, but in a
       | more realistic application I think this would hold much more
       | truth. In projects I've worked on I've seen methods get
       | incredibly bloated due to this. I certainly do agree that
       | "splitting things up for the sake of splitting them up" can be
       | bad practice, I'm just not sure this is the best example to
       | demonstrate that.
        
         | estevaoam wrote:
         | I agree. The main function of a component should describe what
         | it does, similar to describing the algorithm in natural
         | language. I have been following this pattern with success. It
         | is much easier to understand things at a glance.
        
       | galaxyLogic wrote:
       | "The idea behind exception aggregation is to handle many
       | exceptions with a single piece of code; rather than writing
       | distinct handlers for many individual exceptions, handle them all
       | in one place with a single handler."
       | 
       | This seems similar to how events are handled in a web-browser.
       | Each element can handle its own event-handlers. But equally well
       | there can be a single event-handler for each event-type in a
       | containing element, perhaps at the top-level only.
       | 
       | If you define event-handlers of a given type for all DOM-elements
       | of the page in a single location it becomes much more flexible to
       | modify how and which events are handled and for which DOM-
       | elements.
       | 
       | So we could say that "error" is just one of the event-types,
       | errors can be or could be handled by the same mechanism as events
       | in general are. Right? Or is there clear categorical difference
       | between error-events and other types of events?
        
       | NomDePlum wrote:
       | A similar article discussing the same book:
       | https://blog.pragmaticengineer.com/a-philosophy-of-software-...
        
       | suzzer99 wrote:
       | Something bugs me about that first example. We started with two
       | classes that had trivial constructors, and changed them into
       | classes that require an instance of DiscountService be supplied
       | to a constructor. That doesn't feel like less complexity to me.
       | 
       | I'd probably just make applyDiscount a static utility method that
       | the two classes import and invoke on their own, at least until it
       | becomes obvious that something more involved is needed.
        
         | exoji2e wrote:
         | Yes, and also it's weird to get a negative shipping cost (-5)
         | for US and code SUMMER2024. Typically you would only apply the
         | discount code once and not both to shipping and the total order
         | value.
        
           | suzzer99 wrote:
           | So next, they realize they need a different calculation for
           | shipping, and now their beautiful abstraction has a big _if
           | isShipping() {...} else {...}_ block. So much for reducing
           | complexity.
           | 
           | Sometimes it's best to let two identical blocks of code
           | remain intact if there's a reasonable chance that their logic
           | may diverge in the future. If they don't diverge, and you
           | find yourself constantly updating both, then you can factor
           | it out into shared code. It's usually much easier to create a
           | new layer of abstraction in the future, than to remove an
           | unneeded one after a ton of code has grown up around it.
           | 
           | I'm a big fan of WET - write everything twice (stolen from
           | HackerNews), then maybe the third time think about
           | refactoring into shared code, especially in new apps where
           | you don't know how things are going to involve.
        
         | quest88 wrote:
         | Can you articulate what this feels less complex? The author did
         | a good job articulating the complexity with the trivial
         | example.
         | 
         | One benefit I like in the author's example, vs a static utility
         | method, is you don't need to concern yourself about the
         | implementation when it comes to tests.
         | 
         | Let's consider your example. The CheckoutService needs to call
         | applyDiscount. So how do we get a discount to be applied? Well,
         | we need to look at the source code of the static function to
         | see that the order needs a CouponCode of "SUMMER2024". We may
         | also need to see how much the order is discounted by so we can
         | assert on the correct total value in the tests (or we can
         | simple assert the total is less than the total we started
         | with). That means that anytime we update the CouponCode (e.g.
         | "WINTER2024") then we have to update a bunch of tests.
         | 
         | Now let's consider the example's change. I see that the
         | constructor takes some DiscountService interface. So now I can
         | create a fake implementation that's used in the tests. I don't
         | need to dig into implementation code to see how to trigger a
         | discount. I can create that fake implementation in the test
         | itself so I can provide exactly how much discount will be
         | applied and the test can assert that the total is discounted by
         | the amount specified in the test itself, now we can see it's
         | definitely being applied! Or I can create a
         | FiftyPercentDiscountFake for all other tests to use.
         | 
         | The example is trivial of course and you likely don't need such
         | an abstraction for trivial services. After all, this is for
         | example purposes. But as code becomes less trivial or many
         | teams are repeating the same thing if you're at a large enough
         | company, then this a tool in our toolbelt to use to manage the
         | complexity.
        
       | abcde777666 wrote:
       | A lot of these types of books and posts only deal with the low
       | hanging fruits of software design difficulty, such as the
       | provided discount service example.
       | 
       | The trouble is that kind of thing's pretty much software
       | development common sense - only the inexperienced don't know it.
       | 
       | The true difficulties of software development are often must
       | gnarlier in my experience.
       | 
       | For instance, making architectural choices for large and dynamic
       | software systems, such as say a cutting edge game engine - that
       | can be really hard to get right, and there's not always a lot of
       | sage advice out there for how to navigate it - and not just for
       | game engines but for any equally or more complex software.
       | 
       | I guess my point being - I'd love to see more effort into
       | addressing the hard design stuff, and less repetition of what's
       | already been established.
        
         | f1shy wrote:
         | I'm with you with 99% of those books. But this one is little
         | bit different, IMHO
        
         | AndyMcConachie wrote:
         | Every example I see in programming books that say something
         | like, "You should do it this way." Always come with the caveat
         | of, "It depends."
         | 
         | For the hard stuff that you would like to see covered the "It
         | depends" part becomes more important. The correct way of
         | handling the really tough cases you're talking about are
         | extremely circumstancial. Thus, a book discussing them
         | generally wouldn't really work. What would probably work better
         | are examples of these tough design issues that include the
         | actual code and some discussion about why specific design
         | decisions were made.
         | 
         | I like reading code from people who had to make tough trade
         | offs in the real world and hearing in their own words why they
         | made the decisions they did. I loved reading Lion's Commentary
         | on the UNIX OS 6th edition, for example.
        
       | gregfjohnson wrote:
       | This short book is (IMHO) one of the best on software design. To
       | me the main point of the book is the importance of well-designed
       | abstractions. The "surface area" of a well-designed abstraction
       | is small, easy to understand, and helpful as you reason through
       | your code when you use it. The underlying implementation may be
       | deep and non-trivial, but you find that you don't have any need
       | to worry about the underlying internal details.
       | 
       | In short:
       | 
       | A beautifully designed abstraction is easy to understand and use.
       | 
       | It is so trustworthy that you don't feel any need to worry about
       | how it is implemented.
       | 
       | Finally, and most importantly, it enables you to reason with
       | rigor and precision about the correctness of the code you are
       | writing that makes use of it.
        
         | f1shy wrote:
         | That book is a almost perfect summary of what is in my head
         | after 30+ years of programming. I recommend it often to new
         | people, as I see they make the same mistakes I did back then.
         | 
         | I recommend not loosing time with "Clean X" books, but instead
         | read this book. Also, as noted in other comments, you can only
         | "get it" after some real experience, so it is important to
         | practice an develop a "common sense" of programming.
        
           | karmakurtisaani wrote:
           | I disagree that the "Clean X" books are a waste of time. They
           | lay a nice ground understanding of what to aim for when
           | writing code, in particular when you're early in your career.
           | 
           | When I was starting as a professional coder years ago, I had
           | an intuitive sense of what good code was, but I had no idea
           | how much actual thought had been put to it by other people.
           | Reading those books was a good step in seriously starting to
           | think about the subject and look at code differently as a
           | craft ("it's not just me, this code smells!" or "hey that's a
           | neat idea, better keep this in mind").
           | 
           | Definitely would recommend to someone starting out their
           | career.
           | 
           | Edit: getting downvoted for a reasonable, justified opinion.
           | Classy.
        
             | f1shy wrote:
             | I think you are totally right. The clean X books are not a
             | waste of time. I meant that in the sense of "start here,
             | don't delay this". I would recommend: read aPoSD, then
             | Clean X series, then again aPoSD ;)
        
             | pdpi wrote:
             | Don't know about the rest of the series, but Clean Code
             | isn't merely a waste of time, it's worse -- it's actually a
             | net negative, and lies at the root of a number of problems
             | related to incidental complexity.
        
               | karmakurtisaani wrote:
               | Care to elaborate?
        
               | whstl wrote:
               | Not GP but: Personally, I find that book's advice is
               | highly subjective and rooted on aesthetics rather than
               | pragmatism or experimentation. It encourages an excessive
               | number of very small methods and very small classes, and
               | brushes off problems that it causes.
               | 
               | Not about the book, but: Its influence is malignant. Even
               | Uncle Bob mentioned in a recent interview that he will
               | break the "10 lines per method" rule if need be. But
               | practitioners influenced by the book lack his experience,
               | and are often very strict. I even remember a specific
               | Ruby linter that capped methods at 5 or 6 lines max IIRC.
               | Working in such a fragmented codebase is pure madness.
               | This comment from another user made me remind some of
               | those codebases:
               | https://news.ycombinator.com/item?id=42486032
               | 
               | EDIT: After living in the "Clean Code world" for half a
               | decade I can categorically say that it produces code that
               | is not only slow to run (as argued by Casey Muratori
               | [1]), but also slower to understand, due to the jumping
               | around. The amount of coupling between incestuous classes
               | and methods born out of "breaking up the code" makes it
               | incredibly difficult to refactor.
               | 
               | [1] https://www.youtube.com/watch?v=tD5NrevFtbU
        
               | karmakurtisaani wrote:
               | I think people get hung up with the small classes/methods
               | and ignore all the rest. One important lesson being that
               | the aesthetics do matter and you have to pay attention to
               | writing maintainable code. These are important lessons
               | for a beginning developer. If you think otherwise, you've
               | never worked on a code base which has 300 line functions
               | with variables named temp, a and myVar.
               | 
               | Regarding short functions: yes, having them too short
               | will absolutely cause problems. And you should not use
               | this as an absolute rule. But when writing code it's very
               | useful to keep this in mind in order to keep things
               | simple - when you see your functions doing 3 independent
               | things, maybe it's time to break ivt in 3 sub functions.
               | 
               | Edit: I see some criticism concerning too small classes,
               | class variables being used as de facto global variables
               | and shitty inheritance. Fully agree that these are plain
               | bad practices stemming from the OOP craze.
        
               | whstl wrote:
               | Sure, but nobody is saying that aesthetics don't matter.
               | Quite the opposite. People have been saying this for
               | decades, and even government agencies have code-style
               | guidelines. Also, the idea that big procedures are
               | problematic is as old as procedural programming itself.
               | 
               | The problem is that, when it comes to aesthetics, one of
               | the two more-or-less-novel ideas of the book (and the one
               | that is followed religiously by practitioners) is
               | downright problematic when followed to the letter.
               | 
               |  _> when you see your functions doing 3 independent
               | things, maybe it 's time to break it in 3 sub functions_
               | 
               | That's true, and I agree! But separation of concerns
               | doesn't have much to do with 10-lines-per-method. The
               | "One Level of Abstraction per Function" section, for
               | example, provides a vastly better heuristic for good
               | function-size than the number of lines, but unfortunately
               | it's a very small part of the book.
               | 
               |  _> I see some criticism concerning [...] class variables
               | being used as de facto global variables_
               | 
               | The criticism is actually about the book recommending
               | transforming _local_ variables into instance /object
               | variables... here's the quote:
               | https://news.ycombinator.com/item?id=42489167
        
               | lokar wrote:
               | If the 3 things are related such that they will only ever
               | be called in order one after the other (and they are not
               | really complex) it's better to just do all the work
               | together.
        
               | whstl wrote:
               | Yep, if they're related then I agree 100%.
        
               | sfpotter wrote:
               | But this line of thinking is exactly what's wrong with
               | Clean Code. Just seeing your function doing three
               | independent things is _not_ a signal that you should
               | begin refactoring.
               | 
               | I've worked on code bases with functions that were longer
               | than 300 lines with shorter variable names. Whether this
               | is a problem is _completely_ dependent on the context. If
               | the function is 300 lines of highly repetitive business
               | logic where the variable name  "x" is used because the
               | author was too lazy to type out a longer, more
               | informative variable name, then maybe it's possible to
               | improve the function by doing some refactoring.
               | 
               | On the other hand, if the function is an implementation
               | of a complicated numerical optimization algorithm, there
               | is little duplicated logic, the logic is all highly
               | specific to the optimization algorithm, and the variable
               | name "x" refers to the current iterate, then blindly
               | applying Clean Code dogma will likely make the code
               | harder to understand and less efficient.
               | 
               | I think the trick here is to cultivate an appreciation
               | for _when_ it 's important to start refactoring. I see
               | some patterns in when inexperienced developers begin
               | refactoring these two examples.
               | 
               | In the first example, the junior developer is usually a
               | little unmoored and doesn't have the confidence to find
               | something useful to do. They see some repetitive things
               | in a function and they decide to refactor it. If this
               | function has a good interface (in the sense of the book
               | ---is a black box, understanding the implementation not
               | required), refactoring may be harmful. They run the risk
               | of broadening and weakening the interface by introducing
               | a new function. Maybe they accidentally change the ABI.
               | If you have only changed the implementation, if no one
               | spends any time looking at the details of this function
               | because it has a good interface, ... what's been gained?
               | 
               | In the second example, the junior developer is usually
               | panicked and confused by a Big Complicated Function
               | that's too hard for them to understand. They conflate
               | their lack of understanding with the length and
               | complexity of the function. This can easily be a sign of
               | their lack of expertise. A person with appropriate domain
               | knowledge may have no trouble whatsoever reading the 300
               | line function if it's written using the appropriate
               | idioms etc. But if they refactor it, it now becomes
               | harder to understand for the expert working on it because
               | 1) it's changed and 2) it may no longer be as idiomatic
               | as it once was.
        
               | pdpi wrote:
               | One of the biggest issues with the book is that it is a
               | Java-centric book that aspires to be a general-purpose
               | programming book. Because it never commits to being
               | either, it sucks equally at both. In much the same way,
               | it's a "business logic"-centric book that aspires to be
               | general purpose, so it sucks at both (and it _especially_
               | sucks as advice for writing mostly-technical /algorithmic
               | code). This is epitomized by how HashMap.java from
               | OpenJDK[0] breaks almost every single bit of advice the
               | book gives, and yet is one of the cleanest pieces of code
               | I've ever read.
               | 
               | One fundamental misunderstanding in the book and that
               | I've hear in some of his talks is that he equates
               | polymorphism with inheritance. I'll forgive him never
               | coming across ad hoc polymorphism as present in Haskell,
               | but he book was published in 2009, while Java had
               | generics in 2004. Even if he didn't have the terminology
               | to express the difference between subtype polymorphism
               | and parametric polymorphism, five years is plenty of time
               | to gain an intuitive understanding of how generics are a
               | form of polymorphism.
               | 
               | His advice around prefering polymorphism (and, therefore,
               | inheritance, and, therefore, a proliferation of classes)
               | over switch statements and enums was probably wrong-
               | headed at the time, and today it's just plain wrong. ADTs
               | and pattern matching have clearly won that fight, and
               | even Java has them now.
               | 
               | Speaking of proliferation of classes, the book pays lip
               | service to the idea of avoiding side-effects, but then
               | the concrete advice consistently advocates turning
               | stateless functions into stateful objects for the sake of
               | avoiding imagined problems.
               | 
               | One particular bugbear of mine is that I've had literally
               | dozens of discussions over the years caused by his advice
               | that comments are _always_ failures to express yourself
               | in code. Many people accept that as fact from reading it
               | first hand, others you can clearly trace the brain rot
               | back to the book through a series of intermediaries. This
               | has the effrt of giving you programmers who don 't
               | understand that high-level strategy comments ("I'm
               | implementing algorithm X") are incredibly information
               | dense, where one single line informs how I should
               | interpret the whole function.
               | 
               | Honestly, the list goes on. There's a few nuggest of
               | wisdom buried in all the nonsense, but it's just plain
               | hard to tell people "read this chapter, but not that, and
               | ignore these sections of the chapter you should read".
               | Might as well just advise against juniors reading the
               | book at all, and only visiting it when they've had the
               | time to learn enough that they can cut through the
               | bullshit themselves. (At which point it's just of dubious
               | value instead of an outright negative)
               | 
               | 0. https://github.com/openjdk/jdk/blob/master/src/java.ba
               | se/sha...
        
             | nyrikki wrote:
             | There tend to be two camps with the Uncle Bob franchise as
             | I see it:
             | 
             | Those that fall for the way he sells it, as the 'one true
             | path', or are told to accept it as being so.
             | 
             | Those who view it as an opinionated lens, with some
             | sensible defaults, but mostly as one lens to think through.
             | 
             | It is probably better to go back to the earlier SOLID idea.
             | 
             | If you view the SRP, as trying to segment code so that only
             | one group or person needs to modify it, to avoid cross team
             | coupling, it works well.
             | 
             | If you use it as a hard rule and worse, listen to your
             | linter, and mix it in with a literal interpretation of DRY,
             | things go sideways fast.
             | 
             | He did try to clarify this later, but long after it had
             | done it's damage.
             | 
             | But the reality is how he sells his book as the 'one true
             | path' works.
             | 
             | It is the same reason scrum and Safe are popular. People
             | prefer hard rules vs a pile of competing priorities.
             | 
             | Clean architecture is just ports and adapters or onion
             | architecture repackaged.
             | 
             | Both of which are excellent default approaches, if they
             | work for the actual problem at hand.
             | 
             | IMHO it is like James Shore's 'The Art of Agile
             | Development', which is a hard sell compared to the security
             | blanket feel of scrum.
             | 
             | Both work if you are the type of person who has a horses
             | for courses mentality, but lots of people hate Agile
             | because their organization bought into the false
             | concreteness of scrum.
             | 
             | Most STEM curriculums follow this pattern too, teaching
             | something as a received truth, then adding nuance later.
             | 
             | So it isn't just a programming thing.
             | 
             | I do sometimes recommend Uncle Bob books to junior people,
             | but always encourage them to learn why the suggestions are
             | made, and for them to explore where they go sideways or are
             | inappropriate.
             | 
             | His books do work well for audiobooks while driving IMHO.
             | 
             | Even if I know some people will downvote me for saying
             | that.
             | 
             | (Sorry if you org enforced these over simplified ideals as
             | governance)
        
         | begueradj wrote:
         | > A beautifully designed abstraction is easy to understand and
         | use.
         | 
         | It's like in "Clean Code" where Ward Cunningham said a clean
         | code is a beautiful code.
         | 
         | Beautiful design, beautiful code, beautiful abstraction,
         | beautiful class, beautiful function ... But is not that
         | subjective and broad ?
        
           | AnimalMuppet wrote:
           | Yes, it's subjective, but not entirely. After you've done it
           | for a couple of decades, you start to have a sense of taste,
           | of aesthetics. Some things seem beautiful, and others ugly.
           | It's "subjective", but it's also informed by two decades of
           | practice, so it is far from being _purely_ subjective.
        
           | cratermoon wrote:
           | Robert M. Pirsing discusses qualia in his writings. One
           | objection raised by his antagonists is, "quality is just what
           | you like", echoing the idea of broad subjectivity you raise.
           | Yet there is broad agreement on what counts as quality. Among
           | the aspects we agree on is complexity and subjective
           | cognitive load.
        
       | cdpd wrote:
       | I think that the first example tackles such a naive approach
       | about how to implement the discount code, IMHO I would ask more
       | about the business logic around it. Why is a discount applied to
       | both the order and the shipping? are they the same thing? What if
       | the company applies discounts to only shipping and not orders
       | itself?
       | 
       | Maybe it comes from experience, but I would focus on
       | understanding the business side first and the see if the
       | abstraction is feasible (To be honest the first approach in the
       | example is not even bad given that they are two "independent"
       | business entities)
        
       | PunchTornado wrote:
       | I view that some of his principles are against what uncle Bob is
       | preaching. And I agree with him, especially on the focus to
       | reduce complexity. Uncle Bob preaches modularity and
       | encapsulation over everything and you end up with a thousand 2
       | liners classes and methods.
        
       | tpoacher wrote:
       | The telegram channel is a great idea. Subscribed!
        
       | ozgrakkurt wrote:
       | Focusing on these things feels like focusing on training
       | technique too much when going to the gym. In the end mostly what
       | matters is getting things done and keeping it as simple as
       | possible. And simple is very subjective, everyone's simple is
       | what is simple to them. Feels like everyone should pick a
       | technique and master it then reuse it, there is not much point on
       | finding a global simple/elegant
        
       | Warwolt wrote:
       | I read this book with some colleagues at a work book club, and I
       | think it's interesting how split the opinion on the book is among
       | readers.
       | 
       | My impression is that there's some good ideas in the book, but it
       | suffers from not being thorough enough on a theoretical level.
       | Many definitions given are NOT consistently used, the book
       | frequently falls back on discussing things in a very OOP centric
       | way, and a lot of stuff came across to me as just opinion pieces.
       | 
       | Some stuff I found was excellent, like the notion of module
       | depth.
       | 
       | When reading reviews on Goodreads, there's a similar disparity
       | between people who really liked it and people who are critical of
       | it.
        
         | rodolphoarruda wrote:
         | > the book frequently falls back on discussing things in a very
         | OOP centric way
         | 
         | I do procedural most of the time. Do you think I can still
         | benefit from reading the book? Judging from the summary in blog
         | post, it seems to be a nice read even for non-OOP code. It's
         | just my first impression though.
        
       | johnwatson11218 wrote:
       | A good game is supposed to be "easy to learn and hard to master".
       | I think software abstractions should have this property as well.
       | Too often the next "fix" in a long chain of failed ideas in
       | overly engineered software feels like the Batman games where one
       | has to complete a mini tutorial to learn to use the "bat-
       | whatever" for a single application/puzzle. Contrast this with the
       | Borderlands franchise, I can learn to play Borderlands in 5
       | minutes and explore the skills tree and whatnot at my leisure if
       | at all. You hear about "Deus ex machina" as a lazy trait in
       | writing, but it is commonplace in enterprise software. Load
       | Bearing Abstractions.
        
         | elanning wrote:
         | I know the feeling. I like to picture it as a kitchen, and
         | those "bat-whatever" gadgets are like those silly infomercial
         | cooking tools that are only good for one specific thing.
         | Meanwhile the good abstractions are like a nice knife, that can
         | be used in so many different contexts.
        
       ___________________________________________________________________
       (page generated 2024-12-22 23:01 UTC)