4 ms·
In the real world, code is read often and for many reasons. The main ones I can think of are: 1) To understand the system without necessarily wanting to ch
by strnisa 2y ago
In the real world, code is read often and for many reasons. The main ones I can think of are:
1) To understand the system without necessarily wanting to change anything. This is common with new employees or anyone wanting to learn more.
2) The system often needs tweaks, bug fixes or new features. Each of these normally requires that the code in question is read by several people several times.
3) The architecture is normally not perfectly modular, so changing one part often requires one to understand and tweak the neighbouring parts of the system, too.
- jongjong 2y agoI agree with the first one but the other 2 are basically what the author is speaking out against. Some change/rework is unavoidable, but if code is good, then it should be relatively rare. Modularity isn't sufficient for code to be good. It's difficult to have truly 'loose coupling' without 'high cohesion'; each module should have distinct and well-defined responsibilities. My test for high cohesion is the question: "Is this module easy to describe to a user with limited technical abilities?" If modules are both loosely coupled and high cohesion, you'll find that you rarely need to change the code, or won't need to change it much, even after substantial refactorings. This is because such modules provide a near-optimal level of abstraction. Interfaces of such modules tend to be simple (a relatively small number of simple parameters, e.g. primitive types); this is what makes the modules easy to substitute. For example, consider a database client library, the most powerful method is for running queries against the database; this method typically requires only a single argument as a query; a string, though it will also typically support an object/map as second argument to substitute values into the query. How often do you need to change the database client library because of a refactoring? You could literally pivot your entire business model from a social media app to an enterprise CRM and you wouldn't have to change a single line of code in your database client. You might change how you use your database client within your back end logic, but you won't have to change the implementation of the client itself. There are many less extreme examples though where a module can handle very significant changes to your business without having to be modified at all. Maybe your business pivoted from being a professional/business social media app to being focused on friends and family; it might change some aspects like friend discovery, algorithm recommendations, banning, etc... But you should be able to keep most of your existing code if your code is good quality. My definition of good code is "Code that is resistant to change when faced with requirement changes." Though there is a lot of overlap with "Code that is rarely read."
- nsinreal 2y agoThat's kinda unrealistic. It's okay to expect that if you change the requirements for A, there should be no changes in the code of B. It's not okay to expect that if you change the requirements for B, then there should be no changes in the code of B.
- jongjong 2y agoFor essentially all my projects, I end up having most of my business logic at the trunk of the project source. The leaf nodes are the most general purpose modules (e.g. database clients, utility functions), the branches are still relatively generic but closer to the business domain. The trunk (e.g. entry point of my program) changes very frequently and is directly related to the business domain. The branches change rarely and the leaves almost never change. The leaves are usually third-party modules. For the leaves, I will typically swap them out if they cease to meet my requirements. I almost never refactor those. For the branches, I sometimes have to refactor 1 or 2 of them at most. I can't recall ever doing a refactoring which touched on many branches at the same time. Most of my refactoring only affect the trunk of the code. I try to have all the business logic for a program or service represented in a single file. If the file gets too big, I create new modules 'branches' and move the most generic logic to those branches. My top level file tells the full story of the program/service. Anyone can open that file and, based on the module names and method names that are being called, they can figure out what happens and when. All the events, endpoints, logging, access control and other externally observable behavior is wired together in that file. If the file has been abstracted to the maximum amount possible (with all generic functionality moved to branch modules) and it's still too big, it may be time to switch to a micro-service architecture. Break up the trunk into 2 parts and we basically end up with 2 apps/services. This rarely happens though. With the right level of abstraction, you can fit a massive amount of user functionality in a single main file. By the time the main file's code becomes overwhelming, the application's UX becomes overwhelming for the end user too... Time to split up into multiple apps. Think of how complicated UX would be if a video-editing software tried to support image editing as well (e.g. to make fancy title screens or UI overlays). It would become too much for the user. Just make two different applications; one for video editing, one of the image editing. You can integrate them in a seamless way, but they should be different apps.