Apropos nothing, but I giggled at a screen cap of hitchikers guide labeled “courtesy Pinterest”. Seems unlikely that Pinterest was actually in a position to grant that “courtesy”.
Though speaking of over engineering, labeling images you make yourself “no attribution required” would also count.
I agree with the principle but some parts of the article smacked of fundamental misunderstandings.
specifics would be nice
Really liked this point in the article:
I have never seen a single business “converge” on requirements. They only diverge. Its simply the nature of business and its not the business people’s fault.
To deal with this, I do a few things (which are closely aligned with the suggestions in the article).
I usually tolerate a degree of duplication until it’s clear that there is a sufficiently stable piece of shared functionality that can be extracted into a function/component/library.
I push out functionality into config (e.g. extra attributes for things in the DB), templates and the like. E.g. in one of my projects it was very useful to implement report templates with conditional logic and arithmetic expression support, so I could deal with ever more complex requirements from one customer outside of the code. And when I had to extend the template parser to deal with some crazy new twist, at least it was improving the capability for all reports now and in the future, not just the report for one customer.
At the same time, I avoid exposing this sort of config via UI (e.g. form or report builders). It’s tempting, but I feel that the effort to build the UI is likely to be undermined by the changing requirements, just like everything else. In the end, the UI will get really complicated for end users anyway, so best not to invest in building it.
Even so, “business logic” can be rather dispiriting - whatever nice abstraction you build, it ends up being mutilated by special cases sooner or later.
Honestly that sounds like a common overengineering pattern I’ve seen. I’d be more likely to write a class for that customer’s report (I already have a great language with conditional logic and arithmetic expression support, it’s called my actual programming language). I think people have this unreasonable aversion to putting things that seem like “config” in code - if it’s maintained by programmers code is the best place for it.
For myself, it depends on exactly what you have in mind when you say this. I have generally put a lot of stuff into configs for integration tests. Things that go outside the program are config options in some way. Generally what this looks like is some kind of factory (for me, just a map of string -> constructor function) and the config file entry becomes the string.
string -> constructor function
But I definitely agree, config files that are basically their own little programming language tends to go poorly. I like you configs to be little more than key-value pairs and I can use whatever config management tooling to generate it. I do like this separation though between the code that generates a config, a config, and the program that consumes it. I’ve had many clever config languages where it was very hard to understand what the actual config was once the program interpreted it.
It is if you disregard all sorts of considerations: difficulties of versioning and deploying to the customer (in this case, it wasn’t a web app), time taken to rebuild and test such changes, whether I could delegate “config” changes to a junior developer or a support person to save my time etc.
Config over code is an extremely useful pattern in practice. Like all of these things, it’s not black and white and can be used unnecessarily.
This is the only thinkpiece on engineering errors in general, and over-engineering in particular, that I’ve agreed with from tip to tail. Extraordinary advice, delivered succinctly and actionably. Absolutely required reading.