Convention: File structure
The most important convention in dogstack
is how we structure our projects into files across directories.
We want to provide the hinges for developers to lay their medium-density fibreboard (MDF).
In contrast to frameworks like Rails which split our project into directories for each type of file (models, views, controllers), our project is split into directories for each conceptual topic, where each topic contains the various types of files within that topic.
This leads to a directory structure of ${topic}/${type}/${name}
.
What is a topic?
What the module does
A topic is a grouping of modules that are related by concept.
Some examples of topics:
- accounts
- profiles
- navigation
- notifications
- payments
- database
Topics are sentimental and subjective, dependent mostly on the common vocabulary used across the team when communicating about the project.
The reasons for co-locating modules into topics:
- Keeps the project grounded in shared vocabulary and business logic
- Concepts are each cohesive inside and decoupled outside
- Architecture of your files matches the architecture of your app.
Known topics that are exceptional:
- app: a catch-all topic for your home page, layout, etc
- lib: what isn't part of any topic and should really be published as a reusable module, but too lazy
What is a type?
What a module is made of
A type is a grouping of modules that are related by the shape of export, as in how these modules interface with other modules.
Contrary to topics, types are more or less objective and predetermined by dogstack
.
- sync (helper function that returns value or throws error)
- async (helper function that returns promise)
- type (
tcomb
type) - style (
fela
rule) - action (
redux
action creator) - reducer (
redux
reducer) - getter (
reselect
selector) - component (presentational)
- container (data)
- hoc (higher-order components)
- route (
react-router
<Route />
) - service (
feathers
service) - migration (
knex
migration) - seed (
knex
seed)
What is a name?
The name of your export should be exactly the name of your default export.
Common smells
- When a module feels out of place, they probably need a better place.
- When your name contains the topic or type in it, you can leave out the topic or type from the name.
- When you feel the need to make a sub-directory anywhere, you probably need a new topic.
- When you keep using the same word to disambiguate files from those of the same type, it's probably a topic.
- When you talk to other developers on your project using different words than your topics and names, you need better topics and names.
- When you have a "core" topic, or something equally vague, it's probably multiple topics.
- When you have many topics each with a single file in them, you might be seperating too much.
- Categories should tell us something about what they separate, so if they separate out only one thing it doesn't tell us much..