Organization and Naming Standards for Projects

After exploring the Repeating module name for each module component issue, we have decided to adopt the organizational recommendations outlined in the Best Practice Recommendations for Angular App Structure blog post. This approach has been implemented in a small internal application used for measuring connection quality.

The current structure of the project includes:

$ 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

This setup, with a mix of directives, services, partials, controller, and other files all grouped under a single module, is becoming difficult to manage and work with due to the high number of files involved.

Considering that everything is contained within a single module, would it be beneficial to transition to a component-oriented approach? Should we introduce separate directories for services, controllers, directives, and partials in this simple application? Or does the "Organized by feature" method only prove effective for large-scale applications?

Answer №1

You mentioned that you planned to "adhere to the suggestions outlined in a blog post about Best Practices for Structuring Angular Apps", however, it appears that your implementation deviates from those guidelines...


As per the recommended methodology, each component or feature should reside within its own directory (nested under a main directory like components).

Advocated by Gil Birman and discussed in both the aforementioned blog post and on Repeating module name for each module component, organizing directories based on features (e.g., having a directory like foo-feature for related directives, services, controllers, partials, etc.) is deemed more sensible than grouping them based on type.


It's crucial to note that these are mere guidelines (rather than strict rules) and serve as a guiding principle rather than an exact formula to dictate where each file should be located (e.g., considering a directory like components/lib/, deciding whether a service belongs in a feature's directory or a generic components/common/ directory, etc). You must grasp the essence of these guidelines and tailor them to suit your team's preferences.

Situations may arise where there is uncertainty regarding the placement of a file. In such cases, engaging in discussions with the team, making a collective decision, and proceeding accordingly is common practice. While this might occur frequently initially, over time, such instances will diminish.


With that in mind, it would be expected that your directory and file structure closely resembles the following (keeping in mind potential scenarios where certain services could be more universal/utility-oriented):

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

Answer №2

How Modular Design Reflects the Functions of Our Brain

Even with a small project, I find it beneficial to organize the code into separate modular folders. This approach simplifies the process of locating and working on specific code segments, as programmers typically focus on one module at a time.

For instance, I may spend an hour concentrating on the footer module, which encompasses both directives and services housed in the footer directory. Conversely, it's unlikely that I would dedicate an hour solely to working on various directives in their respective folder without addressing any services.

The Convenience of Transferring Code Across Projects via Modular Design

When commencing a new project, regardless of its scale, my initial step usually involves extracting modules from previous projects. The use of modular architecture streamlines this process, making it straightforward and instinctive.

Naturally, if a module holds significant reusability value, it is advisable to package it as a bower module. However, most small modules are likely to undergo customization tailored to each individual project.

Answer №3

If you're just starting out, I suggest utilizing the project organization framework provided by yeoman generators:

This method follows a component-oriented approach and comes with various generators that help organize code in its proper place, create unit tests, maintain consistent file naming conventions, configure grunt build processes, and more.

The typical project structure using this approach would resemble the following:

Adopting a structured approach is beneficial even for simpler applications to avoid code chaos. While it's easy to get lost in tangled code, starting off organized is key. However, as your project grows, you may encounter limitations with handling multiple modules efficiently with standard yeoman generators.

Answer №4

It has been pointed out by ExpertSystem that your current directory structure does not align with the best practices outlined in this blog: Best Practice Recommendations for Angular App Structure.

I agree with ExpertSystems and Gil Birman on the importance of a modular approach to designing the app structure. Angular itself follows a modular structure, so whether you have multiple modules or a single Angular module, it is essential to consider the functionality you are catering to. For example, if you have a 'CountDown' functionality, it should have its own dedicated structure.

Significance of Modular Structure:

1. Code Maintenance: As your code grows, so do your maintenance costs. Having a modular structure allows for easier identification and debugging of errors, leading to faster solutions.

2. Development Ease: By splitting functionalities between developers and assigning them to specific folders, conflicts can be minimized and development streamlined.

3. Faster Reviews: Breaking down the app into functional components enables quicker and more efficient code reviews.

4. TDD Implementation: A structured approach supports Test Driven Development (TDD), enhancing code quality and maintainability.

Distinguishing Development and Production Structures:

During development, organize the structure based on functionality. To optimize performance in production, consider concatenating, minifying, and obfuscating files using tools like GRUNT. I will provide an example GRUNT file for reference, which can be automated during deployment through continuous integration tools like Jenkins.

Answer №5

When structuring my projects, I like to organize them using a feature (module) based approach at the top level and a type-based approach (directives, controllers) at lower levels:

For example, in one project I have three separate root modules: home, search, and shared. These modules serve as the foundation of my application, each containing directives, services, views, less files, and more. I find it beneficial to keep related components of my application close together, which is why I group all parts of the news directive in a news folder specific to the home module. However, if the news directive were to be utilized in multiple modules (such as home and search), I would relocate the news folder to the shared directory.

This strategy aligns with the prefix-based approach discussed in this question (Repeating module name for each module component), albeit with the use of folders instead of prefixes.

Answer №6

When embarking on a new project, it's important to consider more than just the file structure. I suggest thinking about module creation, dependency injection, and how you plan to minify your application.

