I think that words like "clean code" or "beautiful code" does help juniors to learn best practices of software architecture. - Junior asks to senior: what did you we use an ORM ?
- senior answers: because it's cleaner.
- junior: ???
I prefer when people are able to define a clear list of objectives: - maintenable;
- performant, scalable;
- efficient;
- resilient;
- observable;
- testable (and tested);
- secured;
- readable for new devs that come on board.
Each criteria balance the others, and the more we add criteria the more it helps to make good choice when we hesitate. It is also meaningful for people outside of the dev team, we can reach an agreement with the customer so he knows what he pays for."maintenable" can be also defined, since a project is mostly in maintenance mode during its lifetime (which means the project is successful, which is good !). The ability to incorporate new features without breaking architecture or even without breaking a single method signature is a good starting point. Being super careful with abstractions. Here someone wrote something like that: "abstraction often hides how what you want is simple". True, ORM I am looking at you. In most case data should be threaten as first class citizen, it also fosters good collaboration with the DBA. Thinking beyond "the happy path" without falling in premature optimization is also a challenge. A nice one, once again to it avoids to go head first in implementing a good idea without considering drawbacks. I also tend to imagine that the one that will work on my code had a very bad day so it must be pleasant to read what I wrote. Comments here and there, locale variable here and there even if they can be avoided, variable naming, etc... Being selective about frameworks. They are good servant but bad leaders. "Be an engineer, not a frameworker" says an article. |
When it comes to frameworks - highly opinionated tends to get corrupted into "We have this hammer and suddenly everything looks like a nail" - it doesn't always happen and it doesn't always bite you but when orthodoxies are taken from one domain and applied broadly you run the risk of some of the justifications for that orthodoxy being domain specific and being violated in the wider context.
So, when it comes to frameworks, I like modularity where I have options to plug in a different ORM or persistence integration layer - where I can swap out the router - or the validator - or any other component that proves a poor fit for our problem. It is especially valuable if there are multiple paradigms expressed in alternatives within the framework's ecosystem since you may find a pre-baked tool that mostly works where you can choose an option with shortcomings that are clear and addressable if ever the need arises.
To support maintainability it's very important to fight against NIH-ism, that is a constant danger that can soak up resources at an alarming pace - but it's also important to realize that there are some components that you will greatly benefit from tweaking or taking full ownership of with the most difficult problem being trying to figure out which is which.
I appreciate deeply that your list put maintainability first - that's my opinion as well!