Settings

Theme

How to write unmantainable code (2015)

github.com

160 points by diegolo 3 years ago · 86 comments

Reader

Waterluvian 3 years ago

They forgot the masterpiece I saw years ago:

1. Give all your Python class members a tedious naming convention.

2. Be DRY by writing helper functions that do name lookup based on a string of the last half of the member name.

3. Be even more DRY by having the function guess a little if the match isn’t exact

You now have an application where you cannot search for where members are referenced.

  • ziml77 3 years ago

    I did something like step #2 in C# some years ago. Pulled data from the database based on the calling function’s name.

    Clean Code was mental poison for me and certainly led to a bunch of overly abstracted or overly-DRY code.

    • Waterluvian 3 years ago

      I feel like every coder has to overdo it at least once to truly grok why it is a balancing act. And I think that oftentimes leads to the discovery that every best practice is a balancing act.

      • bitexploder 3 years ago

        A good rule is two maybe even three duplications is ok. After that, probably tome to refactor at least a little. Often this rule of thumb saves some efforts.

        • idontwantthis 3 years ago

          W.E.T. then D.R.Y.

          (Write Everything Twice)

        • Rexxar 3 years ago

          The rule should not be primarily based on a number of duplications but if we know that all the duplicated parts need to be changed when one is changed.

      • ziml77 3 years ago

        You're probably right on that. I now weigh my options to try to find a middle ground between impossible to change because it wasn't designed for change and impossible to change because it was designed for too many future use cases that will never happen.

        • ahartmetz 3 years ago

          IME, extensible code comes from thinking of possible extensions and then not getting in their way, which usually just means keeping it simple. Easy to say but hard to do.

  • kayodelycaon 3 years ago

    Ah yes. Just like Ruby and meta-programming games with send, define_method, and method_missing.

    • Waterluvian 3 years ago

      They call it “reflection” because the more you use it, the more you ought to stop and reflect on your choices. ;)

    • matheusmoreira 3 years ago

      Yes. It's very easy to get addicted to that powerful Ruby stuff. Unlike C and Lisp though, there is no way to get a compiler to expand the macros and show you the resulting metaprogrammed source code. You can inspect the objects at runtime but it's cumbersome compared to reading source code.

      Sometimes repetition is good.

  • 9dev 3 years ago

    Oh, you mean like the oh-so-great Laravel framework, which is structured like this exclusively?

  • Tade0 3 years ago

    #2 Sounds like your typical Angular 1.x app.

    For some reason everyone tried to be clever with code reuse in them which almost always resulted in an unsearchable mess.

  • Stratoscope 3 years ago

    > Be even more DRY by having the function guess a little if the match isn’t exact

    At that point you'll be singing How DRY I Am!

    https://temperanceblues.web.illinois.edu/how-dry-i-am/

  • valand 3 years ago

    Be even more DRY by having function that does quite a bit of everything, accepts different arguments, and returns different type. You only need to supply different strings to the first parameter

  • eximius 3 years ago

    so, a normal ruby codebase?

  • glitchc 3 years ago

    Feels like a dad joke!

xyzelement 3 years ago

My first job out of college, my boss and I took over some code that was written by two genius PhDs (one math, one physics - we were working in finance.)

I noticed a variable (long word starting with z) used in a lot of places. Turns out it was the German word for "counter".

It was my first hint that most of the backend codebase was written as a competition between the two of them to seem the smartest.

On the front-end, I remember opening some many thousand line long file trying to figure it out. I scrolled pages and pages to the top of the file looking for a comment. I found one. The comment:

/* What is this shit? */

