alecxe
alecxe

Reputation: 473873

Project organization and naming conventions

This is somewhat a follow-up to Repeating module name for each module component question.

We've decided to follow the suggested in Best Practice Recommendations for Angular App Structure blog post angular project organization and naming conventions while building a small internal application for measuring connection quality.

And this is what we've got at the moment:

$ tree -L 1
.
├── app-config-service.js
├── app-config-service_test.js
├── app-connection-service.js
├── app-connection-service_test.js
├── app-controller.js
├── app-controller_test.js
├── app-countdown-directive.js
├── app-countdown-directive_test.js
├── app-footer-directive.js
├── app-footer-directive_test.js
├── app-footer-service.js
├── app-footer-service_test.js
├── app-math-service.js
├── app-math-service_test.js
├── app-stats-directive.js
├── app-stats-directive_test.js
├── app-status-directive.js
├── app-status-directive_test.js
├── app-status-service.js
├── app-status-service_test.js
├── app-time-directive.js
├── app-time-directive_test.js
├── app.css
├── app.js
├── bower_components
├── config.json
├── countdown.html
├── footer.html
├── img
├── index.html
├── ping
├── stats.html
└── status.html

As you can see, there are several directives, services, partials, single controller, module declaration file and couple config and app-specific unrelated to the topic files. This really becomes a mess of files and is not quite readable and easy to work with.

This is probably because we have only one single module and keep everything inside it.

Is it okay to use the good old component-oriented approach and have special directories for services, controllers, directives and partials for such a simple app? Does this mean that the new "Organized by feature" approach work only for non-trivial huge applications?

Upvotes: 3

Views: 4871

Answers (6)

R. Gulbrandsen
R. Gulbrandsen

Reputation: 3778

When you start a project, there is not only the file structure to have in mind. I would recommend you to think about how to create your modules and how you want to inject the dependancies, and ofcourse how you want to minify your application.

Angular boilerplate at github.com is a boilerplate project which let you build the application with grunt, use bower for depandancies, live reload your browser and lets you use LESS instead of CSS.

It contains a starting structucre like this:

ng-boilerplate/
|- grunt-tasks/
|- karma/
|- src/
|  |- app/
|  |  |- <app logic>
|  |- assets/
|  |  |- <static files>
|  |- common/
|  |  |- <reusable code>
|  |- less/
|  |  |- main.less
|- vendor/
|  |- angular-bootstrap/
|  |- bootstrap/
|  |- placeholders/
|- .bowerrc
|- bower.json
|- build.config.js
|- Gruntfile.js
|- module.prefix
|- module.suffix
|- package.json

It also contains guide on how to set it all up. Happy hacking!

https://github.com/ngbp/ngbp

Upvotes: 0

Marian Ban
Marian Ban

Reputation: 8168

I prefer organize my project in feature(module) based approach on top level and type based (directives, controllers) on lower levels:

enter image description here

in this example i have 3 separated (root) modules home, search and shared. These modules are root parts of my application. Each module may contain directives, services, views, less files, etc. In general I prefer to keep related parts of my application as close as i can. That is way i grouped each parts of the news directive in the news folder. But keep in mind that this news directive is used only in my home module. If it would be used in multiple modules (home and search) then i will move the news folder into the shared folder.

This is similar approach to prefix based approach from this question (Repeating module name for each module component) but I use folders instead of prefixes.

Upvotes: 1

V31
V31

Reputation: 7666

As ExpertSystem stated, your current directory structure is not in relation to the blog Best Practice Recommendations for Angular App Structure.

I am in conjunction with ExpertSystems as well as Gil Birman, that the approach in order to design the app structure should be modular. As you know that Angular itself follows a modular structure so whether you have multiple modules or a single Angular module you need to think according to the functionality you catering to. For instance if you have a 'CountDown' functionality it should have its own structure.

Why this is important?

1. Code Maintenance: As your code will grow your maintenance costs grows. If for instance in the production environment you get an error in your angular code and want to rectify with a KRA of 1 hour, you would first need to replicate the scenario locally and then traverse to that particular file. If it had been module you would know which folder to target and boom you got the solution fast.

2. Development Ease: You can split multiple functionalities between multiple developers and they can target different functional folders so their wont be touching the same files. Merging conflicts can be reduced.

3. Faster Reviews: Since the app is broken down into functionality, reviews can be done faster and with ease knowing that the code for that folder is for that particular functionality.

