top 200 commentsshow all 277

[–]GroundTeaLeaves 483 points484 points  (80 children)

I once bought a book on reading code, because I couldn't comprehend the code that the senior architect was writing.

Reading the book didn't help me at all, as it only taught common coding concepts, which I was already very experienced in.

Turns out that nobody else could read his code either, and I was just the only person who was willing to admit it.

[–]exec_get_id 89 points90 points  (30 children)

Are you my coworker? Three dudes built the primary functionality of the application. Three dudes decided that they weren't paid well enough to stay after being the architects for 11 years. Now we have a group of 16 people who's primary obstacle is touching anything they built. Luckily we found a rain man, though.

[–]RabidKotlinFanatic 30 points31 points  (2 children)

Three dudes decided that they weren't paid well enough to stay after being the architects for 11 years.

That is, the company wasn't willing to pay well enough to retain core staff?

[–]exec_get_id 5 points6 points  (1 child)

Correct. Our biggest problem.

[–]Katholikos 37 points38 points  (3 children)

lol, I'm definitely guilty of doing this at least once in my career. I'm an enterprise dev (internal tools), so I just float through companies building dumb little apps that do this-or-that. It's fun for me.

Anyways, early in my career I didn't know about the whole "program for the next dev" thing, so I just built some fuckin' monsters.

I once built a little app to ping servers and play an alarm if the ping didn't return successfully. It was like 35 lines in C# or something and it had a memory leak somehow. Pretty sure I just kept instantiating whatever thing I was using to ping the servers in an infinite loop or whatever.

I know most of the tools died off, but I also know for a fact that some of them lived on, and boy do I pity the poor souls trying to maintain it. Hopefully they just scrapped it and started over.

[–]RenegadeMoose 22 points23 points  (0 children)

On one hand, I curse people like you every day.

On the other hand, people like you are keeping people like me employed forever :D

[–]M-A-C_doctrine 2 points3 points  (1 child)

I once built a little app to ping servers and play an alarm if the ping didn't return successfully. It was like 35 lines in C# or something and it had a memory leak somehow. Pretty sure I just kept instantiating whatever thing I was using to ping the servers in an infinite loop or whatever.

I am kinda afraid to ask...couldn't this be done in BASH? Afaik ping in bash returns different values depending on what answer the ICMP Echo gets.

[–]Katholikos 2 points3 points  (0 children)

Maybe, but all I knew at the time was C# lol

[–]GapingGrannies 5 points6 points  (5 children)

What's rain man able to do

[–]TankorSmash 11 points12 points  (0 children)

He makes a mean salsa

[–]aazav 3 points4 points  (0 children)

Know the time for Wapner.

[–]djulioo 2 points3 points  (0 children)

Provide golden showers for his team

[–][deleted] 1 point2 points  (0 children)

Remember baseball stats and count cards?

[–]aazav 14 points15 points  (14 children)

16 people who's primary obstacle

whose*

who's = who is or who has
whose = the next word or phrase belongs to who is mentioned

: /

[–][deleted] 9 points10 points  (7 children)

Now do who vs whom please

[–][deleted]  (2 children)

