Big monolithic codebases. There’s nothing quite like it. Code from one side calls code from the other. The reverse can also be true. Boundaries are...there are no boundaries! The interfaces of the different apps are muddy at best. Often, you can just bypass them by calling database methods anyway.
I am joking. I deeply care about good understandable code. Why? Because it makes my job a whole lot more enjoyable. I love it when an application’s structure is clearly logical and intuitive and I can understand it in a reasonable amount of time. When understanding an application takes hours, there’s a design issue. It might successfully achieve its practical goals, but it is awkward and future engineers will struggle to maintain it. Growing it will definitely be a challenge. This is where attention to clear, logical and maintainable design is important. It can also be unnatural. I have no definite answers to that, but I can certainly appreciate more some paradigms I encountered in my previous work experiences. I am here thinking of microservices and clean architecture. I understand that many tend to see them as either monstrosities or panacea. They are neither. They’re only tools, or more precisely, different ways to structure your code. I have heard of people going crazy and building hundreds of microservices when a couple would have sufficed. It is always important to clearly define exactly what our requirements are so as to know what would likely constitute a microservice. In the case of a monolith, microservices are usually equivalent to the applications that are housed within the monolithic codebase and breaking the monolith down in that manner just feels natural. The interfaces will need to be clearly defined, enforcing clear boundaries. New and lazy engineers will not be able to call implementation-specific code from another service. There will be some overhead, but the system should be simpler to understand as communication will go through clearly defined interfaces. I suppose there are always loopholes to chaos, such as abusing messaging queues to send just about anything, so some goodwill from engineers and the watchful eye of more experienced devs (or ones who want good design) is still required to oversee this little world. Complexity is now also shifted to a distributed system, and tracking root issues may become very difficult. Seems like there are no ideal solutions.
All in all, we want code that is easier to understand. If a codebase is difficult to dive into, it becomes more difficult to grow it, especially when the turnover of engineers quickly transforms your whole experienced team into new engineers that are not familiar with why in the world previous engineers would do it the way they did. Enforcing clearly defined boundaries at the inter-application level and code clarity at the application level (through good architecture) is key to building a maintainable and growable system.