4. TDD Implementation: The structure can be used to kick start Test Driven Development (TDD). Benefits of TDD are mentioned over here in this article

Difference between Development and Production Code/Structure

In Development you can have the structure according to the functionality. However in order to improve on the performance of your web application (or a hybrid mobile app), the best way to go about that is to concatenate all the files, minify it and obfuscate it using GRUNT. Will be giving a sample of the GRUNT file for the same. You can run the script every time during deployment using any continuous integration tool such as Jenkins for example.

Upvotes: 1

Marcin Wosinek
Marcin Wosinek

Reputation: 1009

For the beginning I recommend sticking with project organization offered by yeoman generators: http://yeoman.io/

It uses component-oriented approach; and offers multiple generators that will put code in expected location, generate unit tests for them, keep file-names patter, set up the grunt build description etc.

The example project structure looks like this:

enter image description here

Definitely it's worth to use a structure approach to even simple application. The will be plenty of possibilities to create a mess in the code base, so better start neatly:) The problem can arrive on the other end of the scale - at same point you may need more then just one module, and standard yeoman generator doesn't support it well.

Upvotes: 1

Gil Birman
Gil Birman

Reputation: 35900

Modular architecture mimics how our brain works

Even for a small project, I would still separate the project into module folders for the simple reason that it makes it easier to find the code you need to work on. That's because us programmers generally work on a per-module basis.

For example, for an hour we will work on the footer module which includes both directives and services which will reside in the footer dir. In contrast, it's much less likely that we will decide that for an hour we have to work on various directives in the directives folder and never touch any service.

Modular architecture makes it easier to rip code across projects

When I start a new project, regardless of the size of that project I usually start by ripping modules out of existing projects. With modular architecture this is extremely easy and intuitive.

Of course, if a module is highly reusable you should package it as a bower module instead, but most small modules will end up being customized on a per-project basis.

Upvotes: 2

gkalpak
gkalpak

Reputation: 48211

You say that you decided to "follow the suggested in Best Practice Recommendations for Angular App Structure blog post", but you don't seem to have followed it...


According to the recommended approach, each component/feature should be in its own directory (under a components directory).

For the reasons pointed out by Gil Birman and also detailed in the aforementioned blog post as well as in Repeating module name for each module component, it makes more sense to organize the directories by feature (e.g. the foo-feature directory contains all directives, services, controllers, partials etc related to that feature) than organizing by type (e.g. all controllers in one directory, all services in another) etc.


In any case, all the above are guidelines (more a way of thinking) and not a precise recipe or a deterministic algorithm that can decide for you where to place each file (e.g. is there going to be a components/lib/ directory, will a service go inside a feature's directory or under a components/common/ directory etc).
You need to understand the guidelines (and what purpose/need the are trying to fulfil) and develop a convention that suits your team's style.

There are times when you won't be sure where to place a file. You can have a debate with the team, make a decision and go with that. This is totally normal (especially at first), but you'll find out that as time goes by, such cases will arise more and more rarely.


That said, I would expect your directory and file structure to be more like that (making some assumptions about which services might be more generic/utility-like):

app/
|___ app.css
|___ app.js
|___ app-controller.js
|___ app-controller_test.js
|___ bower_components
|___ config.json
|___ index.html
|
|___ components/
|    |___ common/ or util/
|    |    |___ config-service.js
|    |    |___ config-service_test.js
|    |    |___ connection-service.js
|    |    |___ connection-service_test.js
|    |    |___ math-service.js
|    |    |___ math-service_test.js
|    |
|    |___ countdown/
|    |    |___ countdown.html
|    |    |___ countdown-directive.js
|    |    |___ countdown-directive_test.js
|    | 
|    |___ footer/
|    |    |___ footer.html
|    |    |___ footer-directive.js
|    |    |___ footer-directive_test.js
|    |    |___ footer-service.js
|    |    |___ footer-service_test.js
|    |
|    |___ img/
|    |    |___ ...
|    |
|    |___ stats/
|    |    |___ stats.html
|    |    |___ stats-directive.js
|    |    |___ stats-directive_test.js
|    | 
|    |___ status/
|    |    |___ status.html
|    |    |___ status-directive.js
|    |    |___ status-directive_test.js
|    |    |___ status-service.js
|    |    |___ status-service_test.js
|    |
|    |___ time/
|         |___ time-directive.js
|         |___ time-directive_test.js
|
|___ misc/
     |___ ping

Upvotes: 8

Related Questions