Written by someone who tried to help those guys.

  • haginile 3 years ago

    Similar story: a few years out of college I too inherited a codebase written in the 1990s by some genius phd, also in the finance field. Someone else clearly tried to clean it up before me. The word “WTF” was in comments throughout the codebase.

  • kwkelly 3 years ago

    The word with Z may be related to “zahlen” which is where Z as the letter commonly used to represent the integers comes from. [1]

    [1] https://en.wikipedia.org/wiki/Integer#History

  • ascotan 3 years ago

    Could be worse - my first was a program where someone had written the source in Delphi and run it through a Delphi -> C converter and then they threw away the original Delphi code. The resulting spaghetti was the only production code available.

  • dfee 3 years ago

    Gulp. I’ve left a comment like that or two. Probably isn’t helping the cause, but it’s waving a flag for the next person who’s got budget to clean it up.

  • tored 3 years ago

    T_PAAMAYIM_NEKUDOTAYIM

  • zcw100 3 years ago

    Maybe this would be a good use for AI code generation. Reversable non-obfuscated obfuscated code. If you just obfuscate it it's pretty obvious what you're doing but if an AI can obfuscate it in a what that looks like something that is plausible that you could have written it you'd get away with it. Reversable so that you could undo it make updates and then reobfuscale.

  • gfaregan 3 years ago

    Ten levels of C++ templates and typedefs are a pretty good way of proving how smart you are and making the code completely opaque.

  • heavyset_go 3 years ago

    That last anecdote is too relatable.

mtlmtlmtlmtl 3 years ago

This is the way it seems to go in the public sector, at least here in Norway.

1. Get an n year government contract for some huge public IT overhaul. E.g building a new hospital journal system for a large region(this example is real, google "helseplatformen")

2. Spend years developing this huge proprietary .net monolith with a waterfall model, and minimal user interaction and testing during most of the contract.

3. Release an MVP by the end of the contract that's barely suited for the task(inevitable due to inherently broken dev model) and causes a huge amount of problems

4. Get another n year contract to fix the thing

