How to Become a Bad Developer

(rafaelquintanilha.com)

211 points | by elsewhen 1043 days ago

37 comments

  • macspoofing 1043 days ago
    >It is very common, especially among novice developers, to be proud of the number of line of code their application has.

    My experience has been the opposite. Novice developers tend to be proud of how terse and dense their code is, and optimize for minimizing line count.

    I also disagree with that author's views on this point. For example: "Simply put, it means “the less, the better”" - No, it isn't.

    In my career I found that maintaining unsexy, and maybe a little verbose code is never the problem. Usually that code tends to be more easily understandable to even junior developers and therefore is less prone to bugs being introduced because developer made the wrong assumptions on what the code was doing. Code that is too clever for its own good is where bugs tend to occur.

    • stonemetal12 1043 days ago
      My take on it is that all software developers novice or otherwise try to write simple, clear code.

      For some(especially novices) that means plodding, low abstraction code, so that all the details are visible. This makes for longer code. Others see high abstraction code as the cleaner simpler code because the abstractions hide what they see as irrelevant details, which makes for terse code.

      “the less, the better”

      “the more, the better”

      Tautologically both are incorrect when pursued farther than is prudent, and "the right amount, the better". Unfortunately no one really agrees on what "the right amount" is or we wouldn't have to discus different definitions and strategies to reach "the right amount".

      • opportune 1043 days ago
        Completely agree with you. The issue IMO is over-eager abstraction tends to simply make code more confusing. It may be more “elegant” but if it turns out the class/functions/whatever used to generalize code will never need to be used elsewhere (so they will only be changed in their current state), or have too many different behaviors based on configuration options, it actually makes things more confusing than just proliferating boilerplate - because instead of a big imperative chunk you can read and modify directly wherever it’s used, now you have to understand the class, maybe base classes, the function and which control paths it takes based on which args, etc.

        And that nuance means for example, maybe it makes sense to create a helper to append some additional error detail to a string if used only twice, but maybe if some similar behavior is used in 7 slightly different ways, it shouldn’t be generalized if it requires lots of conditionals and arg plumbing.

        This is why I kind of hate the mantra of “if it’s used 2-3 times or more, wrap it in a function or class.” IMO the bar for something being wrapped needs to be higher - either the amount of logic should be large and segmentable enough that it can be placed in something that separates concerns from where it otherwise would be, small and very repetitive, or it needs to be used much more often in a way that truly resembles a library (and thus requires an interface that does not expose implementation details or wrap messy conditional logic).

        • stouset 1043 days ago
          > This is why I kind of hate the mantra of “if it’s used 2-3 times or more, wrap it in a function or class.”

          I think that’s a fine signal to use to identify that something needs to be refactored, but that doesn’t absolve an engineer of having to think about how to actually do so.

          It’s why I’ve always cringed at IDEs with “refactor selected code into its own function” actions. This is so rarely what you should ever be doing.

          Refactoring is like butchering. You need to figure out how the muscles lie and separate them on their natural boundaries, not just start hacking things into parts because they seem too big. Once you’ve separated pieces across good functional boundaries you can start trimming and breaking things up to fit specific needs, but it has to start with stepping back and getting a wider view.

      • Osiris 1043 days ago
        And of course it depends on context. The interworking of a game engine may require some really obtuse code because it's focusing on performance and not on readability (in those cases, comments should be used to explain the code).

        In my experience the problem with juniors is more about thinking about the problem in a very linear fashion and not stepping back to see it as individual parts.

        For example, I need to know when a user takes an action. So, I go into the code where that happens and throw in a bunch of analytics vs having a messaging system where events are raised and the code that handles those events are completely separate workers that are simple and easy to understand.

        • cardanome 1043 days ago
          > For example, I need to know when a user takes an action. So, I go into the code where that happens and throw in a bunch of analytics vs having a messaging system where events are raised and the code that handles those events are completely separate workers that are simple and easy to understand.

          It is interesting that you think that code with more abstractions is easier to understand.

          From my experience the simple linear beginner code is the one that is quite easy to work with. It is easy to grasp the general intention and to slowly refactor parts of the code if need be.

          Now a mid level developer that thinks of themselves to be smart and tries their hardest to use some fancy abstractions and patterns? Yeah, put it in the trash. We will have to rewrite that code.

          The best code is from the senior that finds the right balance. Finding the right abstractions to use takes years of experience.

          The most important rule when programming is: Don't try to be smart. Keep it simple.

          • stouset 1043 days ago
            Code with more abstractions is generally easier to understand, which is precisely why most of us prefer to work in modern languages over assembly. And why we use SQL instead of working directly with low-level storage engines. And why most people prefer languages like Ruby and Python to FORTRAN and BASIC. It’s why we build software on top of an operating system and kernel, and now why we do so with the further abstraction of containers. It’s why we use an HTTP library for clients and servers instead of just writing and parsing requests directly on the wire.

            And it’s why io_uring is a stark improvement over select.

            The problem is bad abstractions. Bad abstractions don’t cut the underlying problem across clean axes, they leak too many implementation details, and they aren’t often able to be reused. “Linear beginner code” that handles too many concerns in one place is inarguably bad, but bad abstractions are generally worse.

            We shouldn’t be trying to stop using abstractions: virtually all of the history of progress in computing has been driven by finding good abstractions that allow us to build bigger and better things with less mental overhead. We should be doing absolutely everything we can to understand and teach the practice of writing good abstractions.

        • aYsY4dDQ2NrcNzA 1043 days ago
          “We must always think of the Way of strategy as being both a rat's head and an ox's neck. Whenever we have become preoccupied with small detail, we must suddenly change into a large spirit, interchanging large with small. This is one of the essences of strategy. It is necessary that the warrior think in this spirit in everyday life.”

          — Miyamoto Musashi, The Book of Five Rings

      • dmartinez 1043 days ago
        A mental analogy that I personally use for this is cabinets. A section of an app is kind of like a cabinet in a kitchen. Some people like opaque cabinet doors while others prefer glass. Other people go even further, and eschew cabinets for open shelves.

        These differences in object and system visibility sometimes reflect specific use cases (e.g., a professional kitchen can operate faster with open shelving than with opaque cabinet doors). Other times, they simply reflect the personal preferences of the designer.

      • kerblang 1043 days ago
        It's that concise, straightforward, efficient & flexible are often contradictory instead of complimentary: You're typically sacrificing others for the one.

        It often helps to be specific about which traits you are/aren't focused on when arguing for the "right" solution. Words like "easy" and "simple" are more ambiguous and lead to confusion.

      • golergka 1043 days ago
        Everyone has their own definition of "simple". Some think that closures are too fancy and complicated while others don't understand what's so hard to grasp about a monoid in the category of endofunctors.
      • Hermel 1043 days ago
        Ideally, the code is structured such that one can navigate it at different levels of detail, with the lower level functionality encapsulated into separate units that can be ignored if one is not interested in the details.
    • drewcoo 1043 days ago
      Part of learning any new technique is overusing it to see what its limits are.

      When people first start coding they're trying to get machines to do things. They have to learn the techniques of making code for other humans. To them it's making things verbose and adding tons of comments because that's better.

      Meanwhile, they're usually learning to plan for future code needs and make their code flexible.

      But part of learning to use those techniques is overuse. So that means code gets gold-plated, baroque, byzantine, and needs a novella of comments to explain its magnificence to future developers so that they use it right. Time to trim it back. Less is more.

      I think that's what the author meant.

      • vagrantJin 1043 days ago
        > So that means code gets gold-plated, baroque, byzantine, and needs a novella of comments to explain its magnificence to future developers so that they use it right.

        I like the way you phrased that.

        Anecdotally I find code that is too clever annoying at times, when time is short and the PM Melissa has a bolt action rifle to my head on friday afternoon. I get that code that is too concise is also trying hard to be marvelled as genius-worthy.

    • galangalalgol 1043 days ago
      Verbose code is one thing but multiple adjoining layers of abstraction, or excessive modularization can both make maintaining code very difficult as well. Both dense and bloated solutions had goals other than doing the simplest thing that might possibly solve the immediate problem. That is the only worthy goal, it ensures maintainability due to its simplicity and any extensibility loss is offset by that simplicity. Most of the designed in extensibility I've seen predicted the wrong sort of extension that would be needed anyway.
      • cactus2093 1043 days ago
        > Most of the designed in extensibility I've seen predicted the wrong sort of extension that would be needed anyway.

        I definitely agree with that, and I think a preference for more verbose code is actually very compatible with this idea. Verbosity is not the same as over-complicating or over-abstracting things. In my experience a lot of the time it's actually the drive to avoid verbose code that causes these problems in the first place.

        For instance, you have two functions that are similar but with some important difference, and the developer decides that anything that resembles duplication is bad and refactors them into a single abstraction. This type of thing can cause much more harm than just leaving in a little bit of verbosity by keeping the functions independent of each other.

        • gradys 1043 days ago
          One way to analyze the two similar function situation is to ask whether a future change in the logic to one would imply that a change should also made to the other.

          If so, then by keeping them separate, you introduce the risk that you would forget to update the other. Using a single function and calling it twice, even with different parameters, is a way communicating that it's important that the semantics be tied.

          If a change in one wouldn't imply a change in the other, then you really have two separate semantic roles being played that happened to resemble each other in implementation - harmless incidental duplication.

          • cactus2093 1043 days ago
            > to ask whether a future change in the logic to one would imply that a change should also made to the other.

            If there's a really obvious answer to that question, then great. But often the answer is "sometimes" or even "most of the time". We train most developers beginning even in intro-level programming classes to err on the side of deduplication and over-abstracting in these cases, but the longer I've been working as a developer the more I have come to think it's better to err on the side of allowing some duplication except in the most clear cut of cases.

          • Wowfunhappy 1043 days ago
            What if a change to one would imply a change to the other, but also the block of code is needed in 20 places instead of two?
      • me_me_me 1043 days ago
        This.

        Clearly defined purpose for each layer when doing abstraction.

        Verbosity and simplicity.

        And NEVER EVEN try to be smart. In two weeks you will forget how the 'smart' solution works and have to spend x2 time changing it.

    • ritchiea 1043 days ago
      I believe the author would agree with you, his last bullet point is write for humans not for machines. When he says write less code, I believe he means favoring simpler architectures, saying no to features & tools until you absolutely need them & even finding no-code solutions. Not taking verbose code & making it less readable by shortening it.
      • rightbyte 1043 days ago
        I note it is quite common with rule of thumbs in programming and that they are misused to sillyness.

        One way to write less code is to in practice code golf. To follow DRY add deeply nested abstractions. To not have to plan out what you do, use YAGNI or "no premature optimizations". Etc.

        Edit: My personal favourite is "code should be self-documenting", i.e. comments are a failure.

      • rafaquintanilha 1043 days ago
        Author here. You summarized it better than me! Thanks.
    • jayd16 1043 days ago
      I think the author is referring to the mentality of "I wrote my way into this mess and dammit I'll write my way out!"

      That is to say, novices can tend to pile onto a solution with hacks and special cases instead of examining why their abstraction requires so much special casing.

      I think the code golf you're talking about is a different (but not exclusive) thing.

      • Jtsummers 1043 days ago
        Yep. It's an interesting dichotomy with new hires.

        They can write some of the tersest code once they learn some new thing ("Wait, C# lets me use LINQ and lambdas. I can turn this entire thing into 3 lines of code!") and some of the most convoluted messes when they run into an issue.

        I call the latter the epicycle approach [0]. A simple model that doesn't quite work, but they can't let go of, is complicated by adding more and more "simple" extensions but it produces a convoluted mess that is nigh impossible to maintain or sustain.

        [0] https://en.wikipedia.org/wiki/Deferent_and_epicycle#/media/F... : Demonstrating the complexity needed to maintain a geocentric model and account for the movement of celestial bodies.

    • genezeta 1043 days ago
      > My experience has been the opposite. Novice developers tend to be proud of how terse and dense their code is, and optimize for minimizing line count.

      I would agree with that. But then again, it isn't entirely incompatible with the cited quote. That is, at different times in their careers, developers may tend to do different things.

      In any case, I think I understand the original quote as something I have indeed seen somewhat frequently in large projects. It seems somewhat common, from my experience at least, that people -particularly "not-so-good developers"- involved in large projects tend to assert how large/important the project in fact is, by mentioning LOCs. "This is a very large project... It's about 5.5MLOCs or so. It will have grown a bit since we last counted."

    • bena 1043 days ago
      Write as little code as needed to complete the task and as much code as needed to be understood. At the same time.

      Both incredibly dense and incredibly verbose code can become maintenance headaches. You want it short enough that it can be contained in your head, but long enough that the steps are obvious.

      I liken it to the scene in Return of the Jedi where Han is instructing Chewie to fly close, but not too close.

    • grp000 1043 days ago
      Agreed. Some of my early code is near unreadable due to the complexity that I've since pared down on how much a single line should be doing.
    • ChrisRR 1043 days ago
      Oh god, I used to work with the guy like this. Incredibly clever graduate, blew some of my knowledge out of the water.

      But every day was a game of code golf to him. His code was absolutely illegible

      • jackcviers3 1043 days ago
        To be fair, bugs are highly correlated with line count, and all code is inscrutable in the absence of knowledge.

        I do like vocabulary-based metrics for legibility/difficulty; Halstead metrics can't tell you how good a piece of code is, but they can tell you how difficult it is for others to read, empirically.

        The old 7 +- 2 rule applies, if you are using more than 9 functions/methods and arguments, the vocabulary of a function is difficult.

        f compose g is 0.5. It has 3 elements. It's not hard to understand.

        def compose (f: B=> C, g: A => B): A => C = x => f(g(x))

        Is 2.5, counting all the definition parts and type level stuff. It has 14 distinct elements. If you don't know the pieces, it's really difficult to read if you don't know any of the parts. If your language doesn't care about types,

        def compose(f, g) = (x) => f(g(x))

        Comes to 2.1 by my count, but you have to look up fewer things at 7, so it's easy to read for new people.

        Now, the types make it easier once you advance beyond a pure beginner- the constrain the function to only one possible implementation. But if you're totally unfamiliar with things, they make stuff unreadable. Even in tiny functions.

    • kbenson 1043 days ago
      > My experience has been the opposite. Novice developers tend to be proud of how terse and dense their code is, and optimize for minimizing line count.

      I think it's both. There's a sense of accomplishment that goes along with both accomplishing some small task with minimal code, and also for having written a somewhat large chunk of code for a project. Both have their place, as succinctness has it's place, and it's natural to look back and feel proud of a lot of work. It's just when they aren't tempered by the experience to ask whether that terseness came at a cost that wasn't worth it or whether that project is much larger than it needs to be for the task accomplished that it ends up being detrimental.

    • AceJohnny2 1043 days ago
      I agree, and it reminds me of an analogy...

      I discovered IRC as a teenager in the 90s, and soon learned SMS-speak for rapid messaging. I was proud of how quickly I could write if I just wrote "u r" instead of "you are"... This was cool! In chatroom arguments, being able to belt out more sentences faster was better!

      But as my typing improved, I realized the above was a childish optimization. Real skill was able to write out correctly-spelled sentences just as fast. I then saw the SMS-speak as immature shortcuts.

      This realization carried over into code: good code is the clear, adequately verbose (but appropriately concise) kind. Code that tries to be overly-clever (of the "code golf" kind), was to be viewed with suspicion.

      • AceJohnny2 1043 days ago
        (I'll admit this tainted my view of Perl for a long time, as I perceived its community tending to more vocally celebrate such "clever" code)
    • mch82 1043 days ago
      It seems the author agrees with you. The final “bad habit” calls people out for writing code for machines instead of humans.

      https://rafaelquintanilha.com/how-to-become-a-bad-developer/...

      The author lists the habits of *bad* developers as: (1) Never assume there is a bug in your code, (2) Write code without reasoning, (3) Lack assertiveness, (4) Take pleasure in writing more code, (5) Write for machines, not humans.

      So the author advocates for less code, but written to be used and maintained by other people.

    • BitwiseFool 1043 days ago
      My friends and I used to joke about how verbose variable and object names can be in an enterprise setting. But the longer I have worked as a professional developer the more I appreciate the long and 'exactly what it says on the tin' names. In almost every circumstance developer time is more valuable to the company than some clever code that 'saves' CPU time.
    • 908B64B197 1043 days ago
      > My experience has been the opposite. Novice developers tend to be proud of how terse and dense their code is, and optimize for minimizing line count.

      Depends on the culture. A lot of offshored programmers will report their "performance" as number of lines written. With the expected results...

    • systemvoltage 1043 days ago
      “the less, the better”

      Could mean:

      1) As you said, terse clever code and agree 100%.

      2) Or avoid writing factories that produce factories, abstractions upon abstractions that never get the payoff since the abstraction only gets used for a single (or a handful) of cases ever. When you write abstractions, make sure that in next 10-20 years its going to get its money's worth by taking advantage of it. There are always some exceptions but most of the time I've seen code that has no defense for all the bloat.

      3) The best code is the code that you don't write. In this case "the less, the better" indeed.

      So I can see multiple meanings of "less, the better". Also, my experience matches the author - new developers are mostly proud of number of lines than cleverness.

    • corentin88 1043 days ago
      Agreed. More-readable code is generally longer in my experience. And that’s not a problem AFAICT.
      • dave_sid 1043 days ago
        Yes, Especially when there a compiler in between the ide and the cpu :-)
    • rafaquintanilha 1043 days ago
      "Simply put, it means “the less, the better”" was referring to the principle of "via negativa", not necessarily to code.

      Maybe I conveyed the wrong meaning on this sentence. I don't think that less code is better. I believe that the more code you have, the more potentially breaking parts you get. However, the right amount of code is a function of your deadline, team, goals, budget and whatnot.

      In any case, it's nice to have principles as a beacon during your development, so you don't get lazy and fool yourself. But by no means they are written in stone and every attempt to summarize an absolute truth will be shallow.

    • jt2190 1043 days ago
      > I also disagree with that author's views on this point. For example: "Simply put, it means “the less, the better”" - No, it isn't.

      This is one piece of developer lore that’s actually backed by some research. [1] Like it or not, there is a correlation between lines of code and bug count.

      [1] I’ll link to this research when I have a little more time. Edit: Here's a great resource on this: https://www.hillelwayne.com/talks/what-we-know-we-dont-know/

    • fifticon 1043 days ago
      Maybe I misread him, but I read it as "it is better to have just the right, critical set of features", instead of "adding more bells and whistles will always makes it better!" I know from my own code, that whenever I introduce too much flexibility, I invariably end up with fragile complexity, and using it to shoot my feet from various angles. And I have also met a colleague or two who so far haven't reached the same conclusion, only the fragile complexity part (i.e. they still see it as a positive thing.)
    • toomuchredbull 1043 days ago
      Yup... I find this with swift developers they love to write code that is just a series of : ? ! type symbols to do what should be 3 or 4 lines of readable code into one line of unreadable code.
    • teucris 1043 days ago
      The principles in this article seem paradoxically conflicting, especially this one (“[don’t] Take pleasure in writing more code”) and “[don’t] Write for machines, not humans”

      Inherently, more code means more chances to explain what it’s doing to other humans, so shouldn’t more code be better?

      Obviously not, so I take these two principles in tandem as “write as much code as is needed to accomplish the task effectively and explain how it works, but no more than that.”

      Squishy, but I think this article as a whole does a decent job of addressing your concerns.

    • marcus_holmes 1043 days ago
      Agreed. The author should change it to "write complex code".

      Novice developers are frequently proud of the complexity of their code. Experienced developers write simple, easily understood, code.

    • dgb23 1043 days ago
      I know where you are coming from and I agree on a certain level, but I think this is too specific to your case (large teams, high fluctuation, lots of juniors)

      The more general approach would be to write code with coworkers/audience in mind.

      In some environments or projects it might be more effective to write in a way that is harder to grok (requires more work to understand) but is ultimately more tailored to a specific outcome, may that be performance, extensibility, security or what ever.

    • mcguire 1043 days ago
      Have you ever dealt with seriously verbose code? One 10,000 line file with maybe three functions or methods? Setting and resetting the same variables; perhaps introducing new ones kind of randomly? From a programmer who uses essentially one control structure, a while(true) loop with a test and break somewhere in the middle of the body? (Actually, the last is a separate issue, but things like that always add to the fun.)
    • h1fra 1043 days ago
      Funny that point 4 and 5 both make sense alone but are fairly contradictory when applied together. Juniors can barely understand why they are both very important. It's with experience that you learn to write less small dumb code, and write more longer smart/debuggable code.

      In my short career, the worst code was always the one made by the overly experienced CTO that insist on doing everything in a one liner.

    • joshwcomeau 1043 days ago
      +1, came here to say this. The comprehensibility of the code matters way more than the length. It’s not like the bugs sneak in once every 50 characters typed.

      As I’ve gotten more experienced, my code has gotten less fancy and more verbose. A single terse expression is broken out into 3 or 4 statements, defining variables that capture and name fragments.

      But yeah, otherwise really enjoyed the article!

    • k__ 1043 days ago
      Yes.

      Often even sacrificing everything to that tersness.

    • slumdev 1043 days ago
      > Novice developers tend to be proud of how terse and dense their code is, and optimize for minimizing line count.

      I've never seen a senior write nested ternary expressions with side effects...

    • austincheney 1043 days ago
      My experience is somewhere in between. Many novice developers are proud of how few lines of code their solution is although it’s really just 2 lines of glue code masking 300mb of dependencies. When you point this out they come back with some bullshit like:

      * any original code is NIH

      * vetted by the community

      * original code can fail

    • johnalbertearle 1043 days ago
      Quite so.
  • TrackerFF 1043 days ago
    Hubris, to the point where everyone around you must be a moron.

    I've seen very talented developers fall prey for that one. They seem to fit the pattern of your typical "hacker" type that grew up spending all their youth on coding, and thus binding a lot of their identity and self-worth to their coding abilities.

    They blaze through college, being extremely competitive among their peers, and are often among the "go-to" students in class, which only boosts their ego even further.

    Then they join the workforce, and find themselves having to work with other people - and they hate it. Any hint of criticism is taken deeply personal, like a sledgehammer to their self-worth. Tips and tricks from others are equally bad - who are they to teach you anything? After all, you've been banging out code and reading books since you were 9.

    Code review is like walking on eggshells for the others - they know you'll roll your eyes, chuckle and snort, and just shoot down any incoming comment.

    If only you didn't have to work with all these morons around you - the very people that are slowing you down. Move fast and break things, isn't that the motto?

    • fridif 1043 days ago
      What if the guy who thinks everyone is a moron, is the moron?

      I have a team leader right now who blocks all of my PRs and always demands rework, despite the code functioning exactly as intended and being performant and efficient as well, and maintainable too.

      • duxup 1043 days ago
        Even a talented developer who can't get along with others even on a minimal basis ... may as well be the moron.

        At some point you've got a job, and code alone is not the whole job. Can't do part of it, then you're not doing a good job.

        A job is almost never just code.

        • dave_sid 1043 days ago
          Some of my coding jobs are no code
        • madeofpalk 1043 days ago
          or put differently - learning how to code is table stakes. It's boring and not impressive.
      • alphanumeric0 1043 days ago
        I've been struggling with the same issue. I have a team lead who, if they have no good feedback, will fabricate an issue with my code during PR reviews, no matter how trivial. I sometimes have to take a step back and laugh. I understand some people may be under the illusion that they must give feedback no matter what, at the risk of seeming unsavvy, but it's starting to become ridiculous, and it seems more about competing with me rather than giving me genuine, constructive feedback.

        I make sure to thoroughly document my changes in my commit messages and sometimes in my comments, especially documenting who requested the change so that there's a nice paper trail. I also push back often, but the mere act of responding to feedback that does not seem honest from a team lead is traumatic.

        My problem is: how do you report such a passive-aggressive person? A single request or question on its own seems benign and not particularly harassing, but the overall trend is a huge red flag. To be honest, I'm not sure much can be done.

        If you decide for whatever reason that you cannot leave, the best way to deal with a passive aggressive person is to erase from your memory that they are passive aggressive at all. It is a test of wills that you will win, just don't lose your cool. Never forget that a passive aggressive person is a fundamentally insecure person, and then you will always have the upper hand.

        • fridif 1043 days ago
          I am simultaneously sad and a bit relieved that others are also struggling with a problem that I thought was uniquely mine!

          This is genuinely just an example of bad management and bad workplace politics. If the code is working and checks all the boxes, nobody in the organization should be allowed to say "I personally do not want your code to be deployed", especially if other developers dont face such restrictions.

          The simple solution is to leave, but I am growing tired of job hopping. If I can land a job as a lead, or at least a place that has autonomy, I am pledging not to do such things to those "beneath" me, as if that word was even true.

      • stonemetal12 1043 days ago
        I worked for a guy like that. I even tried going to him before I implemented anything try and get it to his liking the first time. He would still demand rework after doing it his way .
        • softfalcon 1043 days ago
          This. So much this. I have worked under countless team leads who are like this.

          At first I thought I was just hopelessly bad at coding/following instructions, but even when I pair programmed with these folks and followed their every instruction, they'd still want to refactor all of it the next day.

          Some people are just never content unless it's 100% written by them.

        • dctoedt 1043 days ago
          > He would still demand rework after doing it his way

          I sometimes do that with contracts drafted by junior lawyers — and often it's due to having had additional thoughts after seeing an actual "product," in sort of a fail-fast mode of drafting. Could that be part of the explanation in your case?

        • craftinator 1043 days ago
          > He would still demand rework after doing it his way .

          I've dealt with this before by documenting everything they told me to do differently, with date and time.

          Always fun doing code review in a group, having the lead point out a number of problems they have with the code, especially actual bugs, and pulling up the changelog which includes notes from the one criticizing your code, telling you to make those design choices. I've collapsed whole meetings this way, with people walking out and going straight to HR with requests to transfer teams. Really helps to remove the poison from the group.

        • fridif 1043 days ago
          This same exact thing is happening to me! Like man, I implemented your sequence diagram your way!
      • snovv_crash 1043 days ago
        Leave something obvious and easy to fix on each PR. This lets them get their 2c in and you can move on with life.
        • fridif 1043 days ago
          I've found what always works there is

          var string = "";

          instead of

          String string = "";

          My teammates waste their time focusing on the most inane things.

      • kilroy123 1043 days ago
        You just got to add a duck.
      • slumdev 1043 days ago
        Is your code actually correct, efficient, and maintainable? Does the rework improve its correctness, efficiency, or maintainability?

        There are members of my team whose PRs are rarely approved without rework. There are other members of my team whose PRs almost never require rework.

        It's just a gut check question. This guy could be totally wrong and a jerk. Or he could be right and a jerk. If he's right and a jerk, then internalizing that feedback might help you (even if he's still a jerk.)

      • hungryforcodes 1043 days ago
        If it's really an issue, get a trusted 3rd party (or two) in the team or organization to evaluate your PRs -- and the team lead's feedback. Eventually with a few iterations of this, the reality will become evident for everyone. There should be an engineering manager above the lead that is vested in this process being successful.
      • dude01 1043 days ago
        I'm gonna guess they have a bit of oppositional defiance disorder. I'd probably try to change teams because that's not going to change.
        • cjaybo 1043 days ago
          A pretty specific guess for someone we know basically nothing about!
      • nine_zeros 1043 days ago
        That team lead might have insecurity issues. It will not get better. Switch teams asap.
        • fridif 1043 days ago
          Thanks so much, I'm working on that!!! Good to hear the confirmation of my suspicions..
    • hungryforcodes 1043 days ago
      The real purpose of a good engineering leader is to help mentor people like this to become mature. They have talent -- they just need everything else (humility, social skills within the team, shared vision, whatever).

      With good mentoring, I've seen a few of these so called "hacker" types transform after a few years. Also when you are 20 you're into one thing -- competition for the ego -- and 10 years later into something else -- collaboration for the group. Responsibility and experience are great transformers.

      But someone has to actively give that feedback, and the "hacker" type has to be willing to learn, it's true. Some engineering leaders lack the courage to do so and this really is where the problem starts.

  • sdevonoes 1043 days ago
    I would add: "Follow the rules no matter what"

    I've seen people reading about CQRS, Clean Code, Hexagonal Architecture, Event Bus, all these "good practices" published by celebrities... and after some time these people believe "they are right" because they know these patterns and because they apply them every time code needs to be written. It's difficult to reason with them; the conversation usually goes this way:

    - Joe: We should use Hexagonal Architecture in our new system because Alistair Cockburn knows what's best

    - Me: I think we don't need it? Past experience in other projects of ours says we can handle this new system without HA

    - Joe: I don't think you know better than Alistair Cockburn, so let's stick with HA

    • ChrisMarshallNY 1043 days ago
      I'm not a fan of dogma, in general. The whole "My only tool is a hammer" deal.

      Many architectures and techniques (CI/D, TDD Unit Testing, etc.) are based on large projects, with multiple developers, being reassigned and rotated frequently. They often can be applied to smaller projects, but their effectiveness is not always on par with large projects.

      I tend to write alone. That means that my scope is, out of necessity, much smaller than many people enjoy, but it also means that a lot of infrastructure overhead is actually a severe problem.

      The advantage of writing alone, is a flexibility that many teams could only dream of, and having a lot of team overhead management practices and structure in place, absolutely kills flexibility.

    • ratww 1043 days ago
      Oh, man, I've seen the damages this kind of thinking does.

      The Terse vs Verbose code debate is important and all, but honestly architecture is the thing that can make or break a project.

      Picking the wrong architecture for the job is the kinda thing that delays features, brings more bugs to the table and will make the exact same people ask for a rewrite down the line.

      I once worked on a company that was dominated by such types. They made terrible architectural decisions out of cargo-cult and it took two backend rewrites in a row to get things half-right, but they still ended up with a mongrel codebase with several mixed complex patterns.

      In your example, your real-life experience matters 100x more than Joe's opinion of whatever architecture he wants to use.

    • kristopolous 1043 days ago
      They already know "the answer" before hearing the problem and it's the same answer every time.

      Sometimes it's medical quackery, other times it's economic policy orthodoxy or religious moralism and sometimes it's software stuff

      It's fundamentalism. I've gotta go back to working on that book. It's all the same shit and enters and exits people's heads through the same emotional and environmental triggers

    • rjbwork 1043 days ago
      I have found that, especially in the cloud with the many SAAS, IAAS, and PAAS offerings there, people end up implementing some kind of poorly thought out CQRS/Event Bus architecture because these offerings naturally lead that way. Attempting to bring some order to it by actually applying these patterns in a structured way is met by something like "that seems complicated" or "we'll never need it" or "why would we keep a log of all of our events"?

      If you're doing distributed cloud event based systems these are sane ways to go about it. I contend though that usually you can get away with a series of big fat SQL databases until you're well into the billion in revenue a year club.

    • ItsMonkk 1043 days ago
      Your co-workers argument was an appeal to authority. That's not sufficient. Your argument is a straw-man. That's also not sufficient.

      The set of patterns that you mention are a different paradigm from the typical OOP-based paradigms. They come from people who are looking at code and seeking composability. As they come at it from a different perspective, when an OOP-programmer comes at the patterns they will cross a "weirdness budget" limit and superficially disregard it.

      Any architecture - in a Turing complete language - can solve any problem. All programmers should be seeking to keep complexity to a minimum, while also being well understood. Complexity is made up of two elements, essential complexity that all problems have, and accidental complexity. Accidental complexity can arise out of all sorts of ways, and skill of the programmer, maturity of the architecture, and many others.

      Switching to a different architecture that you are not familiar with will cause accidental complexity. Switching to an architecture that has not been well tested will cause accidental complexity.

      I believe that CQRS, Clean Code, Hexagonal Architecture, Event Bus are all patterns that will eventually be proven to be correct for most people in most situations, but that the tooling for all of them is not yet there. You should evaluate the patterns for yourself and test them out and find what you can take away that works today. I do not currently use all of them myself even though I believe in their long-term suitability. I do the same for OOP frameworks. The only way to know anything is by trying it yourself and getting to know it.

    • overgard 1043 days ago
      Yeah, this drives me crazy. I've had people in the past suggest supporting legacy apis on our project that has exactly one consumer (whose code we can directly update in the same repo), or adding wrapper functions all over the place for "layers" in an app that's like maybe 10,000 lines of code. These things are perfectly fine in the context they're designed for, but people love their shiny new hammers.
    • softfalcon 1043 days ago
      Agreed! If you can't explain WHY the design decision is the right decision, you haven't thought hard enough.

      If I ever hear folks name-dropping, that line of discussion ends and we need to reign it back in to the real "choices and trade-offs" discussion that will get us a real solution, not some abstract opinions.

    • spand 1043 days ago
      Everything is gold plating until it isn’t. So do you bet on the project going big and deep or not ?
  • PragmaticPulp 1043 days ago
    > Take pleasure in writing more code

    Very common trap. Most of us grew up with a natural enjoyment of programming, so it’s easy to lose sight of the fact that our job as engineers isn’t to produce more and more code. Our job is to deliver results, not lines of code.

    This often manifests as developers or entire teams that can’t stop rewriting, refactoring, and rearchitecting code that is already good enough. They might want to rewrite their otherwise working service in Rust because Node.js is no longer popular, or rework the stable React app to use hooks, or fork and maintain a popular open-source project because they think they can improve it. They prefer to write generalized solutions or frameworks from the start instead of writing a specific one-off solution to get the job done. Or maybe they just have perfectionist tendencies and struggle to submit that PR until they make just one more improvement.

    This isn’t unique to developers, of course. My last company had a major problem with UI/UX designers who could never finalize their designs. We lost countless months to endless iterations and tweaks. Part of the problem lies with management, of course, if they’re not enforcing actual project deadlines and end times.

    • Ensorceled 1043 days ago
      As a technical manager, the most important thing I end up doing is snipping off complete re-writes or re-architectures in the bud.

      I've also found that management is actually the greatest source of UI/UX reworks; once they've seen the pixel perfect mockups, management thinks that "the job is done" and they want to iterate ...

      • cogman10 1043 days ago
        I gotta ask, though, how do you handle it when a product ISN'T working?

        I've dealt with a product that was so poorly architected that, to this day, it is constantly causing production outages, bad data, etc. And the root of the problem is that it wasn't built to do the right thing. At it's very core, it processes and stores data incorrectly. (Leading to "there are good days and bad days and ops will handle it").

        Yet, I met the "We CAN'T REWRITE" pushback, which, ok, but here's the solution that doesn't involve a rewrite, it'll be 10x more expensive because the slow evolution will be a whole lot harder and more risky than a fresh solution with an adapter to the old interface.

        I certainly don't take rewriting lightly, and don't generally suggest it, but I have to ask. How can you sell it when the alternative is what my company deals with today?

        • Ensorceled 1043 days ago
          > I gotta ask, though, how do you handle it when a product ISN'T working?

          Yeah, sometimes you have to rewrite/rearchitect but more often you don't. But sometimes the job is to actually get some one to let go of the control of strange baby they implemented so you can rewrite.

          Years ago I worked on DNA analysis software where the entire thing was abstracted; codons could be any number of bases instead of just 3, there could be any number of bases instead of 4, there was a whole system for managing amino acid names that assumed there could be an infinite number of amino acids. Loading a sequence involved millions of checks to see if there were any matches against 4 base codons or 5 base codons ...

          That definitely was a rewrite; but the developer fought it every step of the way.

        • eropple 1043 days ago
          I find myself saying "beware the protoduction trap" a lot because of exactly this. Get-it-out-there prototype code pushed into production roles can work great. It also can not work great and can have discontinuous failure modes. You're placing a bet that it won't fail until you somehow outpace the need to care about it, and...well, I don't love that bet when I'm the one advocating for it, if I'm advocating against it it's probably because I can see the crack and hear the rumble on the horizon.
        • avgDev 1043 days ago
          I rewrote a product which was not working and was never completed 100%. New version is better but I had to hack things here and there due to constraints of the existing systems. Additionally, the number one problem is lack of documentation, not in the app but in the business sense.

          In order to write a good application the process it is going to support needs to be well documented. This wasn't the case and I had to go back in circles a few times but you live and learn.

      • belval 1043 days ago
        At my first real software job one of the engineer always used very rough outlines that are obviously unfinished. He always said that having pixel-perfect mockups is a sure way to have your meeting sidetracked by someone asking if "the button should be bigger" or "the orange should be more red-ish" and then not understand why it would take 5 engineers 6 weeks to "just make the button bigger".

        I work as a backend engineer now because I just couldn't take those meetings anymore.

    • dgb23 1043 days ago
      I strongly believe that regular refactoring (rarely rewrites) is very beneficial, efficient and has strong implications on sustainability of the code and the competency of programmers.

      But too much refactoring doesn't really make sense because you cannot see where chaos wants to go, so you'll constantly find local maxima.

      I believe we often have to use heuristics and "best practices" as guidelines for refactoring, structure and design. However one of the best methods I find is to just observe for long enough where problems start to arise. Like pumping a liquid through a thing so you see where it leaks if that makes sense.

    • magicalhippo 1043 days ago
      > This often manifests as developers or entire teams that can’t stop rewriting, refactoring, and rearchitecting code that is already good enough.

      We got tons of code that I'd love to rewrite or refactor. But it works. Has done for 15 years and will continue to. Instead I can fix proper bugs and add new features.

      Sure if the old mess is standing in the way of delivering something important I will do something about it. But not until then, we just tweak it when needed and that's it.

      • handrous 1043 days ago
        Unfortunately, it's common to get "stakeholders" involved who want to "approve the design" before a feature's green-lit, as in, exactly what's going to be built, or at least very close. Because they're "important" so they must know software UI design better than the UX experts, designers, and developers they've hired. "No no no, this delete icon must be a red X, even though that could easily be mistaken for 'close' in this context, and I will fight you for weeks to make sure it happens". They don't like wireframes or deliberately-rough mockups.

        Or you get branding lunatics involved who aren't able to produce and provide visual-design guidelines that they trust well enough not to need to stick their nose into every project to make sure the button corner radius is "on-brand" and can't ever let a design pass without some kind of tweak, because that means they're doing work, I guess.

    • climate-code 1043 days ago
      So what is the correct way to think about refactoring?

      Should code that is delivering results, but is hard for others to understand & work on be refactored?

  • okareaman 1043 days ago
    I once had the misfortune of working at a company whose rockstar developer was a bad developer. He could crank out reams of working code as easy as breathing it seemed.

    My misfortune was being assigned to take over one of the projects he threw together. My god, what a mess. He literally had 10 to 20 boolean flags in every pages long functions so that it was extremely difficult to tell what path the code would take under what circumstances. I got fired because I couldn't understand the code enough to enhance it. I was judged inadequate.

    A couple of years later I had lunch with the developer who took my place. She told me what code she was working on. When I casually said "Oh, that spaghetti code is still used?" she let out a big sigh. She thought the problem was with her and finally someone had come along to call out the crappy code this "rockstar" was foisting on everyone.

    • overgard 1043 days ago
      I remember this one job, I got assigned to this team because their rockstar left the company and I had similar overlapping talents. His code generally wasn't terrible, but he had this habit of being /way/ too clever for his own good. For instance, we had this 3d mesh file loader (for a game). We wanted to add another file format, since the legacy one we were using was some ancient outdated thing from 3ds max that only one artists could export from their machine, so it was a bottleneck in the pipeline. Anyway, this fricking mesh loading code should have been, if well designed, super easy to update right? Hell no! This guy attempted to use every template meta-programming feature available in C++, so even adding a method to a class would suddenly result in this nightmare cascade of indecipherable template issues.

      There's this phase any every developers career, my own included, of "being just smart enough to be dangerous". It's like, you're smart enough to use those kind of features, but not smart enough to realize that just because you can doesn't mean you should.

      The worst part though is, when you take it over, the expectation from non-technical people is "well this guy wrote the feature in a weekend, why can't you update the feature in a weekend"? So you end up looking worse in comparison because your predecessor set you up to fail. I would implore anyone writing code that has some empathy: try to setup the people working on your code for success.

      • dorgo 1043 days ago
        >try to setup the people working on your code for success.

        yeah, but that would take more than a weekend..

    • cogman10 1043 days ago
      This is a major industry problem. Business managers often care about how many features devs churn out. Quality generally takes a backseat.

      Devs that churn out more features are generally perceived more favorably than devs that churn out fewer lower maintenance features. There's no linking to "The guy that original wrote the code wrote a mess".

      • okareaman 1043 days ago
        You raise a good point. I don't see maintainability and extensibility discussed very often, except for jokes about Perl being a "write only language."

        The ironic part of it was I fired because of a bug in his code. One of the flags he was using was set wrong. It cost the company a contract worth a few hundred thousand dollars and since I owned the code at the time it was my fault. I didn't even try to argue because programming jobs were easy to find at the time and I wasn't sticking around to deal with their mess.

  • goda90 1043 days ago
    > Take pleasure in writing more code

    My manager showed me where I fall on the company-wide distribution of quality(based on issues attributed to my code), and quantity(based on logical lines of code committed). I was near the top for quality, and near the median for quantity. My project had been fairly complex, involving the joining of two already complex systems that handle a wide range of configurations and had their own fair share of bugs that I had to figure out. I held my tongue when they said that I should work on increasing my output.

    • eatonphil 1043 days ago
      That sucks. I'm sorry you have a manager who isn't seeing the obvious. But speaking as a manager it's always possible to miss the obvious, so I always encourage people to make it as clear as possible (please, literally speak about it) where things are difficult or challenging so everyone can understand that the quality is inversely related to quantity.
    • scioto 1043 days ago
      Reminds me of the story of knowing which screw to turn[1]. Whenever I modify or add to code, unless it's a total pile of dung I usually try to figure out the general pattern of the original developer, which leads to the smallest number of added lines to accomplish things.

      I've noted code where a previous fixer obviously didn't figure out what was going on, and instead bolted their solution to the side of the codebase instead of figuring things out. I spent a good six months after go-live on my last big project removing the bolt-ons and following the patterns, leaving consistent code.

      Committed LoC: not much, bad if quantity proves worth; actually removed more than I added on that clean-up job.

      [1]https://www.snopes.com/fact-check/know-where-man/

    • hpoe 1043 days ago
      An employer ever starts evaluating my productivity in lines of code or git commits is the day I become the employee of the year. After all do you know how many lines of code you can put back in once you start writing all of the java boilerplate by hand? Also with magit I challenge anyone to come up with more commits than I am capable of.
    • majormajor 1043 days ago
      Tell them you should work on increasing everyone else's quality instead. ;)

      (I mean, unless you don't want to do that sort of role, of course.)

  • rafaquintanilha 1043 days ago
    Author here. So you guys are the reason of the huge spike on my website today?

    I should mention that the "rules" there are completely opinionated and reflect what I understood as the biggest problems I had (and still have) as a software engineer.

    Also would like to clarify that "via negativa" is a general principle, but of course won't work all the time. As a matter of fact, I refrain myself from excessive modularization whenever I can. In the end, software development is about delivering the biggest value, in less time, without compromising quality and maintainability (or at least being aware of the costs).

    A nice side-effect of this semi-virality is that I get to read a lot of nice additions to the original 5 points. This post is calling for a sequel...

  • Jtsummers 1043 days ago
    > Never assume there is a bug in your code

    I had a boss who went with, "Always assume the bug is in our code." Which wasn't too bad, except for the time he wouldn't let us tell the hardware partner they probably had a bug until we could definitively prove that it was their problem and not ours. Took us a few months to produce a reliable test case for the error (consistent failures and not sporadic ones) and shifted the entire project schedule (not just us) right. He just didn't trust us lowly CS types.

    • defaultname 1043 days ago
      That boss' demand would be right probably 99% of time. And getting it fixed by a hardware partner without concrete evidence would be unlikely to be successful.
      • Jtsummers 1043 days ago
        It would have been right to notify the hardware partner that we believed we'd found an issue but were investigating on our end. He did not, in fact he forbade mentioning it in any meeting with them. We had good evidence that it was a hardware issue (No issue and then a new hardware revision and then the issue appeared. There had been some software changes, but none that should have impacted this). The problem was we couldn't say it with enough confidence to satisfy him, he wanted absolute proof and he did believe that CS people were incapable of identifying a hardware issue (a statement he'd made on multiple occasions). This literally resulted in spending an extra million or more to finish the project late. It was not the right call to delay several months before reporting it to the partner. It took them another 3+ months to develop a fix and we couldn't progress on the software in that time because it was not working correctly.

        We could make it "work" in that it would send the correct data but it was too slow to operate within the protocol specs (so the whole system would fail, hitting time limits that caused resets and test failures), or we could pray that all the correct data made it which it would 7 times out of 10. But that 30% (or more) failure rate meant that we couldn't reliably determine when a failure was in our software or the hardware.

    • Jemaclus 1043 days ago
      For customer-, client-, partner-, vendor-generated complaints, I also operate on the "always assume the bug is in our code" philosophy. You don't want to go back to a customer (customer, client, partner, vendor) and tell them that it's _their_ problem until you have sufficiently ruled out evidence that it was _your_ problem. In your case above, however, I would have spent a couple of days--max--before going back to the partner and saying "Hey, we've noticed this bug, and we're still investigating things on our end, but we're reasonably confident it's not something on our end. Can you take a look?" This would have saved you months, but also demonstrated to the partner that you've done (and are doing) due diligence to investigate the problem.

      But for 99% of interactions, you want to assume you're the one who screwed up. It's safer and it's better customer support.

      A similar rule to this is to remove the phrase "it works for me" from your vocabulary. The client wouldn't be complaining about it if it worked for them! So you need to rule out a bug before you go back and say "Hey, actually, you're the one who screwed up." I've found that maybe only 50% of the time is it client error, and so I always operate under the condition that the customer was right until I can prove that they weren't.

      • Jtsummers 1043 days ago
        I agree, and we'd already done that (short investigation on our end). We just hadn't fully isolated the bug, which we ended up doing after a few months once we had discovered more about the failure pattern to direct our attention to one key area of the hardware system. This let us write a single program that reliably produced the failures. But if we'd let the hardware team know early on, they may have been able to put a few days in to investigate themselves instead of waiting for us to provide them with what they should have already known (it revealed that their design and testing was grossly flawed and incomplete).
  • OskarS 1043 days ago
    This one is interesting: "Take pleasure in writing more code".

    I agree with the author's reasoning that the number of lines of code you write is meaningless and not something you should hold up with pride, but there is a flipside to that: when you get to a certain amount of experience, code verbosity is usually a good thing.

    At some point when learning, many programmers become good enough at thinking in code that they become able to express everything in incredibly terse one-liners. This is when they start using ternary operators everywhere instead of if statements, or very obscure functional map/reduces instead of simple for loops.

    Being able to write like this is obviously good, but that doesn't mean you should do it: just because you can cram everything into one line/statement, doesn't mean you should. This gig is not just about writing clever code, it's about writing code that others can read (as well as yourself, six months later) and reason about and debug easily.

    Writing understandable code is not always the same as writing more verbose code, but the two are certainly correlated.

    • Swizec 1043 days ago
      > or very obscure functional map/reduces instead of simple for loops

      The functional programmer in me just died a little. Map and reduce are not obscure. They’re the basic building blocks!

      For loops, now that’s obscure. There’s like 5 different incantantions for a for loop in JavaScript alone. Each with its own subtle behavior differences.

      • OskarS 1043 days ago
        You’re right, there’s nothing inherently wrong with map, reduce and the rest of the high-order functional suite. What I’m talking about more is when people make very complicated aggregation functions in order to keep state around. In these cases, simple for loops are usually much easier to read and as a bonus they’re almost always significantly faster.

        Not every problem benefits from a functional solution.

        • ratww 1043 days ago
          I mean, sure, but the opposite is also true:

          Sometimes people make complicated incantations inside for loops (or worse, while loops) that could be replaced by simpler functional constructs. In these cases, map and friends are easier to read.

          The problem here is not one construct or the other, but the fact some people are making code that is hard to understand. There's no one size fit all solution.

        • jhgb 1043 days ago
          > What I’m talking about more is when people make very complicated aggregation functions in order to keep state around

          Are we talking about languages without handy combinators? I can imagine that in these, turning stateless functions into stateful aggregators is going to be more obscure rather than easy.

          As for speed, that seems like an implementation issue. In principle a functional solution could still preserve more information for efficient code generation than a loop for which such information needs to be extracted from by complicated auto-vectorizers. In practice the environments aren't "quite there" (lack of such features as Common Lisp's compiler macros), and any potential or even realized benefits may be cancelled out by other performance issues of such environments.

          • overgard 1043 days ago
            > As for speed, that seems like an implementation issue.

            At the end of the day though, it's still your issue, even if you can point at a 3rd party. Personally I'd rather have my fate in my own hands rather than wait on a "sufficiently smart optimizer"

            • jhgb 1043 days ago
              Hence my mention of compiler macros, which put the fate of the sufficiently smart optimizer into your own hands.
      • jcelerier 1043 days ago
        > Map and reduce are not obscure. They’re the basic building blocks!

        Conceptually basic != basic for humans. The more basic and "simple" the maths, the harder it becomes for human beings to understand (otherwise most people wouldn't fail first years of higher education maths that often).

    • UglyToad 1043 days ago
      This is my take from writing object oriented code (I don't know how broadly applicable to functional languages it is).

      I started off writing code in a procedural style with no organisation. I was told that was bad so I created fragmented abstracted code where everything did very little across 10s of classes and methods.

      Now I write procedural style code again, I don't worry about long methods as long as the flow is obvious and the abstractions, used sparingly, feel right.

      • samsquire 1043 days ago
        I'm the same. I'd rather inherit large methods that do a thing than an over abstracted mess of classes and methods that don't give you anything but noise.
  • 29athrowaway 1043 days ago
    The #1 way to become a bad developer is: stop caring.

    - Stop caring about understanding what you are doing.

    - Stop caring about the quality of your deliverables.

    - Stop caring about understanding how things work.

    - Stop caring about finding better ways of doing things.

    - Stop caring about learning.

    - Stop caring about what you have learned and how you can use it.

    There are many factors that will make tempt you stop caring, but you should resist them and persevere. One of such factors is: mediocre jobs, mediocre leadership.

    If you stop caring, you'll become unemployable in a few years, and any advantage you had over younger developers will go away.

    • agomez314 1043 days ago
      Can attest to this. You start letting small things slide in PRs, decide not to add those extra assertions because "you know it will work", not understand the libraries being used and before you know it the codebase is something people want to stay away from.
  • Osiris 1043 days ago
    In my experience, a junior developer is one that 1. Thinks through problem very linearly, leading to very long and complicated functions. 2. Only thinks about the happy path. They don't validate inputs or analyze what could go wrong and handle those cases.

    I can't tell you how many bugs I've fixed because programmers write code that only works if everything goes exactly the way they expect.

    • morelisp 1043 days ago
      Junior developers ignore the non-happy path and accidentally crash a lot.

      Mid-level developers spend enormous effort modeling the error conditions and their programs never crash but are 10x longer and have lots of subtle bugs, especially edge cases of data corruption.

      Senior developers ignore the non-happy path and ensure the program crashes a lot.

    • cakebrewery 1043 days ago
      On the other hand, linear code is the easier to refactor compared to over engineered code
  • fighterpilot 1043 days ago
    Cyclomatic complexity is the most common code smell I've seen from experienced devs.

    Callbacks everywhere. Confusing use of compositions - A is in B but also B is in A, making it impossible to reason about.

  • tuyguntn 1043 days ago
    Please enlighten me here, in the past we were obsessed with design patterns and tried to make code as modular as possible and we were proud if our code worked for 5-10 years.

    nowadays, 2 biggest advise I get from articles and books are: (1) make code as readable as possible (2) write code so it is easy to remove the code and re-write. basically advising me to write such methods: StoreUserDataAndFetchDetailsFromOauthProvider, instead of some fancy flows

    world is moving very fast and time spent on making code modular with design patterns seems not worth it (I am spending my last 6-8 years in startups).

    most of my code is verbose and doesn't contain design patterns, am I that bad developer?

    • amackera 1043 days ago
      I would think writing modular (decoupled) code would make it easier to remove and re-write, no? I don't see any conflict between those two bits of advice.

      Readability has a long tradition in programming too, including but not limited to literate programming (1984). IMO nothing wrong with verbosity as long as it serves a purpose (readability is a worthy purpose). I think the perceived trend "developers care more about readability now than they did x years ago" is likely due to the proliferation of click-bait blog posts on the subject.

      Lastly, if you're asking yourself the question "am I that bad developer", then IMO you by definition aren't that bad developer. Bad developers don't ask this question, or they don't care about the answers. You are self aware!

      • tuyguntn 1043 days ago
        > would make it easier to remove and re-write, no

        maybe yes, maybe no. depends on how much engineering effort was spent. if upfront cost of perfect decoupling is high and later we need to delete it, why think about decoupling it at the first place? maybe write verbose, spaghetti code and when code contains all the business logic, then start refactoring slowly, when things became stable?

  • DoctorNick 1043 days ago
    "How to be successful" screeds like the one cited in this article from the Berkshire Hathway ghoul always seems to leave out a crucial step: "Come from a well-off, well-connected family".
  • Tade0 1043 days ago
    I would add "focus on how your progress looks in the eyes of the stakeholders".

    I lost count how many times I had to fight over doing actual work and coming clean on how much is really done versus making the result only appear finished and knowingly merging buggy code.

    Stakeholders put pressure because of course they do. That doesn't mean lying to them is a sound tactic. It's much better to negotiate a reduction of scope than pretend you've delivered only to later have them, or worse - the users - discover the truth.

  • Exuma 1043 days ago
    Step 1: Constantly suggest very stupid ideas with a complete unawareness of the greater context, just because the thing youre suggesting is something you're good at, so you just recommend it blindly

    Step 2: Don't ask questions, don't know how to communicate

    Step 3: Take ideally 1 day or more to respond to clients

    • Akronymus 1043 days ago
      I am sometimes guilty of the first. Altough, I try to go in with: "Whats the reason why we are doing it in x and not in y?"
  • sjatkins 1043 days ago
    On the taking pride in LOC counts I really enjoy the opposite. Especially rewarding is blowing up a bad manager who things LOC increase equals productivity. So much fun to report I contributed -10,000 LOC in the last month by careful refactoring and reusability.
  • mywittyname 1043 days ago
    > Write for machines, not humans

    I could see this being a "good developer" trait too. For example, writing programs that are designed to be easily consumed by other programs. Humans might like a nicely formatted HTML page, but machines like plain text output.

    • onion2k 1043 days ago
      Machines don't care. What you mean is "Developers like plain text output."

      If you meant to say that machines will parse content faster in plain text because there's no HTML parsing necessary then you're right, but you're also missing that there are far better formats than ascii text for passing data from one machine to another, and what format to use really depends on what the data is.

    • 29athrowaway 1043 days ago
      There will be times where you will need to optimize a routine that runs very frequently or takes a long time to execute, and you'll have to resort to stuff that makes it harder to understand and maintain.

      But, that's a last resort problem solving approach, and should be the exception not the rule.

      • djmips 1043 days ago
        Depends on your field.
  • tarkin2 1043 days ago
    The more code/less code debate can be seen in language learning. Initially, you're happy you can use a large amount of language well. Later, you're happy if you can articulate yourself in as few words as possible.

    I would prefer a developer who can work with a large amount of code. I would prefer, even more, a developer who can write the same thing with less code. Generally speaking, a developer doesn't gain the ability to the do the latter without first doing the former.

    And there's an annoying phase in the middle where "less code" is condensed code.

  • flippinburgers 1043 days ago
    I don't know about this. Some of the junior devs I have had to work with modularize everything into, in this case, components to be used by react just to save a line of code or two. Understanding what is happening on the page requires drilling down through multiple file/function jumps.

    I cannot stand that approach. The real tell is that none of them have ever used a raw html element in any of the code they have written. It is more or less custom components on top of something like material-ui or bust! Yikes.

  • m3kw9 1043 days ago
    One cannot judge programmer in a silo. A good developer gets the job done and within the overall requirement of the team and aligns with goal of the team or company they are working for. Without knowing and the need to do that you will only be writing code for yourself and to your liking. The determination of good is based on the people that hired you and based on how your code helped to meet their overall goals.

    So in one company you can be a good programmer, in another you could be a hindrance.

  • tonymet 1043 days ago
    I find double negative articles very difficult to comprehend . Way easier to say : these are the best practices .
  • blendo 1043 days ago
    The worst developer I knew never wrote things down: requirements, comments, test plans, and bug reports were only communicated verbally. Even worse, their boss had the same mental block about putting anything in writing.

    Oh, and to echo another comment here, they just LOVED cyclomatic complexity.

  • andredz 1043 days ago
    The way of presenting reminded me of this video: https://www.youtube.com/watch?v=LO1mTELoj6o (7 Ways to Maximize Misery) and also reminded me of the 10 commandments.
  • seanalltogether 1043 days ago
    I have one more to add

    "Don't worry about failure conditions" - Just code everything to the happy path

  • gfiorav 1043 days ago
    The part about writing more code... I depends on your definition of "developer". If you're a lone wolf, sure, make your own code as compact as possible and it doesn't matter if no one can understand it.

    If you work in a team or a joint repo...

  • stakkur 1043 days ago
    There's a very good article by James Clear related to the Carl Jacobi quote that opens the post:

    https://jamesclear.com/inversion

  • tdsamardzhiev 1043 days ago
    I've worked with some great programmers who check all the boxes. It gets harder and harder to have a reasonable discussion about programming as some generic type of activity.
    • guenthert 1043 days ago
      Indeed. It's not that just developer experience and skill matters. Team size, project size, nature of the project (firmware for a medical device or space probe will clearly require a different level of scrutiny than e.g. a game), point in time of project life cycle (are we talking PoC or post-release enhancement/fixes?) etc.
  • daadzp 1043 days ago
    This is written more like a puff piece for a resume than an actual substantive article. I've been a professional developer for a long time and the real solution is "all things with a grain of salt".

    > So if you never assume that you might have blown things up, you will start blaming other things – your peers, the stupid framework you are using, an outdated browser or a pre-historic OS. Anything will be responsible but you. And if you never admit your mistakes, you are cursed to never evolve. And not evolving as a developer is fatal.

    If your test suite is comprehensive I've found it's often the case there's some external variable outside of your control that wasn't accounted for. This may or may not be a bug and may or may not need to be accounted for. Sometimes it's as simple as "upgrade your browser" or "we don't support that input, that is why you get an exception". Just as this person seems keen to blame the developer, it's often the user who blames the developer for their own shortcomings.

    > If you lose track of this, you have become a bureaucrat. And well, it’s pretty hard for a bureaucrat to be a good developer.

    98% of my job as a senior IC is bureaucratic nonsense. No one cares what code I write. No one cares about elegance. They care about a solution on time, and most importantly on budget. This is a failing of nu-agile where engineers are micromanaged to death by "certified PMs".

    > But even if you don’t, you are halfway through to the solution and a fresh pair of eyes will be much more effective in the process of helping you.

    "Be assertive" is such a poor way of saying "use rubberduck debugging". Especially in the context of writing code.

    > Take pleasure in writing more code

    There have been many times I've gone out of my way to make my code more verbose (within reason) to increase clarity for my juniors. I don't do this as a habit but again "all things with a grain of salt".

    > It’s pretty clear that your workload is proportional to the amount of code.

    This is so untrue I don't even know where to start. I can make a counter example 10 line function that needs 30 tests. In fact, a lot of real algorithms are this way. Going by line count/test ratio is a bad developer habit and this guy is coming off like a bad developer.

    > Think about what makes a text enjoyable to you. It is usually concise, clear, direct, meaningful and consistent. You won’t enjoy reading when you can’t understand the author

    This sentence is wildly ambiguous. On one hand the author advocates writing clear, meaningful, and concise code, and on the other hand they advocate (by omission) being as verbose as possible all the time. I make frequent use of higher order functions to stop cluttering my code with simple loops for sums, operations over a list, etc. Would the author consider me a bad developer because not everyone understands these simple constructs?

    > I hope that you find the above rules useful in your quest of becoming a bad developer. But if you ever change your mind and decide to grow into a good one instead, well, you now know what you need to avoid.

    Ah, hell hath no fury like the hubris of a bad developer telling other developers how to be good.

  • sometimesshit 1043 days ago
    You can be a one when you start to learn (and use) BrainFuck.
  • xzcxzxczxzxc 1043 days ago
    To become a bad developer you first need to be a good developer. Once good, the only way to become a bad developer is starting to work for the wrong company, dark patterns, viruses, etc..
  • roopawl 1043 days ago
    Meh
  • lpapez 1043 days ago
    This is just generic regular advice but sentences are negated...
  • FirstLvR 1043 days ago
    funny thing is this article can help you by NOT following his advice

    wich is, unironically, the purpose of the title haha

  • rob74 1043 days ago
    Interesting thoughts... and also well-written, although with some exceptions. For example, I read more and more phrases like this these days:

    > Always try to understand what’s the purpose of the task you’ve been assigned to.

    Shouldn't that be "Always try to understand what the purpose of the task you’ve been assigned [to] is" ? Is this a new trend in (American) English?

    • sdevonoes 1043 days ago
      Based on the name of the website, I would say the author is not a native English speaker. I'm neither. To be honest I understand his sentence better than yours (even though yours is supposed to be gramatically correct). Interesting, don't you think?
    • developer93 1043 days ago
      It's a little awkward but I don't think it's technically incorrect
    • dboreham 1043 days ago
      Your assigned tasks.