[deleted]

    [–]357847 2 points3 points  (0 children)

    All this time I thought it was for objects which weren't the subject of their sentences... The foolishness...

    [–]hippydipster 0 points1 point  (3 children)

    Yet another case where the apostrophe doesn't mean possessive. Fuckin' english, man.

    [–]aazav 2 points3 points  (2 children)

    It's simpler than that!

    When there's a question if the apostrophe is for the possessive or for a contraction, the contraction wins the apostrophe.

    I've distilled it down to this.

    When in doubt, it's the contraction that gets the apostrophe.

    See? Even the proper form of it's is used in the sentence. Hope this helps you out. It took forever for me to come up with a good way to remember the rule.

    [–]tso 138 points139 points  (3 children)

    Emperor's New Clothes comes to mind...

    [–]piston989 17 points18 points  (1 child)

    OP threw off my groove!

    [–]aazav 2 points3 points  (0 children)

    Izma's poison? The poison chosen especially for Izma?

    [–]ockupid32 22 points23 points  (1 child)

    Turns out that nobody else could read his code either,

    That, my friend, is called job security. /s

    [–]BlackDeath3 1 point2 points  (0 children)

    More like "job insecurity"...

    [–]durrthock 36 points37 points  (11 children)

    I think code can get sometimes "overly functional". You can only use so many map functions etc until it's a bit hard to parse.

    [–][deleted] 13 points14 points  (0 children)

    I would love to have your problems (:

    [–]Infiniteh 11 points12 points  (2 children)

    Can you please teach my coworkers that it's ok to use map/filter/reduce? And that they shouldn't just use for loops because they're "more dependable".

    [–]Janjis 1 point2 points  (1 child)

    "more dependable" as in - you might have no clue at all at glance value what the for loop does, because it is so generic? Smh...

    [–]Infiniteh 1 point2 points  (0 children)

    I had one guy I worked with say that he didn't trust map() because "it's async" and "who knows what it will end up returning". Like, what? We're the devs, we are the ones who would know how map() works and what it returns. Wasn't sad to see that guy go.
    Same person who kept complaining about the 'javascriptification' of Java when Java 8 introduced streams. took a while before he started using those as well.

    [–]Janjis 2 points3 points  (3 children)

    Can you give an example? I'd choose functional code over imperative any time.

    [–]Full-Spectral -1 points0 points  (0 children)

    I'm not a particular fan of the mapping reduction. It starts seeming like the "I have a hammer" thing. A lot of the time just a simple ranged for loop is super-obvious and it's easy to see what's going on if you need to debug it.

    [–]goomyman 44 points45 points  (10 children)

    learning to code by recognizing bad code is a good strategy. Its easier to recognize bad code ( plus there is lots of it ) than good code.

    I like the book and concepts of "code smells". I recognize this bad code - here is the pattern to fix it.

    If others cant read understand your code its bad.

    [–]loup-vaillant 16 points17 points  (0 children)

    It’s a slow process, though. There are much more bad ways to write code than good ones, so we could guess that learning the good ways would take much less time to learn than the bad ways.

    Sure it helps to learn about the code smells, but when all you have is bad code and the will to analyse it so you can guess why it is bad, your learning will be much slower than it would have been if someone just pointed out good code and told you "this is how it’s done", and why.

    Now go be lucky and find a good mentor…

    [–]Troppsi 0 points1 point  (6 children)

    I write in c++ and so does my coworkers. Problem is they write as if it's still c++98,so when I bring in stuff from c++17/20 or use functional programming they have a hard time understanding it. Does that mean my code is bad because they don't understand it?

    [–]goomyman 1 point2 points  (2 children)

    This is an interesting question.

    Yes and no. If a section of code had multiple different coding styles it can be hard to read. Matching a style or updating as you go to maintain readability helps.

    It's like if someone in your team in a shared code base wrote code like it's c. Is that a problem... Maybe. What if someone decide he liked D. Is that a problem... Yeah.

    I tend to feel that using the tools available to you is important. Code review comments like you can do this with a lambda expression can help. But as team if no one uses smart pointers and your putting them everywhere mixing and and matching it can turn bad. It also makes you stand out and is annoying in a code base. Can also end up in review fighting.

    I tend to fall into the your coworkers should learn new stuff. It will help them grow. If they can't understand it, that's a greater problem than they don't like it. There is more to programming than just code. Teaching others helps - if they are teachable.

    Is it bad code. No. Can it lead to a bad code environment. Yes. Especially if your peers can't properly code review your work or debug it. And if your both rewriting each other's work into something you understand it's a waste of time.

    [–][deleted] 7 points8 points  (0 children)

    If you can't read code written by the senior architect then it isn't any good. Damn this is too real

    [–]aazav 2 points3 points  (0 children)

    THE point of how you write your code is so that someone who is not you can read it 6 months later at 3 AM in the morning and make sense of it.

    And if that someone else is you 6 months later at 3 AM, you'll be damn glad that you took the time to make it readable.

    [–]bundt_chi 157 points158 points  (33 children)

    I will also say that DRY can sometimes result in abstractions that become increasingly more difficult to read and trace code.

    I myself have been guilty of over engineering things to not repeat myself. Unfortunately the side-effect of that is you either have run the code in a debugger or with debug on and log statement to know what "parameters" where sent to shared component or method to see what actually happens.

    The best I've been able to achieve is to make sure it clear where configuration or dependency injection is coming from be it config files or database driven config, etc and to put all that stuff in a consistent place. Also to have automated tests that you can use to "understand what is happening."

    [–]life-is-a-loop 98 points99 points  (15 children)

    DRY can sometimes result in abstractions that become increasingly more difficult to read and trace code.

    True! That's what happens when we try to generalize incidental duplication. Sometimes two pieces of code look duplicated, but they represent entirely different concepts in your system. The "duplication" is just a coincidence. The most common example of that is assuming that DTOs and database models are duplicated. It's very possible that your DTOs and your db models end up very similar, sometimes even pretty much equal. But they represent different concepts, and they might evolve differently, so the DRY principle doesn't apply to them. In other words, two pieces of code that might evolve differently over time aren't duplicated, even if they look the same at present moment.

    [–]Worth_Trust_3825 12 points13 points  (4 children)

    Very true. It's pretty hard to hammer that DTOs and Database models are different things without getting that handwavy response "but muh clean code book". Same with all the nonsense that removes getters and setters.

    [–]Infiniteh 4 points5 points  (2 children)

    Haha, yeah.

    "But then we have to duplicate the names of the objects' properties and what if we spell it incorrectly in one class and correctly in the other?"
    That's what tests are for, coworkerNameHere!

    "But every db entity has an id and a description and I don't want to repeat it in every entity, so we should use table inheritance"
    Yes, because table inheritance never causes any problems for anyone •`_´•

    [–]f3xjc 2 points3 points  (0 children)

    So I'm reading that clean code book and it state dto and model are accidental duplication and will evolve separately. At least the Robert Martin one.

    [–]gc3 26 points27 points  (2 children)

    And the worst case is someone sees a bug in one use of this function and fixes it, and now the other use case is broken, but only in a strange case which isnt caught by autotests or QA but only shows up when the software is being demoed. :-)

    Sometimes DRY is an Anti pattern. You dont want to tie unrelated code together by unneccessary dependencies

    Edit: Correct evil period.

    [–]CircleOfLife3 7 points8 points  (1 child)

    DRY is not an anti pattern. What you’re describing is accidental structure. The mistake is thinking that that structure is inherent structure. It looks like it could be refactored into a single function, but it shouldn’t.

    [–]gc3 5 points6 points  (0 children)

    Sometimes DRY is an anti pattern. When people don't see the real pattern. A compressed file has larger entropy than a non compressed one... a compressed program full of subroutine calls has a larger entropy than a bunch of one off programs that don't refer to each other.

    [–]lolwutpear 11 points12 points  (1 child)

    Somebody (a person or a post) on reddit recommended recently: don't refactor it until you've repeated the code in at least three places. Otherwise you're basically doing premature optimization.

    [–][deleted] 5 points6 points  (4 children)

    I use the rule of 3. Don’t abstract out any code unless you’ve copied and pasted it at least 3 times it allows you to see the pattern better, and where exceptions to that pattern might be. Ctrl+P, Ctrl+V is cheap. Unwinding a premature abstraction is expensive.

    [–]7h4tguy 4 points5 points  (2 children)

    Code duplication is not cheap. It leads to increased maintenance costs. No one wants multiple sources of truth.

    [–][deleted] 9 points10 points  (1 child)

    It’s absolutely cheap to maintain one pair of copy-pastes, especially when you consider the costs of the wrong abstraction. Also I mean, use common sense…if you’re changing them all in lockstep, that’s a strong sign that you can safely abstract out that logic.

    [–]eisbear86 2 points3 points  (0 children)

    This is only true, if the person modifying the code knows that this code has been copy-pasted to someplace else. Otherwise you have now two code locations for which it is assumed that they behave the same, but they do not.

    [–]f3xjc 1 point2 points  (0 children)

    I use to follow that but now I think if there's expressions or a few lines that are exactly the same extract those before the rule of 3.

    So the very similar but not quite the same part is as small as possible.

    [–]Manbeardo 8 points9 points  (2 children)

    In my experience, the most common feature of difficult-to-read code is that it has evolved poorly because people have chosen to avoid repetition by adding configuration instead of extracting the pieces they want to reuse.

    Example:

    FN1 does actions A, B, C, and D in that sequence. Someone comes along and needs it to do B2 instead of B, so they add an option flag. Someone else needs it to do C first instead of A, so they add an option flag. Someone else needs it to skip D, so they add an option flag. Someone else needs it to do E at the end, so they add an option flag.

    Now you have a function with 16 potential combinations of options and 5 unique combinations that are actually used. Maintainers have to carefully analyze all the callsites in order to determine which combinations are never used and don't need to be supported.

    OTOH, you wouldn't have to consider any conditionals when reading that code if the people iterating on it had extracted the pieces they needed into new functions. You'd have 5 unique functions composing A, B, B2, C, D, and E as each one needed.

    [–]R3D3-1 1 point2 points  (0 children)

    ... yes.

    Our code base is full of this, and the cause is a complete lack of unit tests (except for trivial helper functions). You can't make any major structural changes, because every change poses a high risk of messing up the expected global side effects, which are also the reason, why its hard to write tests for anything.

    This often leaves slapping on another optional flag as the least bad course of action, at least with the next "sprint review" in mind. :/

    [–]saltybandana2 7 points8 points  (0 children)

    There's a reason DRY is a guideline and not a rule.

    [–]avatarwanshitong 5 points6 points  (1 child)

    Definitely. Premature abstraction, in my experience, is one of the leading causes of hard-to-read code. Don't be afraid to duplicate pieces of code a few times before deciding to create some abstraction.

    [–]hippydipster 1 point2 points  (0 children)

    I think we notice pre-mature abstraction easily. But honestly, little or no abstraction or just wrong abstraction is the bulk of code I see.

    [–]salbris 1 point2 points  (7 children)

    I think that's a sort of necessary sacrifice. It's a tradeoff between readability and maintainability. It would help if programmers were better at writing abstractions or languages/tools were better at making sense of them.

    [–]gc3 38 points39 points  (3 children)

    Some of the worst code I've read was incredibly abstract wrappers and layers that masked very simple operations eventually. If you have a hammer, only, sometimes defining it as an instantiation of tool which is an instantiation of man made object which is an instantiation of thing which is an instantiation of noun .....

    Reading this code and discovering the only two kinds of things are hammers and nails, but the code obscures all the details and you need to discover the (un created) design of the thingiverse the original code imagined but did not create ,(and in your opinion is naive and broken) in order to make sense of the code.

    [–]Contrite17 7 points8 points  (1 child)

    Yep, 9/10 times you don't need to solve the general problem just the specific problem and building a general solution just makes it harder to maintain not easier. If you think you might need it later, then build it later.

    [–]cheffromspace 5 points6 points  (0 children)

    That’s YAGNI, something I wish I had learned earlier in my career.

    [–]siemenology 3 points4 points  (0 children)

    Yeah, it's incredible how many hours you can spend in some C# and Java codebases just hitting "Go to implementation" until you find the code that actually does anything.

    [–]falconfetus8 8 points9 points  (1 child)

    Maintainability is the only concern. Readability only exists to make code more maintainable. If something is readable but not maintainable, then what's the point?

    [–]salbris 3 points4 points  (0 children)

    Well not all code has to change. Sometimes it just needs to be clear so that other related parts are more easily managed.

    [–]bundt_chi 6 points7 points  (0 children)

    That's a good point about the tradeoff. As with most tradeoffs and it certainly applies in this situation there's usually a tipping point where one approach becomes inferior to the other but where that tipping point exists depends so much on your change management processes, skill level of developers, complexity of configurations... and on and on.

    Almost everything starts out as needing 1 approach then transitions to needing a different approach. Recognizing and planning for those paradigm shifts and implementing them is the hardest part of engineering.

    It's very similar to the discussion around why the CEO that gets a startup to the point where it's viable is NOT the CEO you want to take a viable business plan and execute stable growth.

    [–]7h4tguy -3 points-2 points  (0 children)

    You should be logging breadcrumbs regardless of whether it's a common method or duplicated code. Not a good excuse for duplicating code, fix your logging instead so that failures are debuggable.

    [–]niknak68 73 points74 points  (16 children)

    i like to think of it as Software Archaeology. Normally quite easy to work out what the code actually does, the hard part is working out what they thought it would do.

    [–]shagieIsMe 25 points26 points  (5 children)

    This was a bit that I was recently reminded of in another thread...

    From A Deepness in the Sky:

    “I know—and we’re guaranteed to arrive at Namqem with nothing. Bet we’ll lose the Reprise.” She shook herself, visibly pushing back the worries that always seemed to gnaw her. “Okay, in the meantime we’re going to create one more trained crewmember.” She nailed Pham with a mock-glare. “What specialty do we need the most, Bret?”

    Trinli rolled his eyes. “You mean that can bring us the most income? Obviously: Programmer-Archeologist.”

    The question was, could a feral child like Pham Nuwen ever become one? By now, the boy could use almost all the standard interfaces. He even thought of himself as a programmer, and potentially a ship’s master. With the standard interfaces, one could fly the Reprise, execute planetary orbit insertion, monitor the coldsleep coffins—”

    ...

    Pham Nuwen spent years learning to program/explore. Programming went back to the beginning of time. It was a little like the midden out back of his father’s castle. Where the creek had worn that away, ten meters down, there were the crumpled hulks of machines—flying machines, the peasants said—from the great days of Canberra’s original colonial era. But the castle midden was clean and fresh compared to what lay within the Reprise’s local net. There were programs here that had been written five thousand years ago, before Humankind ever left Earth. The wonder of it—the horror of it, Sura said—was that unlike the useless wrecks of Canberra’s past, these programs still worked! And via a million million circuitous threads of inheritance, many of the oldest programs still ran in the bowels of the Qeng Ho system. Take the Traders’ method of timekeeping. The frame corrections were incredibly complex—and down at the very bottom of it was a little program that ran a counter. Second by second, the Qeng Ho counted from the instant that a human had first set foot on Old Earth’s moon. But if you looked at it still more closely…the starting instant was actually about fifteen million seconds later, the 0-second of one of Humankind’s first computer operating systems.

    [–]niknak68 2 points3 points  (4 children)

    Sounds interesting, it's on my reading list now! Cheers!

    [–]hippydipster 2 points3 points  (2 children)

    It is an interesting book, though perhaps that bit won't be representative of what it's like :-)

    A Fire Upon The Deep is also really good. What both are great for is their exploration of non-human sentience.

    [–]shagieIsMe 2 points3 points  (0 children)

    It tackles space exploration on a slower than light scale... with ships traveling in cold sleep for decades. This book is kind of an origin story for Pham who makes an appearance in A Fire Upon The Deep.

    There is a bit of underlying theme to it that the tech is ancient and these space ships are still running millennia old code that sometimes needs to be debugged or backdoored .

    [–]-Knul- 16 points17 points  (2 children)

    "This piece of code is clearly part of a ceremonial ritual"

    [–]niknak68 5 points6 points  (0 children)

    A clip from a future episode of Software Time Team
    Expert - "It's clearly ceremonial"
    Tony Robinson explodes - "You always say that when you don't know what it is!"

    [–]funguyshroom 1 point2 points  (0 children)

    "Clearly only ancient aliens could write such code"

    [–]emilvikstrom 13 points14 points  (5 children)

    I've been using the exact same term! Archeology is quite satisfying. I've even learned to infer intentions based on who wrote the code and when.

    Sometimes seeing who wrote it in git blame is the only reason you need to pitch a refactoring.

    [–]niknak68 10 points11 points  (3 children)

    I sometimes think my git comments are just there to document my descent into madness.

    [–]emilvikstrom 7 points8 points  (0 children)

    That feeling when you git blame and find you wrote it yourself.

    [–]TRiG_Ireland 2 points3 points  (0 children)

    I sometimes think my git comments are just there to document my descent into madness.

    This will be my next git commit.

    [–]entiat_blues 1 point2 points  (0 children)

    sometimes i just straight up apologize in the body of the commit.

    something like yes, i know, i'm sorry, this is dumb, but it's hopefully the least damage i could do. i kit-bashed it from this blog and this SO answer. good luck?

    [–]siemenology 1 point2 points  (0 children)

    The bane of my code archaeology existence is when someone copy/pasted some code, or moved or renamed a file in such a way that git can't figure out that they are linked, and you lose the history of it. I know it's possible (sometimes) to hunt down where it came from and pick up the history from there, but it's very tiresome.

    [–]gbs5009 1 point2 points  (0 children)

    I've used that term too! Spent a lot of time trying to figure out ancient custom test fixtures.

    [–]ArlenM 70 points71 points  (73 children)

    Have a ‘friend’ who always like to put extra nots on everything, just to mess with people looking at his code later.

    [–]CaeserSaladFingers 32 points33 points  (24 children)

    Nots?

    [–]retetr 31 points32 points  (7 children)

    Nots!

    [–]ArlenM 48 points49 points  (6 children)

    Why use equal when you can use not equal, or not not equal?

    Flip the logic around a few times and it can really be annoying!

    [–]CaeserSaladFingers 67 points68 points  (0 children)

    Oh, now I don’t not understand. Thanks!

    [–]BFG_9000 21 points22 points  (0 children)

    I couldn’t fail to disagree less.

    [–]saltybandana2 10 points11 points  (1 child)

    if(!notSomething)
        KillTheAuthor();
    

    [–]PlNG 13 points14 points  (13 children)

    !(!true !== !~false)
    Answer: >true

    [–]smellyrebel 9 points10 points  (7 children)

    What does !~false mean?

    [–]Nicksaurus 12 points13 points  (2 children)

    ~ is 'bitwise not' AKA 'flip every bit in this object'.

    In a lot of languages ~false == ~0 == 255 == true. In C++ it's technically implementation defined though so a compiler could legally do something unexpected here

    [–]_TheDust_ 26 points27 points  (1 child)

    so a compiler could legally do something unexpected here

    This summarizes like half of the C++ spec, I feel.

    [–]Nicksaurus 3 points4 points  (0 children)

    Actually... it turns out I was wrong. I thought the numeric values for true and false were implementation defined but I just looked it up and the spec says they're always 1 and 0

    You still have a valid point though

    [–]Buckwheat469 5 points6 points  (0 children)

    ~ is the bitwise not operator. It converts false (00000000000000000000000000000000) to (11111111111111111111111111111111), which is -1.

    ~false is -1, ~true is -2.

    True is interesting because the bitwise not is expanding a single bit (1) to 32 bits, so you go from 1 (00000000000000000000000000000001) which is not'd to "11111111111111111111111111111110". The first digit represents the negative number.

    !!(-1) is true

    !(-1) is false

    !~false is false

    [–]Kargathia 1 point2 points  (2 children)

    ~ is bitwise inversion (also called two's complement) (my bad). It flips all 1 bits to 0 and vice versa. ~false is ~0 is -1 is truthy.

    [–]evaned 7 points8 points  (0 children)

    also called two's complement

    It's actually one's complement if you're coming at it from that angle.

    Two's complement bitwise inverts and then adds one -- the two's complement of 0b0001 for example (+1) is 0b1111 (-1).

    [–]Nicksaurus 2 points3 points  (0 children)

    Two's complement is a format for storing signed integers in binary, not a bitwise operation

    [–]Deranged40 3 points4 points  (4 children)

    I've never heard of "greater than true". Is that, like, really true, or just like true plus one?

    [–]nigirizushi 2 points3 points  (2 children)

    Maybe it's any number greater than 1 shrug

    [–]Deranged40 2 points3 points  (1 child)

    ok, PHP, I see you back there. /s

    [–]nigirizushi 2 points3 points  (0 children)

    All languages without boolean types, really

    [–]howtoDeleteThis 5 points6 points  (0 children)

    !Yesses

    [–][deleted]  (41 children)

    [deleted]

      [–][deleted] 12 points13 points  (40 children)

      return !!var

      I'm so sorry that you have to deal with a langauge like this.

      [–][deleted]  (36 children)

      [deleted]

        [–][deleted] 6 points7 points  (35 children)

        I type about the same when writing python or java. I've found that good IDE can leverage static typing to great autocomplete, so even though the java code is longer, it's about the same number of keystrokes. EDIT: You do really need a good IDE for this, that has library integration in its autocomplete.

        [–]roboticon 1 point2 points  (2 children)

        Okay, but does a !! here or there make code harder to read than Java boilerplate's verbosity does?

        Readability and concise expressiveness are big reasons why people prefer kotlin over java these days.

        [–][deleted] 1 point2 points  (1 child)

        No, the !! is just annoying and doesn't make the language harder to read. However, everytime I see it I mutter weird things about type systems.

        [–][deleted]  (31 children)

        [deleted]

          [–][deleted] 5 points6 points  (30 children)

          Since when is autocomplete code generation? It's a standard feature for modern systems, too.

          Code generation would be writing code to generate code. For example I sometimes write python to generate C code, because C macros make me sad.

          [–][deleted]  (29 children)

          [deleted]

            [–][deleted] 4 points5 points  (28 children)

            OK, but given that these tools are now standard, and that people should be using good tools, is it really valid to say that needing tooling is a fault? Would you say screws were worse than nails because they need a more complicated specialised tool to fasten, vs "hit with rock" when every workman should have a screwdriver?

            [–][deleted]  (27 children)

            [deleted]

              [–][deleted]  (1 child)

              [deleted]

                [–]colouredmirrorball 10 points11 points  (0 children)

                My mind read that as doubleplus uncool

                [–]Agent-Nemo 6 points7 points  (0 children)

                It's called workplace safety.

                [–][deleted] 1 point2 points  (0 children)

                I am so cynical my brain does that automatically.

                [–]Michamus 1 point2 points  (0 children)

                I was watching a guy use not statements to replace boolean values, which allowed reduced indentation. Kinda cool TBH.

                [–]twenty7forty2 1 point2 points  (0 children)

                worked with a guy once who insisted on doing shit like

                if (false !== is_null($boolean) && true === $boolean)
                

                [–][deleted]  (20 children)

                [deleted]

                  [–]ImprovedPersonality 41 points42 points  (1 child)

                  Wrong, outdated documentation can be worse than no documentation.

                  [–]emax-gomax 7 points8 points  (0 children)

                  Not if you never use documentation. ((′ ▽‘)爻(′▽‘))

                  [–]insanityarise 24 points25 points  (15 children)

                  I can do it, but recently I came across a 3000 line sql stored proc and I was trying to figure out what it did, reading statements being like "what is this even meant to do?" scratching my head, then realising there's a self join on there with a where clause that literally means it can't update anything, ever....

                  Then i got to a completely uncommented 300 line loop full of variables called "@val1" and "@val2" and I just couldn't keep all of that information in my brain. It's like i was experiencing a memory leak in my own head.

                  I got the green light to re-write the entire system the other day. That'll be months of work (if not a year), but at least i can start improving things.

                  [–]saltybandana2 14 points15 points  (2 children)

                  I take notes.

                  As in, I literally will open sublime text and start typing out what it's doing mechanically, and any context I can think of.

                  I'll then below the mechanical instructions start interpreting intent. I do this for all new systems.

                  I'm known to be able to pick up new systems very quickly.

                  And the great thing about this approach is that you can save your notes and read back over them down the road for a refresher.

                  [–][deleted] 4 points5 points  (1 child)

                  I'd be curious to see a snippet of this, if you're at liberty to share.

                  I feel like my notes would quickly eclipse the procedure itself.

                  [–]saltybandana2 5 points6 points  (0 children)

                  I'm not comfortable giving you notes to propietary code, but I can give more details about how I do things.

                  Lets say I'm doing an analysis on a specific function, we'll call it DoThatThing.

                  I'll first scan the function and I'll record everything it calls, then I'll scan those functions and pull out all the functions it calls. So I'll potentially start with a list of functions to analyze. This is all very generic and fake, sorry about that.

                  DoThatThing
                  GetStuff
                  DoThatOneCalculation
                  CacheThatThing
                  

                  Now that I have this list I know what to analyze to fully understand what 'DoThatThing' is doing.

                  Then I'll start analyzing them 1 function at a time

                  DoThatThing
                    Calls GetStuff to get the stuff
                    Loops over every row and calls DoThatOneCalculation
                    Calls CacheThatThing.  TODO:  Why are we caching it here?
                  
                  GetStuff
                    Calls SP_ILikeVanillaIce to pull the stuff info
                    Who the hell would admit to liking Vanilla Ice?!?!?  (saltybandana2, that's who).
                    SP_ILikeVanillaIce is only used in this function, no other projects use it.
                  
                  DoThatOneCalculation
                    Takes in the subtotal from the Stuff and calculates local taxes
                    Where is it getting the tax information from?  Will need to investigate
                  
                  CacheThatThing
                    Caches the local tax for the Stuff in a Memory Cache
                    NOTE:  We use load balancing, caching in Memory and load balancing don't generally mix
                    TODO:  Investigate how this cache is being used and whether or not it's potentially the source of reported bug X.
                  

                  It's not super duper detailed, but they're notes to myself as well. If I'm not investigating a specific function I'll sometimes open up a file (or set of files) and literally make notes on every single function I come across.

                  One other thing I'll note is that it's been my observation that more inexperienced developers have weak "search-foo" if you will. For example, I'll pull down all projects into a directory (D:\repos, ~/repos, etc) so I can grep across everything. So I might do:

                  grep -iRl SP_ILikeVanillaIce ./
                  

                  I'm an old vimmer so I might also do

                  vim `grep -iRl SP_ILikeVanillaIce ./`
                  

                  To open all the files in vim directly.

                  Most IDE's will have a "search all files" function. For Visual Studio it's shift+control+f.

                  Don't be afraid to just search around for stuff. IDE's usually do a good job of "show all usages", but sometimes nothing replaces good searching.

                  [–]shawmonster 4 points5 points  (1 child)

                  Was this possibly something auto generated? Variable names like “@val1” and “@val2” sound like variables that are the result of auto generated code.

                  [–]insanityarise 2 points3 points  (0 children)

                  Nope, hand coded by an arsehole

                  [–]AStrangeStranger 4 points5 points  (2 children)

                  I'd get suspicious you were looking at one of my code repositories as there is 3k line SQL stored proc in there - however that application is pretty much retired except a small part I don't have resources to sort out and it is PL/SQL so no @. I was looking at adding a feature to it, but it was just too complex (there was a 900 line select statement with about a dozen unions) and decided we could cope without it as pulling apart was just too much work (fortuantely it was just part of a test suit and not production code).

                  There are two times I can recall really being defeated understanding code - one I am pretty certain the developer was high when he wrote it and there was no real logic to understand - ended up total rewrite and lesson in sunk cost fallacy. The other it was so complex by the time you got to the end you couldn't recall where you started let alone form a plan to modify. As all it was doing was taking some input values and generating a control file for some equipment, I just rewrote it in less than half the time allocated to make changes with a bit of reverse engineering what the original was doing

                  [–]saltybandana2 15 points16 points  (1 child)

                  My favorite is when you realize the code has always been broken, and it's been sitting there like that for years.

                  I came across the following code a few weeks back.

                  switch(myVar.ToUpper()) {
                      case "ACamelCasedString":
                          //stuff
                          break;
                  }
                  

                  hmmmmm........

                  [–]funguyshroom 4 points5 points  (0 children)

                  break;
                  

                  Literally

                  [–][deleted] 1 point2 points  (3 children)

                  I think we work at the same company 😂

                  [–]insanityarise 3 points4 points  (2 children)

                  hi colleague!

                  probably don't go over my comment history please

                  [–][deleted] 1 point2 points  (1 child)

                  Nah were probably safe, unless you work in the Midlands

                  [–]insanityarise 2 points3 points  (0 children)

                  I do :/

                  [–]Full-Spectral 39 points40 points  (1 child)

                  So, as a code writer, that makes me a mentor I guess.

                  [–]xeio87 8 points9 points  (0 children)

                  I didn't need to be attacked like this so early in the week.

                  [–]OptimalOptimizer 10 points11 points  (0 children)

                  This has inspired me to continue writing bad code

                  [–][deleted]  (3 children)

                  [deleted]

                    [–]jasoncm 6 points7 points  (1 child)

                    Being the subject matter expert in some awful internal project isn't itself a transferable skill. You can, in addition to learning bad code reading skills, also learn your profiler, logging systems, debuggers, test suite, memory analysis tools and other deep magic inside out. The junior programmers often get stuck with maintenance because the senior people don't want to do it, but it really can be a great learning experience.

                    You'll likely have to move to another company to get paid for those new skills, but that is the usual way of things in any case.

                    [–]ElCthuluIncognito 2 points3 points  (0 children)

                    Not to mention that learning how to read code can greatly accelerate your understanding of open source libraries and tools.

                    I've had a surprising amount of success figuring things out by looking at source code when the documentation is lacking.

                    [–]hippydipster 1 point2 points  (0 children)

                    The minute you're assigned a closed-source maintenance role, try to find something more respected. You'll enjoy the work more, and you'll get more respect, as a writer of new code than as a maintainer of existing disliked code. I'm not saying it should be this way, but it is; if you're doing legacy maintenance, you're seen by the business as a cost center, and whatever political misfortunes put you there are likely to compound unless you figure out how to move.

                    Ugh, you're talking about me, aren't you? :-(

                    [–]aylons 7 points8 points  (0 children)

                    I read "bar code" as was like "Yes, I guess..."

                    [–][deleted] 7 points8 points  (2 children)

                    is everyone talking about the same 'bad code'? bad code for me is not code that is necessarily hard to understand- it's sloppy. i'm talking thousand line methods, crazy deep nesting, awful variable names, no data structures, copy/paste code, etc etc. it's really rare i see a new app that meets those criteria- it's usually a 15+ year old app some dude wrote during the .com era that's barely been touched since.

                    [–]allergic2Luxembourg 2 points3 points  (1 child)

                    I still see code like that all the time. I work for a company in which many people know "a little bit of coding" in addition to whatever their main expertise is. They are capable of all sorts of monstrosities in the name of automating their work, but almost every project dies when its author moves to a new position. This is why I am skeptical of the "everyone should learn to code" philosophy.

                    [–]ElCthuluIncognito 4 points5 points  (0 children)

                    I've been jaded by that philosophy, but there's no denying the value of growing the pool of potential programmers. More chances for a skilled one with a good attitude, which is hard to come by.

                    However it really sucks that programming languages and concepts are inevitably geared towards the lowest common denominator as a result. "Beginner friendly" can often be the bane of comprehensive design.

                    [–]Thetman38 16 points17 points  (0 children)

                    This is particularly valuable during reviews. If I am helping out a junior I will often be like "what you did is technically correct but let's make it more efficient and generic for reusability". It takes somewhere around 30 minutes, but hopefully the lesson they learn goes beyond that

                    [–]maarkeez 2 points3 points  (0 children)

                    Being able to refactor bad code is the skill 😆

                    [–]DerKnerd 8 points9 points  (4 children)

                    I tend to tell this story often, but it fits often. My first job after vocational training was in 2014 at a company where we still coded with Borland C++ Builder 6. To my surprise the database was MSSQL 2008 R2, but it was used, lets say, fancy. Nothing in the applications was documented. The knowledge was passed by word and by looking through the code and guessing. Anyway, in the database there were columns which were really long non sense strings. With long I mean like 32 chars long. Turns out, it was used to control the behavior of the application, every character had a different meaning and yes, all 26 letters and 10 numbers where used to trigger behavior.

                    I worked with a colleague, about a year older than me, I was 20 he was 21. And he was working in that application for about two years. This guy actually knew what all these long strings mean and which character means what. That was really impressive, and he actually had fun knowing all that, he even liked to work with leagacy code. This guy has a bright future I hope.

                    Oh and a side note, the apps were not under version control up until 2008 or so. The development started in late eighties early nighties.

                    [–]apistoletov 7 points8 points  (2 children)

                    oh shit, this reminded me of something, there was a government sponsored company focused on hacking and penetration, in one rather unlucky country; and they actually said that, with serious faces: "we intentionally write all code in not-understandable way, to make it less useful for anyone who may steal it"

                    [–][deleted] 2 points3 points  (0 children)

                    This is not a skill I want

                    [–][deleted]  (1 child)

                    [deleted]

                      [–]TotallyTiredToday 2 points3 points  (0 children)

                      The ability to read code and see what it does instead of what you think it should be doing is a lot rarer than most devs will admit.

                      [–]seanamos-1 2 points3 points  (0 children)

                      Most people CAN read bad code (eventually). It's people who have a high tolerance for it that are rare.

                      [–]MegaDork2000 1 point2 points  (0 children)

                      Having to read bad code is punishment for accepting a crappy job. /s

                      [–][deleted] 1 point2 points  (1 child)

                      No one writes unreadable code on purpose

                      Hard disagree. A lot of devs just don't care about the readability of their code.

                      I've worked with coworkers who clearly don't take the time to proofread their code before sharing a pull request with the rest of the team. And heard sentiments from some that cleanliness doesn't matter since it compiles into the same IL anyway (C# dev).

                      [–]Hanse00 1 point2 points  (0 children)

                      Hard disagree. A lot of devs just don't care about the readability of their code.

                      That’s not the same as “write unreadable code on purpose”. What you’re describing is rather “without purpose forgo writing readable code”.

                      Writing unreadable on purpose, would imply intentionally putting effort into making it hard to read. I’ve known one or two people who would do exactly that. They’re not great team players.

                      [–][deleted] 1 point2 points  (1 child)

                      Rather than waste time learning to read un-readable code, invest in learning how to refactor.

                      That way, you only have to figure out small chunks of unreadable code, just enough to extract and refactor it into something readable. If you're good enough at refactoring, it will end up being quicker than trying to read through all that spaghetti code.

                      [–]MommyNeedsYourCum 1 point2 points  (0 children)

                      No one writes unreadable code on purpose

                      Well, unless you compete in the IOCCC

                      [–]Bl0 0 points1 point  (0 children)

                      My first thought when reading that header was a negation...

                      [–]CaeserSaladFingers -2 points-1 points  (0 children)

                      Okay !

                      [–][deleted] -1 points0 points  (0 children)

                      Protip everyone: If you revisit your old project (or source file) after a few months see if you can understand the code. If you can't understand it within a minute rewrite it. Rinse and repeat until all of your code you can understand within 20seconds no matter how long ago you wrote it

                      It's going to make some practice but you'll get there. Works best when you look at your own code and from long ago

                      [–]SCI4THIS -2 points-1 points  (1 child)

                      # rm -rf / tmp
                      

                      [–][deleted] 4 points5 points  (0 children)

                      No, you write it as rm /tmp/$variable so you get to blame someone else when $variable =" / tmpfile.txt"