5. Print money.

  • matsemann 3 years ago

    I've done big government contracts for many years as a consultant in Norway, and haven't really seen this. Guess it's because Java is so much better than those .NET monoliths ;)

    But seriously, I guess it depends on the maturity of those writing the tender / anbud. Too often they get bamboozled by big4 like consultancies (Accenture, Sopra Steria etc..) that act more like project managers and sales people than developers.

    The company I used to work for actually stopped giving offers on lots of these kind of projects. None of us wanted to work on these kind of bureaucratic nightmares where one is set up to fail. It's much more fun to deliver something of value, even if one doing something else could've squeezed out some more money. We "fired" clients that didn't give us opportunity to actually do good or have an impact.

    I think more of these public sector tenders should stop focusing on "projects", and instead focusing on just getting the correct people that can help them iteratively move in the correct direction.

    Unfortunately it's often hard to get money for this. Easier to say "we need X millions for this huge project".

    • mtlmtlmtlmtl 3 years ago

      Thanks for the insider perspective. My experience as a dev in this sector is limited to interviewing for a few consultancies and noping out once I got a look at the code. But most massively public systems I interact with regularly seem to track with both our POVs. Of course the client side is definitely at fault too, for being naïve about these consulting firms.

      I wholly agree with you that big projects are not the way to go. I think a push towards open source would greatly improve accountability. And I don't see why say the tax reporting system needs to be proprietary besides a thin veil of security through obscurity.

      • matsemann 3 years ago

        I was at NAV during their big transformation. The first year I was there, it was this huge billion kroner project. Probably more money was spent on business consultants speccing the project than developers. My company constantly complained about this way of working, that it will only lead to failure. Of course it did with missed deadlines etc, and eventually the huge project was scrapped.

        They got a new director of IT, and managed to hire some hard-hitters internally as well. No longer listening to snake oil consultants, they finally started working the way we wanted. Smaller projects, if projects at all. More continuous deliveries. We got ownership all the way to production instead of just sending our code to some server people to deploy 4 times a year. All the code got open sourced etc. And us as consultants actually preferred this. Our company got paid essentially the same, but now we actually delivered value and worked with them instead of an uphill battle "against" them.

      • actionfromafar 3 years ago

        Job security through obscurity.

  • jongjong 3 years ago

    The worst part is that the people who work for these companies who work for the government think that they're efficient. In reality, there are often startups out there which could build the same system better in 1/10th of the time.

    The bigger an organization is, the more easy money they have, the worst their expectations are when it comes to software development. I once worked for such a company as a software developer and I was shocked that I kept getting positive reviews in spite of being the laziest I had ever been. I was spending most of my time watching videos on YouTube; but the little work I did between YouTube videos was somehow better than that of their average employee...

    • ozim 3 years ago

      Worst part is that even if you are efficient startup you are not going to get government contract because of red tape and also to get such contract you have to know right people.

      Then even if you get such contract you probably stop being efficient - because of red tape and lack of incentives to still be efficient because money will flow either you are efficient or not.

  • kabes 3 years ago

    I've been involved in some big public sector projects and it indeed went like this, but I'd say most of the blame was on the government.

    The tender requirements were written by a general tender-writing team of the government.

    We only got to meet the actual users of the software-to-build after we'd won the tender. Apparently what was in the tender was a complete mismatch with what the actual users wanted (as far as they actually knew what they wanted).

    What the users wanted didn't matter, because payment was based on checking off all tender requirements. Oh, one of the tender requirements was "all business logic needs to be configurable by the users" and more gems like that.

  • saiya-jin 3 years ago

    Definitely true in Denmark too, their back in 2010s new tax IT system (skat-something) made a friend of mine who was sub-subcontracted from his 1-man company a wealthy man (wealthy as fully pay for small flat in central Prague, then for big flat a bit more off and then land & building a house a bit further away, only from income from this within few years, with 2 kids and wife not working).

    When you get most of daily contractor fees directly, you easily end up with 15,000k$ net monthly income, working mostly remotely, in a country that had median monthly income below 1,000$.

    Not that he worked hard or anything, frequently fridays looked like 'ok I am free give me some work' which almost never came. It was done on some ancient long dead weblogic/wslt things, stuff I can hack together in ie apache camel or similar in few afternoons (not 100% of it but core definitely yes).

    Definitely a fault of government, no private company will come and say 'hey we can do it in 10% of the time / costs but we wont be using these big brand technologies (TM)'. Can't imagine there wasnt some big corruption too. IIRC prod launch was some major clusterfuck which filled newspapers for some time.

  • ElfinTrousers 3 years ago

    Sounds like my experience with software procurement in state government in the USA. The basic problem as I see it is that the companies that get contracts aren't especially good at writing software, where they really shine is in understanding the intricacies of the procurement process.

    • magicalhippo 3 years ago

      > The basic problem as I see it is that the companies that get contracts aren't especially good at writing software

      At least here in Norway, a huge part I think is that the buyer doesn't have a good grip on what they need. The people making writing the bids or managing the projects are too far removed from the day-to-day operation to write down proper requirements.

      Don't get me wrong, it's hard. But for these large projects I think many would have gone a whole lot better if the buyer had spent more time understanding their own organization and their needs before doing these large projects.

  • pryelluw 3 years ago

    Bad software is universal. It’s purpose is to milk the public tit. Not to deliver actual value. The value is in the money being paid.

  • 2OEH8eoCRo0 3 years ago

    Sounds like defense industry software. You have super geniuses laying down the actual design and hardware in a few years and troglodytes writing the code for 20 years.

praptak 3 years ago

The section on naming is amateur. Names like `fred` or 'asdf' are too obviously meaningless and wouldn't even pass a code review.

You want names that do describe your code but badly. If your function reads policies from the DB, filters them and calculates some missing data, be sure to name the function 'readPolicies'. Nobody will look at that function when chasing a bug related to the filtering part!

