5 ms·
Organize directories per-feature. What is a feature? Think of it as organizing by end-user value delivered. For example, "appointments/", with subdirectories "a
by astral303 11y ago
Organize directories per-feature. What is a feature? Think of it as organizing by end-user value delivered. For example, "appointments/", with subdirectories "appointments/recurring/" and "appointments/import/" for those two really complex bits.
Don't make sub-directories by kind (screens/, controllers/, directives/, views/, styles/, etc), instead encode the kind in the filename (make it a suffix).
Don't end up with a system where you end up often making sub-directories that contain only one file. That's likely an unnecessary level.
The rationale is as follows: your system will never have a fixed number of components, but it quite likely will have a fixed number of "kinds of components." So as your system grows, you will have to group files by feature to deal with complexity. When this inevitably happens, it helps not to have a per-kind directory structure to swim against.
By naming your files with name of concern as a prefix and kind as a suffix, you also get related files together by the virtue of sorting files alphabetically in the same folder (monocline grouping).
- tristanz 11y agoI don't get the benefit of this approach -- it's too subjective. Is reset-password part of auth or settings feature? What is the link between routes and features? If I'm on a page and see a bug, how do I quickly find the code behind it if it's not linked to the route hierarchy? The easiest mental model for me is to just map files/folders directly to the route hierarchy. That way you can rapidly build out the overall navigation scheme while building functionality. There are very few subjective decisions besides the route name. New developers can immediately grasp how things are organized and where things belong by interacting with the actual site. If they see a bug, or somebody suggests an improvement on a specific page, they can immediately find the code they'll need to modify. With features you have to say something like: "Find routes.js, find the route forgot-password within react-router component, see what component it references, now go to top of the file and see the location for that components import. If it's a folder with an index.js file, look in that file and see what component is actually being exported, once you find the underlying component, open that file and try to find the bug."
- nostrademons 11y agoThe reality of business is that it's subjective. That's what we're paid for - to exercise judgment, and make decisions where there isn't a clear right or wrong answer. Anything that's objective can & should be automated. (This also gives a good rule-of-thumb for when & how structure should be imposed on projects: do so when it lets you replace human work with computer work. This is the idea behind convention-over-configuration frameworks.) Anyway, the practical benefit of a feature-first hierarchy is that it makes the changes you need to add a new feature local to a single directory. This means developers don't need to constantly switch between directories in their terminals & file explorer, it lets you implement mechanisms for automated OWNERS-checking or code review, and it means that commit logs will instantly show which feature they touched just from the filenames. In practice, "feature" is defined by the org chart: it's one concrete improvement that a specific team is working on to benefit the user. If you're worried about finding the code for a feature on the screen, add a system where if you hover over any component in the UI, it pops up an overlay with a link to the source code. At a previous workplace, an engineer built such a feature in a couple days and it was an absolute lifesaver.
- astral303 11y agoYou have to make subjective decisions to structure your code anyway. So I feel that you will hit auth vs settings debate when you implement reset password anyway. For something like reset password, put it wherever your team will find it. It feels more like auth to me, but if you have most of your auth functionality already built in your settings area, it might not make sense to move it (until it gets unwieldy and "uncomfortable" to keep it there). Follow the principle of least surprise: if a fellow developer is looking for "reset password," are "settings" and "auth" the only two places where they would look? That's actually good enough. Think about all the times you really had to hunt around to find something that was placed in an unexpected, "weird" place.
- spion 11y agoThis is where you would also benefit from something like TypeScript. You could just find any use of the component and "go to definition". Or use "jump to class".
- 11y ago
- eddiegroves 11y agoI like this approach because it can be applied to any technology stack. It's also very refactor friendly. Organizing by feature gives you immediate feedback about 'what' the application does, instead of what framework it's written in. I find this structure much more useful during the application's maintenance lifetime, but it does force you to think more about naming and the division of what a 'feature' is. See also from Uncle Bob: https://blog.8thlight.com/uncle-bob/2011/09/30/Screaming-Architecture.html https://blog.8thlight.com/uncle-bob/2011/09/30/Screaming-Arc...
- braythwayt 11y agoI’ve always liked organizing Rails projects along these lines. If I have a `foobar.controller.rb` controller, a`foobar.rb` model, and a `foobar.haml` view, why are they distributed in folders by “type?” It’s so much easier to find them in a related folder by default. Mind you, that goes against the community “standard,” and we all know how that argument ends up.
- draw_down 11y agoProblem is when one component is used in two or more places. Then it goes in the dreaded "common" directory - a roach motel where files check in but never leave. Also the boundary for what a "feature" is, is likely fuzzy. I haven't seen a large project yet that successfully addresses these issues.
- astral303 11y agoRecognize it and rock it. Meaning, don't be afraid to refactor it and take advantage of it. Of course you will end up having common folders, the trick is to have more than one and at the appropriate level. Sometimes you need a common folder between a few close-but-not-same components. Sometimes you end up deciding to reuse that common folder elsewhere, so you "promote" it up a few levels. Other names such as "shared" or even "service" can be used, as long as you put big related pieces in subfolders underneath. Recognize when things get messy with common folders and refactor then. This is the "trick", so to speak. You have to recognize "our common folders are starting to become a mess" as valid technical debt, because the team will keep having a progressively harder time finding the correct code.