When we add features to a product, we rarely think about composability. We assume that it is OK for any feature to rely on internal implementation of some other features. Let’s take a simple ToDo App (every developer created one in his lifespan).
For example, we add a Filter to a List of Tasks and we assume that it is OK when filter knows list internals. When we add Copy action to Task View, we assume that this action can know anything about View. However, this mindless implementation greatly affects system flexibility. In future you may want to add a Filter to a Board View, and it will be hard to do, since Filter is coupled with a List. And when you decide that Copy action for Project is a good addition, it will not be easy, since Copy action is coupled with Task View. What to do?
No feature in a complex system should depend on the internal details of any other feature.
We should think about every feature as a separate component (object) with internal structure and public interface.
For example, List is a complex component, but it should not include Sort, Filter, Batch Actions, Color features. All these features should be independently implemented. List should have extensions points for all these features.
In general the most complex components can be represented as a skeleton that can be filled with smaller components. It greatly improves composability and reuse, thus improving software evolution.
Board Component is a skeleton that can be enchanted with additional features. This is similar to API between software services.
Otherwise you will have hundreds of features that are tightly coupled and any change in a system will be extremely painful. You will have to navigate a dish of spaghetti to add one more requirement. At some point it will take months and software will be frozen in time.