You are always optimizing

What is an optimization?

Term "optimization" can have several different variations of meaning, but in this case "optimization" means improving process or product in some areas, and those changes affect other aspect of the same process or product.

For example if we want to make car more lightweight, we need to reduce materials or use more expensive options such as carbon fiber. And vice versa - let's say we need to make a car bulletproof, then we need to use more and heavier materials which then affect car's properties such as handling, fuel economy and so on.

Another example would be just-in-time supply chain (read more about this here): factories do not need to spend huge amounts of money on warehouses, stock processes and so on, but it comes at a cost of becoming fragile to supply chain instabilities, as we had during COVID times.

Engineering decision making

We, as engineers, make decisions every day. We decide how to approach problem at hand, which library to use, how to split bigger problem into smaller ones to make situation manageable.

During that decision making process, we are always optimizing on something (and sacrificing something as a cost of that priority), and sometimes we are not even aware about that. Here are several examples with optimizations and what we are trading off:

  • Using only familiar technology - optimizing on faster delivery, trading off technology relevance: maybe other technology would be more efficient at problem at hand
  • Using specialized (but unfamiliar) technology for solving problem - optimizing on adopting right technology, and sacrificing delivery times - team will need to learn it, and very likely you will be having difficulty hiring people if that technology is not popular on local market
  • Some frameworks optimize on developer speed (by using opinionated convention-over-configuration practices) over flexibility, while other frameworks prefer explicit code and flexibility, so development takes longer compared to previous framework

Another quite good technical example would be from PHP world: seed data libraries.

One option would be YAML based solution (example here), and another is PHP code (example here). YAML based option is better for web agencies where focus is more on how quickly developers can finish project , and second one is better for long-term projects because explicit code helps developers keep track of which property is used in seed data and which is not, I mean IDE has feature "show usage" on entity attribute (or getter setter), so if I need to remove attribute or change type, IDE will help me identifying all seeds where I need to fix code. YAML option, however, will not be supported by IDE, so seeds will be more problematic over long term.

This does not make YAML option as bad solution, neither DoctrineFixtures is "correct" way of doing data seeds; it just depends on circumstances which makes more sense to use.

And this is my main point here - optimization is good. There is no such thing as perfect solution, there will always be some tradeoffs, either technical, or economical or political. So more important is to have clear understanding what you are optimizing for and what you are willing to sacrifice, and clearly communicate this to yourself, your team, your management, your stakeholders.

The main thing I’m advocating here is about being honest and transparent with yourself: what is it really what you are optimizing for? Could you do the same thing differently? If yes, why this way not another way? Pros and cons? What are you gaining but also what you are losing?

Some people might say that Domain Driven Design is the only correct way to write code, or Functional Programming is the solution to all problems or some other umbrella statement without providing additional context when, why, what is the goal, and that is fundamentally wrong, because it tries to optimize on something without acknowledgement of tradeoffs what is being sacrificed here.

Conclusion

When making decisions, be clear what you are optimizing on, what you are willing to sacrifice and document it somewhere. There is a practice called Architecture Decision Record which helps to capture context as well - maybe deadline is very soon, maybe some technical limitations are limiting some technical choices , everything needs to be captured in that ADR which then helps re-evaluating those choices later - maybe local talent market has changed and we can hire Rust expert which would help rewriting micro-service into more efficient version?