• magic_lobster_party@kbin.run
    link
    fedilink
    arrow-up
    69
    arrow-down
    1
    ·
    5 months ago

    I genuinely think his book is rubbish. I agree with some of his points. Most of the good points are common sense. For the most part I heavily disagree with the book.

    Throughout the book he has examples of programs where he shows before and after he applies “clean code”, and in almost all examples it was better how it was before.

    I can write a lot about why I don’t like his book. He doesn’t make many compelling arguments. It’s mostly based on what he feels is good. He often contradicts himself as well. If I remember correctly, he has a section about how side effects are bad. I agree with him on this part. Shortly after, he proudly shows an example of “clean” program - and it’s littered with awful side effects!

    He also has this weird obsession of hiding the logic of the program. As a programmer, I want all relevant logic of a method to be neatly collected in one place - not scattered around deeply nested method calls.

    I can go on and on. I hate this book with a passion.

    • traches@sh.itjust.works
      link
      fedilink
      English
      arrow-up
      28
      ·
      edit-2
      5 months ago

      I think it’s telling that none of his talks even make it all the way through his SOLID acronym, he sorta just trails off when he’s out of time.

      His ideas were real big in the ruby community back when I was learning it, and if I ever go back that code is such a pain to work with. Almost impossible to follow the logic, inheritance everywhere, and I even thought metaprogramming was a good idea. Tests are the only reason that code has any reliability at all.

      Now most of my code is procedural or functional, favors composition over inheritance, and is colocated as much as possible.

      • JackbyDev@programming.dev
        link
        fedilink
        English
        arrow-up
        9
        arrow-down
        1
        ·
        5 months ago

        Fucking Ruby… Nothing is more confusing to me than seeing an error about a method not existing but the problem being that something was null/missing.

          • JackbyDev@programming.dev
            link
            fedilink
            English
            arrow-up
            6
            arrow-down
            1
            ·
            5 months ago

            It’s amusing to me that people will say “my code documents itself” while also using dynamic languages. It should be called GDD. Guess driven development.

            • traches@sh.itjust.works
              link
              fedilink
              English
              arrow-up
              6
              ·
              5 months ago

              I love how parentheses on function calls in ruby are optional. Is it a variable? Is it a function? Where does it come from? Who the hell knows! Try to run it and find out, loser

    • anti-idpol action@programming.dev
      link
      fedilink
      arrow-up
      11
      arrow-down
      1
      ·
      5 months ago

      death by specificity is a thing…
      HTTPServletRequest has a fuckton of methods but 90% of them could be eliminated if one treated the data as a simple fucking map instead of creating 4 methods for each key in every record of your schemas.

    • Prunebutt@slrpnk.net
      link
      fedilink
      arrow-up
      17
      arrow-down
      14
      ·
      5 months ago

      Sorry, I still don’t really get the hate.

      Most of the good points are common sense.

      I use what I learned from watching a talk by him on clean code and I had to learn some stuff. It might be “common sense” for experienced developers. But it certainly doesn’t come naturally that “functions should do one thing” to first time coders. The thought processes of when the software was developed usually isn’t the best way the code should be structured in the end. But that’s usually how beginners code.

      It’s mostly based on what he feels is good.

      In most diciplines, experience in the field is what makes the knowledge of the field. You don’t always have to be able to explain why good practice does what it does.

      Also: I know of some examples, where he clearly explains his reasoning, e.g. why comments shouldn’t explain how the code works. (Because they’re not going to be updated, when the code will be)

      As a programmer, I want all relevant logic of a method to be neatly collected in one place - not scattered around deeply nested method calls.

      Either you misrepresent him, or you get a hard nope from me. Staying on one layer of abstraction is most likely my most important principle of writing understandable and maintainable code.

      • ByteOnBikes@slrpnk.net
        link
        fedilink
        arrow-up
        18
        ·
        5 months ago

        It’s mostly based on what he feels is good.

        One of my main issues is, seeing his code in the past decade… It feels like this guy hasn’t coded in a collaborative environment in years.

        His personal opinion tends to get on the way with code that’s easier to read from a team perspective. And “Uncle Bob” pushing that as the defacto way to code.

        This happens from Influencer types who are so detached from the industry for decades and are no longer aligned with problems real engineers hit.

        It’s not that he’s wrong. It’s that his perspective is outdated.

      • magic_lobster_party@kbin.run
        link
        fedilink
        arrow-up
        16
        ·
        5 months ago

        why comments shouldn’t explain how the code works

        I categorize this as one of the better points of the book.

        functions should do one thing

        I kinda disagree with him on this point. I wouldn’t necessarily limit to one thing, but I think functions should preferably be minimal.

        Throughout his examples he’s also using ideas like how functions should only be 3 lines long, preferably have no arguments, and also no return values.

        This style of coding leads to programs that are nightmarish to work with. The relevant code you’re looking for might be 10 layers deep of function calls, but you don’t know where. You’re just jumping between functions that does barely nothing until you find the thing you’re looking for, and then you need to figure out how everything is connected together.

        I prefer when things are flatter. This generally leads to more maintainable code as it’s immediately obvious what the code is doing and how everything is connected.

        I think his book is the equivalent of a cleaning guide where all the steps are just to sweep all the mess under the carpet. It looks cleaner, but it’s not clean.

        • nous@programming.dev
          link
          fedilink
          English
          arrow-up
          12
          ·
          5 months ago

          I kinda disagree with him on this point. I wouldn’t necessarily limit to one thing, but I think functions should preferably be minimal.

          I do actually agree with him on that point - functions should do one thing. Though I generally disagree on what one thing is. It is a useless vague term and he tends to lean on the smallest possible thing a thing can be. I tend to lean on larger ideas - a function should do one thing, even if that one thing needs 100s of lines to do. Where the line of what one thing is, is a very hard hard idea to define though.

          IMO a better metric is that code that changes together should live together. No jumping around lots of functions or files when you need to change something. And split things out when the idea of what they do can be isolated and abstracted away without taking away from the meaning of what the original function was doing. Rather than trying to split everything up in to 1-3 line functions - that is terrible advice.

          • magic_lobster_party@kbin.run
            link
            fedilink
            arrow-up
            11
            ·
            5 months ago

            Yeah, that’s an argument of semantics. I agree with you.

            What I believe is that functions should do exactly what they advertise. If they do the things they’re supposed to do, but also do other things they’re not supposed to do, then they’re not minimal.

            But I feel like Uncle Bob is leaning more towards that if a task requires 100 different operations, then that should be split into 100 different functions. One operation is one thing. Maybe not exactly, but that’s kind of vibes I get from his examples.

            • nous@programming.dev
              link
              fedilink
              English
              arrow-up
              5
              ·
              5 months ago

              But I feel like Uncle Bob is leaning more towards that if a task requires 100 different operations, then that should be split into 100 different functions. One operation is one thing. Maybe not exactly, but that’s kind of vibes I get from his examples.

              Oh yeah he defiantly does. He even says so in other advice like a function should be about 1-3 lines. Which IMO is just insane advice.

        • JackbyDev@programming.dev
          link
          fedilink
          English
          arrow-up
          5
          ·
          5 months ago

          People can take the “do one thing” argument too far. I’ve seen people have individual micro services for each CRUD action on a resource.

        • vrighter@discuss.tchncs.de
          link
          fedilink
          arrow-up
          3
          ·
          5 months ago

          also, the dependency inversion thing makes it so that not even the tooling can help you with that, to put the cherry on the cake

        • Prunebutt@slrpnk.net
          link
          fedilink
          arrow-up
          4
          arrow-down
          1
          ·
          5 months ago

          Yeah. I get more of what you’re saying now. The 3 line functions on principle are indeed a bit much. Although I’ve found that sometimes theare necessary to stay consistent with the layers of abstraction (e.g.: a for-loop that writes some data over some bus).

      • JackbyDev@programming.dev
        link
        fedilink
        English
        arrow-up
        12
        ·
        5 months ago

        Which of these do you prefer?

        A?

        @Test
          public void turnOnLoTempAlarmAtThreshold() throws Exception {
            wayTooCold();
            assertEquals(“HBchL”, hw.getState());
          }
        

        Or B?

        @Test
          public void turnOnLoTempAlarmAtThreashold() throws Exception {
            hw.setTemp(WAY_TOO_COLD);
            controller.tic();
            assertTrue(hw.heaterState());
            assertTrue(hw.blowerState());
            assertFalse(hw.coolerState());
            assertFalse(hw.hiTempAlarm());
            assertTrue(hw.loTempAlarm());
          }
        
        Uncle Bob's Clean Code suggests

        Option A

        • magic_lobster_party@kbin.run
          link
          fedilink
          arrow-up
          11
          ·
          5 months ago

          I almost pulled my hair out when I read that section. One is super obvious without any prior experience with the code. The other is an obscure abomination only he can understand. He’s obviously super proud of his abomination and thinks it’s a prime example of “clean code”.

          • magic_lobster_party@kbin.run
            link
            fedilink
            arrow-up
            5
            ·
            5 months ago

            His idea is that it’s faster to read that short string once you learn how to read it. But then you need to learn how to read it.

            In my experience, every time I thought of something clever like this, I’ll almost always regret it a month later when I revisit the code.

        • RonSijm@programming.devOP
          link
          fedilink
          arrow-up
          3
          arrow-down
          4
          ·
          5 months ago

          I’ve started to prefer option A to be honest.

          In C# I’m using Verify - So I prefer to just use Verify(state); and compare the entire state against a json saved state, instead of manually verifying every individual property

      • traches@sh.itjust.works
        link
        fedilink
        English
        arrow-up
        11
        arrow-down
        1
        ·
        5 months ago

        Regarding the experience thing, I’d like to point out that a lot of us have experience that says „clean code” is a real pain in the ass to work with and think through.

        • Prunebutt@slrpnk.net
          link
          fedilink
          arrow-up
          8
          arrow-down
          2
          ·
          5 months ago

          You do? I have the opposite experience: I regularly stumple over dirty code where levels of abstraction differ wildly and I regularly lose my train of thought, because some function writeToFile() all of a sudden shifts some bit in a register with an outdated comment next to it (overly dramatizised).

          Functions never being longer than 4 lines goes, too far IMHO, but the “clean code should read like prose” bit is something that has been really useful to me.

          • JackbyDev@programming.dev
            link
            fedilink
            English
            arrow-up
            13
            ·
            5 months ago

            Functions never being longer than 4 lines goes, too far IMHO,

            That’s the problem with the book! People experienced enough to sort out bad advice from it are already experienced enough to have learned the good advice.

          • traches@sh.itjust.works
            link
            fedilink
            English
            arrow-up
            9
            ·
            5 months ago

            Im not saying every word of it is wrong, just that the sum total of all his advice is. I don’t think there’s any school of thought that says it’s good for a function named ‚writeToFile’ to be doing other stuff

            • Prunebutt@slrpnk.net
              link
              fedilink
              arrow-up
              2
              arrow-down
              1
              ·
              5 months ago

              My (poorly chosen) example wasn’t about the side effects, but rather about the differing layers of abstraction. Almost all criticisms I’ve seen was about the “functions should be like only 4 lines” rule. Which admittetly: Is a bit whack. But no one actually pulls that rule through, do they?

              • traches@sh.itjust.works
                link
                fedilink
                English
                arrow-up
                6
                ·
                5 months ago

                I think the focus on short, simple functions combined with DRY code leads to many early, poorly chosen abstractions. Getting out from under a bad abstraction can be painful.

              • nous@programming.dev
                link
                fedilink
                English
                arrow-up
                5
                ·
                5 months ago

                But no one actually pulls that rule through, do they?

                They do though. Loads of new people to programming read that book and create unreadable messes of a code base that follow all of his advice. I have lost count of the number of times I have inlined functions, removed layers of abstraction and generally duplicated code to get a actual understanding of what is going on only to realize there is a vastly simpler way to structure the code that I could not see until all the layers and indirection are removed. Then to refactor again to remove redundant code and apply more useful layers again that actually made sense.

                And that is the problem we have with his book. People that need it take up as many bad habits as they do good ones leading to an overall decline in their code quality. It is not until years of experience that you can understand the bad bits and ignore them. So overall his book is a net negative on the programming world. Not all his advice is bad, but if you can tell that then you likely don’t need his advice.

                But on the layers of abstractions specifically, he takes this too far. Largely because of the 4 line limit he has. There is a good level of abstraction and I generally find more than 2 or 3 levels of abstraction is where I start to loose any sense of what is going on. He always seems to jump on abstraction as soon as he can, but I find waiting a while and abstraction when you need to to lead to fewer and vastly better layers of abstraction overall.

                And adding more abstraction does not help the people of people doing too many things inside a function - they just move it to sub functions rather than extracting the behavior for the caller to deal with. I have never seen him give advice on what that is appropriate, only keeps the functionality of the original function the same and move the logic into a nested function instead and that only covers up the issue of the function doing too much.