Code modularity is replaceability
For those using a RSS reader, subscribe here: rss.xml
What is the benefit of putting code into multiple files? What is the benefit to the reader of the code? What does it constrain your design on?
When you have a module in your code, you could export everything and import everything where you use it. You can have a rough equivalent #include’s, and end up with a source file that is just split up over multiple files. That is, if you import by following a collapsible structure, a DAG to be specific, without tangling it into cycles.
Although this is useful, it is a small benefit compared to code with sectioning if you do not hide implementation details. Modules that reach outwards to grab stuff are not necessarily a threat to replaceability. They can be part of code up in a hierarchy, and here is the key; that can only give it’s benefit if you mostly abide by it. The further you stray from it, less of its properties are true.
Concrete example: a hierarchy for a single page application. In this example your application has pages, pages have components, components use data and utilities to act on it. A page describes what is shown, and picks the parts to compose it.
This hierarchy has the property that allows re-use the more you use it. But beware, this is a fine balance between verbosity and re-usability. The intuition that is worth having here is that code has a good-enough placement in the program at any given point. As discussed in the post about duplication, duplication and abstraction go hand in hand; you can move between the two if you follow a design.
You do not know what is best for the system in advance, as you don’t know the requirements that come it. But you can design it as such that changing the system allows you to still reason with it, and not relearn it like it is a completely new system. Code modularity is both about saving you as a developer effort, and saving your teammates the effort to relearn specifics. If you design your code with library design in mind, you are already taking modularity into account.
And if you write code that the linter complains about, take it as a hint to also consider your overall design. And if you write code that you name very similar across modules, unroll the imports manually and see what your code ends up being. Put your existing code together experimentally, if you try to figure out the fault of the design. Make it painfully obvious when the same concepts have separately evolved implementations. It is inevitable that you write this kind of code, you are human afterall, right?