What, Why and How
One can frequently hear "no hacks allowed" in programming discussions. This is also frequently considered a trait of a good developer that safeguards his code. However the subject is not quite this simple.What is a hack?
A hack is a part of the system that doesn't fit the overall design.For example, there are inter-class level hacks where a global variable is set because it's "too hard" to pass it around. There are architecture-level hacks where a service might call another service, tweak the output and call the same service again passing the tweaked output. Hacks can exist on any system level, from architectural down to method level hacks.
Why hack?
Hacks are bad and should be avoided at all costs but can you avoid them 100% of the time? Business is complicated. The world is complicated. Capturing all of this complexity in a system model is impossible. New requirements arise that don't fit the existing model. There are several reasons a hack might be considered.- There is a use-case that happens for tiny fraction of uses/users and re-architecting the whole system for this tiny edge case is not prudent.
- There is a use-case that, although common, cannot be modeled in a neat way along with other common use-cases.
- There is a strict deadline to meet and there is no time for proper remodeling. This reason falls outside the scope of this document and won’t be discussed further. Generally speaking, however, these should be fixed immediately after the deadline is met lest the technical debt will start accumulating.
How to hack?
If hacking is unavoidable how do you hack to minimize consequence? There are two simple rules.- Hacks must be placed in the lowest system level possible. For example, a hack in a service implementation is always better than hack in service API. A hack encapsulated in one class is always better than a hack spread out over several classes and so on.
- Hacks must be placed as close to the problem code as possible. Please see the case study for an example.
So @#$& what?
So what if you put a hack in the API instead of service implementation? So what if you put a hack in service A to compensate for service B inadequacy? It still works, right?Hacking in high system levels or in inappropriate subsystems leads to all the bad things you can imagine.
- Duplicated code - because you’ll have to work around broken model possibly in several places.
- Needlessly complicated code - because working around broken models is not straightforward.
- Ghetto, a.k.a. sarcophagus, anti-pattern where one subsystem becomes the dumping ground for all bad code - because it’s the easy thing to do since other hacks are already there.
- Potentially broken architecture - if too many architecture level hacks are added.
Case Study
Service A calls service B with an employee ID argument and gets back the person’s name. Ideally the name is in two fields - first name and last name but you get it as one concatenated field. What can you do? Your downstream data feed provides it this way. One simple solution is to tokenize the string to split it into first and last names. It is a relatively harmless hack. But where should it go?One solution is to create a new API that separates the names. It's a hack at the API level and should be avoided at all costs. What else?
Since you need first name and last name in service A you might be tempted to put the hack there because that's where you need the data. However, hacks must be placed as close to the problem code them as possible. The problem handling code in this case is service A because it’s the one that deals with bad data directly. Therefore this hack should go in service B and the service should return separated first and last names.
No comments:
Post a Comment