You may want to spread it across a few changes to get plausible deniability. You may also "fix" the name by changing it to something hopelessly generic like `initializeState`.

  • adammarples 3 years ago

    My favourite python function, get_data. Takes a dictionary called 'config'. Mutates it, sends it to another function called load_data. No docstrings anywhere.

    • PainfullyNormal 3 years ago

      We had stuff like that all over the place in the last React codebase I worked on. Naming things is hard, especially when you have to name them four times: once for the hook, once for the function that can potentially be called outside of the hook (non-react code), once for the API call, and once again for the graphql query.

deterministic 3 years ago

Heh. The author forgot the most important one:

Use micro-services! The more the better! And write each micro-service using a different programming language and build system. Make sure the protocols are not documented. And that the micro-services are called p376, f190 etc. Make sure that some micro-services need to access a specific server setup to build!

  • hinkley 3 years ago

    Pfft. You haven’t lived until you have introduced a circular dependency between two or three modules.

csours 3 years ago

I just reworked some java code that is deployed INSIDE an oracle database. You can load java classes into oracle and use them like functions.

So I would say: find the most obscure place you can deploy code, and make sure it is not testable.

  • sureglymop 3 years ago

    I did this at my last job. It's truly astonishing how much can run inside the database. Your whole application and business logic if desired. I wrote a lot of PL/SQL which actually was not that unpleasant although god knows who can maintain that after I'm gone.

    What I saw there in particular was that any given team will try to solve their problems in their domain. For example, I was in the database administrator team, and they tried to do everything in the database and use database features for everything. Then you have the DevOps/Middleware team who try to do everything in pipelines and with ansible scripts etc.

    The best thing you could invest in imo. to be a good allrounder is really good knowledge of unix(like) systems and a shell which is available everywhere.

    Write your cicd pipeline logic as shell scripts instead of e.g. the dsl of gitlab/github. That'll be usable in every domain!

SCLeo 3 years ago

> Hungarian Notation is the tactical nuclear weapon of source code obfuscation techniques; use it! Due to the sheer volume of source code contaminated by this idiom nothing can kill a maintenance engineer faster than a well planned Hungarian Notation attack. The following tips will help you corrupt the original intent of Hungarian Notation:

I can't stop laughing.

  • cerved 3 years ago

      m_bIsLaughing
    
    There should be more tips, like use "l" as a prefix to any number, like shorts. Also, make sure to sometimes distinguish shorts, ints and sometimes not!

    Also, when you've accumulated about ten years of this, start using a different making scheme and make sure there are preferably random bits of Hungarian notation around. Make sure there's no record of why and no explanation of what Hungarian notation is and how to use it.

steveBK123 3 years ago

Worked with some guys like this, probably doing it intentionally. One guy liked single-letter vars & derivatives thereof. For example all the following might appear in the same 100 lines of code: a, aa, a_, aa_, aa__, A, AA, A_, AA_.

Often these were crazy code forking paths like:

* a is a 1 liner which calls a_ or aa depending on a conditional.

* a_ then returns something or calls a__ depending on a conditional.

* aa calls aa_ or aa__ depending..

* A, AA, A_ and AA__ might be some global states or boolean flags or cmdline args or env vars read in which effect all the above..

Another favorite was to use the same noun in different cases for different types of things. For example:

* servers - a function you call which returns a list of servers

* servers_ - a subfunction called by servers

* SERVERS - a boolean global variable switch to enable functionality

* Servers - a variable containing the list of servers used by all of the above

I once asked him to explain the differences and there was no consistency. Sometimes all-caps was the function, sometimes all-caps was the boolean, sometimes lowercase, whatever.

The best was clearly someone forced him to put in comments under duress.

However he ONLY commented the obvious stuff, like-

getCmdline # gets the cmdline

aurelianito 3 years ago

Extra points: leave old and outdated documentation and scripts in the repository. New documentation should go to a wiki that is not referenced in code and does not track versions. Different parts of the wiki should apply to different code versions.

epgui 3 years ago

