Imagine looking at an overview of an apartment building, while trying to get some sense of how the individual apartments are structured:
Does this look familiar? No? What about this:
The common theme here being project folders defined by the type of the content. It’s difficult to see what the software actually does. That requires an intimate knowledge of a large part of the source code files. Grouping by type quickly gets out of hand as the project grows. Imagine having fifteen or twenty controller classes that is somehow related to a dozen or so views and viewmodels. Sadly some frameworks that operate by convention over configuration forces you into grouping by type, so that the framework is able to instantiate an appropriate controller etc. If you are not using such a framework you really have no excuse for using this kind of project structure.
An alternative to grouping by type is grouping by software feature. Of course the two can be mixed. Grouping by what the software actually does enables a developer to much quicker gain an understanding of the codebase. Examples of features might be ‘Add item to shopping cart’ or ‘Send mail to customer support’.
Grouping by feature requires constant work as features evolve and overlap. The issue of grouping is not solved a priori as in the case of grouping by type. Furthermore, renaming and moving files and folders is something that is handled poorly by several version control systems. Nevertheless doing these types of refactorings is something that belongs in the skillset of an software engineer.