An anti-pattern I have observed and propably also been the cause of is:
Coding for Development first, Production second
The challenge with this anti-patterns is that it is pretty concealed, it is not done out of evil intentions, in fact actually the opposite, but it is an anti-pattern.
The pattern can have the following effects:
- It introduces unnecessary complexity
- It can introduce security issues
- It obscures priorities
This makes for a exceptions of course, where this anti-pattern cannot be observed since it is a part of the product design, this can be features like:
- ability to run diagnostics
- enabling of debug logs
- dry-run mode
My argument on this, is that if these are not a part of your product design, these features are actually feature creep.
We would rather have feature creep, than creepy features
Sorry, that is just a product management joke, let’s move on.
The complexity issue is quite obvious. If the code base has features implemented to support the development proces, debugging or other special traits, which are not a part of the the specified production, extending the code base, the amount of lines of code, conditionals, and logic branches. The means that the code get to hold additional code structures not necessarily part of the designated product and doing test coverage reporting, test and QA might suffer due to the fact the that the code might only be exercised based on the original production specification and special circumstances might then not be touched by these activities – the test coverage might tell us, but it then again, it might not depending on your tooling.
If done properly, this is not necessarily a bad thing and in some situations it is even acceptable, an example could be log levels.
Modern loggers can differenciate between different loglevels ranging from debug to critical diagnostic messages over informative, warning and error messages. Here it is supported as part of the logging strategy and you can decide (configure) if debug messages should only be enabled in test or development and perhaps not production. Such a logging facility would propably be an integration of an external component/framework, being testing separatly and therefor it can be asssumed that it works even for the parts not necesarily enabled for the product in, which it is integrated.
Another issue with coding for development first, is that products or parts of products can be complex and hard to test. This can lead to implementation of code circumventing protective and defensive facilities. If these circumventions are easy to enable by developers they might also be enabled by users in production, which might lead to unexpected security issues or information leaks.
There is a variation of YAGNI (“You aren’t gonna need it”), which is:
If you do not want to use it in production, do not put it there
Blindly adding features, interfaces, parameters, flags etc. to assist in development extends the attack surface of your product. If these parts are not an integral part of the regular production specification, they might slip under the radar of security audits, penetrations tests as for the normal QA and test activities.
An example could be if you do SCRUM or similar and a feature is not described as a story but is implemented and slipped into the product. It might not pass through the normal proces for a Story. There exist a possible remedy, which is peer review, but again the product might be shipped with bloated facilities, which might cause trouble down the line and people will have a hard time understanding and explaining why – since the issues are caused by unofficial parts of the code.
If you go down this path, document and if possible uniform these approaches to the extent possible, do not forget, that this is not hostile code, it is actually put there to help the developers, but it has to be put under the same scrutiny and it’s implementation should follow the same proces as other code changes and additions.
The last one – obscuring of priorities, it a bit special. Developer time is expensive time, sometimes developers come up with features just for them selves, as mentioned, they do so out of good will towards the proces they are developing under and for their teammates – but all in all, the features they impose on the product have not necessarily been a part of the production specification and since it is code, it can hold just as many bugs, security issues and other surprises as the rest of the product, but it might not have been aligned with the other stakeholders in the product development. As mentioned earlier, code might be complex – address the complexity instead of working around it, Hence this might eventually add additonal complexity.
And what might seem like a loop-hole, might end up costing a lot of man hours at some point in the product’s life.
If these features are truly necesarry for development get them out in the open. Spending time implementing these exceptions to the regular flow in order to be able to test or inspect, can cost a lot of man hours, so make sure it also brings the expected value and not just more lines of code.
All that said, implementing this anti-pattern is sometimes necessary and can help developers, with troublesome products or implementations, so sometimes it can be the solution to go anti… but be wary.