From a recent code-base, here is a list of ways to make a project harder to work with. If you want to slow down your enemies, annoy your friends, and make drawing your paycheck for software engineering just that bit more embarrassing, then please ensure you do the following.
- Only write automated unit tests afterwards – this guarantees you’ll spend as little time as possible on them and not need to worry about whether they actually prove anything as you already know the code works
- Ensure your unit tests depend on the entire ecosystem of the project, including databases and files – this guarantees that they’ll stop working sometime soon, and may not even work on someone else’s machine
- Never fix a broken unit test – this will make it hard for someone else to know whether they’ve just broken something
- Do not comment anything – sure we think code should be self-documenting, so shouldn’t need comments in line, but let’s go further and just have huge monoliths of custom names with no Javadoc or explanation of context
- Use cryptic names – this goes well with not commenting things; it especially makes things harder if the names nearly mean something
- Ensure some methods are ridiculously long and do several things – this can actively prevent code reuse without a huge amount of learning to see where the boundaries are
- Use random assortments of helper classes – distribute the functionality around on almost arbitrary lines, sometimes to make unit testing easier, sometimes to get the IoC container to inject something trivial for you, and sometimes just to give your code a change of scene.
- Use the largest number of DTOs/Value object types as you can. The more the merrier – it means you can litter your code with conversions between objects of these pretty much identical types. Ideally, there should be:
- A value type mapping to the database
- A different value type for when the DAO layer returns that data to the service layer
- A different value type for when the controller layer returns that data to the view layer
- Checked exceptions should be cascaded everywhere rather than caught and wrapped – use the IDE to just add any exception you like to the throws syntax as it saves you having to think about exception strategies and gives your calling code more to worry about, thus slowing everything down more
- Use named queries for everything, rather than a search abstraction – this can allow you to ignore you’re using an ORM layer
- Map your database to your code via ORM in a convoluted manner, creating arbitrary aggregations of data, or parent child relationships that neither exist in the problem domain nor the database
- Ensure the build process is complex and error prone
- Use the application server to do things that it can do, but which would be better done by the reverse proxy/load balancer. Things you could annex into the app server might include:
- HTTPs handling
- Page compression
- Static content serving
- Leave detritus in your configuration files – things that will upset your IDE as it attempts to work with them
- Have a great big file full of strings, unifying constants of any type from anywhere, then duplicate some of those strings inline when you feel like it
- Don’t use any of the automatic mechanisms for dependency injection provided by your framework, use instead, a method which requires providing resource names that you have to inject yourself everywhere; ideally use this in a situation where it’s not helping resolve any conflicts because there are none
- Build your generic code as though it can only do one specific thing, though it advertises itself as generic
If you can do all of these things in one simple codebase, then nobody will be able to follow in your footsteps and you’ll be a success at slowing everyone else down.
Or you could just do the exact opposite of the above and people might like you.