How to be a worse programmer
The Agile Zone is brought to you in partnership with JetBrains. Learn how Agile Boards in YouTrack are designed to help teams plan, visualize and manage their work in an efficient manner, with support for both Scrum and Kanban processes.
Lots of tips collections come up on DZone about how to become a better programmer. But no one ever told us how to become a worse one. What would make our colleagues and everyone who read our code violent? What can question their assumption and introduce defects under the hood of what they think cannot stop working?
I'm not talking about long-run quests like "read or don't read books about programming", but about practices that we apply in every day coding. You always have a choice: you can do the right thing, or becoming instantly a worse programmer by continuing doing what you know will slow down you (Uncle Bob). Here's a guide on how to pursue the latter hypothesis, hoping that it won't be followed by any of us...
The basic tips
The first round of tips is pretty simple: following this advice will result in a lower quality of your code without getting immediately noticed as a bad programmer.
- Hardcode everything from file system paths to database connection params into the code, instead of providing a configuration file.
- The maximum results with this approach are obtained with the hardcoding of magic values and their dependent values to make them untraceable: instead of writing N as the array size and N - 1 as the index of the last element, just write 10 and 9. When you change 10 to something else, fun will ensue.
- Introduce many boolean arguments, especially when there is no support for named arguments like in the majority of programming languages: processThisList(list, true, false) is a line of maximum clarity.
- Copy and paste the same code many times, and spread that logic all over ten or twenty files.
- Use lots of arguments: start with three per method and add more.
- Use the shortest variable names you can find: space shouldn't be wasted. A single letter is the better choice, with bonus points if you use i and j as global variables.
- Better than using short names is using long similar names: percentage, percent, perCent at the same time.
- Much better if the similarity is in semantic instead of form: score, points, grade, mark. All with subtle differences like data type or meanings like including a modifier (like a discount or bonus) or not. Pro tip: switch this meanings in different source files so that an Ubiquitous Language can't be extracted.
- Spelling errors like initilize() are very good because make your code seem generated by a bad MDA tool. Especially if there's an unrelated initialize() methods in the same class.
The intermediate level is composed by more dangerous practices, but that can still be workaround by other savy developers, resulting in the disruption of your efforts to make code incomprehensible.
- Stop refactoring. We are covered by tests, so we can still do it later when we have time, right?
- Start writing diagrams, then make them immediately out of sync with the code and publish them as documentation. Hope the next developer that comes across this documentation does not know your home address.
- Insert business logic in the user interface without any separation of concerns, so that to reuse any method you'll have to instantiate a widget of the user interface (Magic Pushbutton).
- Put all the methods you can think of in an interface the client code has to implement instead of using a bridge pattern. No one would even try to implement it, or will implement it with generated methods returning null.
- Introduce accessed-in-all-the-codebase context objects that make the various classes using them very boring to test. To use a context object, scatter in the client class calls like: this.getContext().getOptions().getCategoryA().getCategoryB().toString().
- Chekov's gun rule: if a gun is shown hanging on a wall in a scene, then
that gun must go off in the rest of the movie/book. So set up a Chekov's gun
in a hidden, far far away part of the execution path, and take
advantage of this effort in a totally unrelated part of the codebase to
introduce a plot twist (Action at the distance). The other developers will thank you for the emotions you gave them with your
literary worksource code.
- never delete code: probably it would be difficult to checkout a tag from the source control system. Better to comment it out, or best, leave it in a method which isn't called anywhere (and a public one, so you can't immediately delete it as unreachable code).
The big cannons
These expert tips would rotten the codebase like anything else. Make sure you won't be responsible for maintaining it anymore in the future or they may backfire.
- Stop writing tests. Jump back to cowboy coding and add features without knowing if they work, committing at random points to the repository.
- Stop running tests. Since we are smart, the changes we made cannot have broken something.
- If you still run tests, at least mix up different kind of test so that the slowest ones (acceptance/functional) take with them the fast ones (unit/integration), and the whole test suite must be executed every time you need some feedback.
- Get rid of real unit test by instantiating at least two different classes in every unit test so that when it fails you won't know where to look. The more classes you throw in, the slower and difficult to check the test will be.
- Similarly, instead of wiring up the different classes in the test so that it may be fixed in the future, you can hardcode new operators in the highest level class so that it instantiates its collaborators instead of asking for them (which would be the overhyped technique named Dependency Injection). More points if this is recursive, with these collaborators creating two database connections, opening a bunch of files and instantiating a payment gateway to pass it your mother-in-law credit card number in an assertion. So much for Command-Query separation: a new can blow up the whole world.
- Put getters and setters on anything, even on services collaborators. This actually makes you able to change these collaborators in the middle of other code that uses the service object, with funny results for the poor fellow that will call the service after the change, basing on false assumptions.
- extends is power. Everything can be subclassed to gain its functionality, by accuratingly studying the documentation and find out the class with more methods (it's a pity we usually don't have multiple inheritance.) This way, you can reach some hundred methods on your single God class, which will be the Facade of your software system.