An excellent resource for this is Angular boilerplate found at github.com. This boilerplate project allows you to build applications with grunt, utilize bower for dependencies, live reload your browser, and use LESS instead of CSS.

The initial structure includes:

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

Additionally, there is a helpful guide included to assist in setting everything up. Happy coding!

https://github.com/ngbp/ngbp

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Trouble selecting options in hierarchical data

I've been attempting to run this sample code for selecting an option from a select element with hierarchical data, but it seems to be having some issues. $scope.options = [ { id: 1, info: { label: "Item 1" } }, { id: 2, info: { label: ...

How can you utilize the Array submission syntax within HTML coding?

I currently have numerous input fields within a form, and some of them are structured like this: <input name="agents[]" type="file" /> Additionally, imagine there is a plus button next to this field as shown below: <img src="plus.jpg" id="some_ ...

Organizing dates with Javascript

Is there a way to convert a string from this format : 2014-06-12T23:00:00 To another format using JavaScript, like so : 12/06/2014 23:00 ...

I am interested in retrieving an array

Here is the array I am working with { Colors: 'Blues', Department: 'Clearance', Size: [ 'Runners', 'Custom Sizes' ], Shape: 'Round', Designer: 'B. Smit', } The desired output should be ...

Using Angular-Resource instances throughout the entire application

Within my code, I have set up a straightforward resource of categories that utilizes a cached query action: app.factory 'Category', ($resource) -> $resource "/categories/:id", {id: '@id'}, { query: { cache: true, isArray: true, ...

The style of the button label does not persist when onChange occurs

Encountered an interesting issue here. There is a button designed for selection purposes, similar to a select item. Here's the code snippet: <button class="btn btn-primary dropdown-toggle" style="width: 166%;" type="button" id="dropdownMe ...

Error: protractor encountered an unexpected issue

Currently, I am following this tutorial I went through all the steps mentioned in the tutorial except for what was suggested in this post instead of npm install -g protractor I opted for npm install -g protractor --no-optional So far, I have succe ...

The "tsc" command in Typescript seems to be acting up. I've exhausted all possible solutions but

Hello there, I find myself struggling to run Typescript throughout the day while utilizing Visual Studio Code. My usual method involves installing TS globally: $ npm install -g typescript But every time I try to use it, I encounter the same error: bas ...

Using AJAX to dynamically load Javascript

I came across this interesting code snippet: <script type="text/javascript" language="javascript"> $(function(){ $(window).hashchange( function(){ window.scrollTo(0,0); var hash = location.hash; if (hash == "") { hash="#main"; } ...

Incorporate a fresh attribute to the JSON data in an Angular API response

I'm currently working on updating my JSON response by adding a new object property. Below is an example of my initial JSON response: { "products": [{ "id": 1, "name": "xyz" }] } My goal is to include a new object property ca ...

Is it possible to assign a class to the initial word within a designated class?

How can I customize the first and second word of a specific class in my code? This is an example of my current code: <h2 class="content-heading">Latest News</h2> I would like to achieve something similar to this: <h2 class="content-headi ...

Arranging Angular Array-like Objects

I am in possession of an item: { "200737212": { "style": { "make": { "id": 200001510, "name": "Jeep", "niceName": "jeep" }, "model": { "id": "Jeep_Cherokee", "name": "Cherokee", "nice ...

Assist with JavaScript Programming

Can someone assist me in creating functionality for the "Show Picture" button to toggle the visibility of the picture when clicked? I've been trying to achieve this using an If/Else statement for a school project but have been struggling with it. Any ...

Leveraging $scope variables to dynamically generate new scope values within an Angular controller

I am currently faced with the challenge of using latitude and longitude data provided by the server, which is stored in $scope.Address. I am attempting to create a map object with these values as shown below. However, my current implementation is not fun ...

An uncaught runtime error has occurred: TypeError - subSector.map is not a valid function

I'm encountering a challenge when attempting to map through JSON data retrieved from a fictitious API. The process works smoothly when there is more than one data item, but I encounter an error when there is only a single object. Below is the code sn ...

Detecting the failure of chrome.extension.sendRequest

Greetings Chrome Developers! I am wondering how one can determine when a chrome.extension.sendRequest call has not been successful. I attempted the following approach with no luck: chrome.extension.sendRequest({ /* message stuff here */ }, function(req){ ...

What are the reasons behind Jquery's decreased speed performance in Internet Explorer?

My ASP.NET page is quite intricate and heavily depends on jQuery for manipulating the DOM without using AJAX. Interestingly, I've observed that the page performs better in Mozilla browsers like Firefox compared to Internet Explorer 7 or 8. Could it b ...

JavaScript: Obtaining the month based on the week number and year

Can someone assist me in determining the month based on a given week number and year? For example: Week - 48 Year - 2023 Desired Output - 11 ...

Trouble arises with MySQL query in PHP/jQuery setup

I am currently in the process of developing a user panel where users can change their first and last names. Everything seems to be working fine with the $ajax form handling, as I can use console.log(data) and see {fname: "Damian", lname: "Doman", id: "20" ...

Is my Discord.js bot malfunctioning due to incorrect indentation, despite the absence of errors?

After spending a considerable amount of time developing this bot, I encountered an issue following an update that introduced 'limitedquests'. Previously, the bot worked flawlessly but now, certain functions are not functioning as intended without ...