Another really good technique: make sure your imports cause side effects! Can't believe that one wasn't mentioned.

Sirened 3 years ago

My favorite is when the codebase is so deeply buried in macros and headers that send you on a wild goose chase to find any actual code that it becomes much easier to just dump the binary in ida/binja. The source code can lie but at least the compiled binary directly does what it says

  • hinkley 3 years ago

    That feeling when you finally, finally find the bit of code you’ve been looking for… and you can no longer remember why you were looking for it, because you’ve completely purged your short term memory.

  • matheusmoreira 3 years ago

    Having to track down macros across several files really annoys me as well. When I write macros in C, I place them just above the code where they are used and undefine them immediately after.

    • cultureswitch 3 years ago

      Using #undef is a big one that wasn't mentioned but oh god it is the ideal way to hide things. If you use it sparingly but in critical places of header files, especially to undef something potentially defined in three other headers, it becomes impossible to find the real substitution without reading the cc output

semi-extrinsic 3 years ago

One of my favorite tricks is to combine functions that get called recursively (ideally four-five calls before you get back to the first one in the circle) with objects that are gradually unpacked such that their identically named member functions do subtly different things.

eyelidlessness 3 years ago

> If you call your variables a, b, c, then it will be impossible to search for instances of them using a simple text editor.

My friends, it’s time we all learn regex. You’ve heard it’s unknowable, but a simple \b on either side of your target search is your friend too! It just means “there isn’t an alphanumeric character next to me!” It wants to get to know you! If you can’t search for a variable named a, it wants to help!

  • eyelidlessness 3 years ago

    If this comment ever becomes a reference for anyone at all, I’d be remiss if I don’t add that “alphanumeric” for some odd reason includes underscores.

  • eyelidlessness 3 years ago

    I did unspeakable multiplication with regex this weekend to help a friend fix an ebook. Feel free to ask me how

gofreddygo 3 years ago

Best way I know to write unmaintainable code is to use all the best practices you can find.

bottled_poe 3 years ago

Hmm, that’s a lot of rules to adhere to. I wouldn’t want to miss one. If only there were a linter to ensure these rules were always followed..

TrackerFF 3 years ago

It's a fun read, but it is pretty much impossible unless you're running a one-man show, with zero oversight or checks at place.

Code like that should set off alarms very fast, and any code review should catch it early on.

  • fcatalan 3 years ago

    I'm that one man show, within a very dysfunctional org. I write a lot of internal tools, unprompted, just to save time for me or colleagues I like. I get bored sometimes, so deep inside some of them there's a naive Forth interpreter, and I then write some non performance critical logic in Forth. It's just a silly personal joke, at least until the proverbial bus hits me.

  • tored 3 years ago

    That is why you make sure your team mates are either in on it or too weak to protest.

justinlloyd 3 years ago

This "how to" guide describes, quite literally, a project I used to be on. I ran down the list and just went "Check. Check. Check. _pause_ Yeah, check. Check. Check."

tored 3 years ago

Inherited one project where the previous developer enjoyed writing if cases like this

    if (article > 0)
confusing early on becuase you would start thinking this is a beginning of arithmetic comparison of numbers when it actually was just a check if the article existed or not.
throwaway14356 3 years ago

you no longer have to learn all that, there are plenty of frameworks and specs to combine into much greater complexity with great P deniability. OAUTH is a good place to start, add some graphQL parsing, there is plenty of similarly legit looking nosql.

CHsurfer 3 years ago

My son is just starting to code for a class in school. If only the author was grading his assignments…

dev_tty01 3 years ago

#define else

dzhiurgis 3 years ago

Reading one of these years ago at the start of my career helped me to write at least somewhat more maintainable code

hinkley 3 years ago

> Roedy Green

< Sir Alec Guinness voice > That’s a name I’ve not heard in a long time…

Dawnyhf2 3 years ago

If you put something out for free on the Internet, don’t expect credit. Why would you?

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection