{"action":"created","issue":{"url":"https://api.github.com/repos/yeoman/generator-angular/issues/109","repository_url":"https://api.github.com/repos/yeoman/generator-angular","labels_url":"https://api.github.com/repos/yeoman/generator-angular/issues/109/labels{/name}","comments_url":"https://api.github.com/repos/yeoman/generator-angular/issues/109/comments","events_url":"https://api.github.com/repos/yeoman/generator-angular/issues/109/events","html_url":"https://github.com/yeoman/generator-angular/issues/109","id":11741035,"number":109,"title":"Proposals to Make Components More Reusable","user":{"login":"joshdmiller","id":101793,"avatar_url":"https://avatars.githubusercontent.com/u/101793?v=3","gravatar_id":"","url":"https://api.github.com/users/joshdmiller","html_url":"https://github.com/joshdmiller","followers_url":"https://api.github.com/users/joshdmiller/followers","following_url":"https://api.github.com/users/joshdmiller/following{/other_user}","gists_url":"https://api.github.com/users/joshdmiller/gists{/gist_id}","starred_url":"https://api.github.com/users/joshdmiller/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joshdmiller/subscriptions","organizations_url":"https://api.github.com/users/joshdmiller/orgs","repos_url":"https://api.github.com/users/joshdmiller/repos","events_url":"https://api.github.com/users/joshdmiller/events{/privacy}","received_events_url":"https://api.github.com/users/joshdmiller/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/yeoman/generator-angular/labels/enhancement","name":"enhancement","color":"84b6eb"},{"url":"https://api.github.com/repos/yeoman/generator-angular/labels/question","name":"question","color":"cc317c"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":208,"created_at":"2013-03-07T00:49:21Z","updated_at":"2016-09-01T23:14:38Z","closed_at":null,"body":"I apologize in advance for this issue's massive length.\r\n\r\nI would like to start a discussion on some ways I think the generators could be changed to make the resulting components more easily reusable. I think when developing, we should have the potential for as much of our code as possible to be \"drag and drop reusable\". AngularJS already sets us well on our way by promoting separation of concerns in its internal architecture, so why shouldn't our development tools do the same?\r\n\r\nThe reference structure I am using is my own [ngBoilerplate](http://github.com/joshdmiller/ng-boilerplate).\r\n\r\nEach section builds on the previous.\r\n\r\n**Update [07 Mar, 0840 PST]:** I use the term \"component\" here a little more loosely than Bower. I just mean it to refer to functionality that is somewhat self-contained. Unless otherwise noted, it refers to both bundled code and internal app features.\r\n\r\n### Organize by Feature\r\n\r\nInstead of bundling code by the layer to which it belongs (controllers, services, filters, directives, etc.), I would like to see code bundled by the feature to which it belongs. There can be many manifestations of this, but here are two examples:\r\n\r\n**(a) Routes** \r\n\r\nInstead of something like this for a `/home` route:\r\n\r\n```\r\n|-- src/\r\n|   |-- scripts/\r\n|   |   |-- controllers/\r\n|   |   |   |-- home.js\r\n|   |-- test/\r\n|   |   |-- spec/\r\n|   |   |   |-- controllers/\r\n|   |   |   |   |-- home.js\r\n|   |-- views/\r\n|   |   |-- home.html\r\n```\r\n\r\nI'd prefer to see it like this:\r\n\r\n```\r\n|-- src/\r\n|   |-- app/\r\n|   |   |-- home/\r\n|   |   |   |-- home.js\r\n|   |   |   |-- home.spec.js\r\n|   |   |   |-- home.tpl.html\r\n```\r\n\r\nThis is a much simpler directory structure, but makes the `home` module very portable. It is also self-contained: it can be totally refactored without impacting the rest of the application.\r\n\r\n**(b) Multi-Component Features:**\r\n\r\nIf we have complex component, it is likely composed of multiple smaller components. For example, an editing component might have a persistence service, a representation service for translating markup to HTML, and a directive or two for display. With the existing structure, each component would be created independently and be mixed throughout the various layers; without a comprehensive, holistic understanding of the application, it is difficult to see how these components are (or should be) inter-related. It demands manually surfing through the code and/or doing searches for component names.\r\n\r\nA cleaner directory structure would look something like this:\r\n\r\n```\r\n|-- src/\r\n|   |-- components/\r\n|   |   |-- editor/\r\n|   |   |   |-- editing.js\r\n|   |   |   |-- editor.js\r\n|   |   |   |-- editor.spec.js\r\n|   |   |   |-- editingStorage.js\r\n|   |   |   |-- editingStorage.spec.js\r\n|   |   |   |-- editingRender.js\r\n|   |   |   |-- editingRender.spec.js\r\n```\r\n\r\nNow it's pretty clear we're talking about one component, albeit a complex one that spans multiple layers. But each sub-component of the editor is still standalone, if need be - that's just good programming.\r\n\r\n### Isolate the Modules\r\n\r\nA logical extension of this reorganization is to so-define our modules. In this pattern, each directory roughly corresponds to a module. Instead of this:\r\n\r\n```js\r\nangular.module( 'myApp' )\r\n  .controller( 'HomeCtrl', function ($scope) {\r\n    // ...\r\n  });\r\n```\r\n\r\nWe would have this:\r\n\r\n```js\r\nangular.module( 'home', [] )\r\n  .controller('HomeCtrl', function ($scope) {\r\n    // ...\r\n  });\r\n```\r\n\r\nSimilarly for the editing component:\r\n\r\n```js\r\nangular.module( 'editor', [\r\n  'editing.editor',\r\n  'editing.editingStorage',\r\n  'editing.editingRender'\r\n])\r\n```\r\n\r\nWhere those modules are defined in their respective files. And our main `app.js` file simply requires the top-level modules:\r\n\r\n```js\r\nangular.module( 'myApp', [\r\n  'home',\r\n  'editing'\r\n]);\r\n```\r\n\r\n### Adjacent Tests\r\n\r\nEveryone coming from server-side development (including myself) is familiar with the separate `test` directory, but I've always found it vexing. Placing test files directly adjacent to the code they test makes them easier to locate. More important, however, is reusability; if our tests are in a separate directory, we now have two things we have to copy between projects in order to reuse a component.\r\n\r\nThis is where it's important to separate two kinds of projects: libraries and apps. When developing libraries, we design them to be self-contained and self-sufficient, so we have no need to take tests with us to reuse in another project - that should have all been part of a build. But when developing apps, where some components may depend more subtly on other components (or at least on assumptions about our app architecture), it makes sense to take the tests with us and ensure they still pass in the new environment. Also see the 'Internal \"Components\"' section below.\r\n\r\nIt's okay to keep the tests side-by-side because our build tools are sophisticated enough to be able to tell the difference. Grunt 0.4, for example, now includes negative file selectors, so our build can exclude files with patterns like `src/**/*.spec.js` or `src/**/*Spec.js` from compilation and minification.\r\n\r\n### Adjacent Templates\r\n\r\nThe same concept also applies to views, partials, and templates. I also prefer they be suffixed with `.tpl.html` or something similar to indicate they're fragments.\r\n\r\n### Modularized Routing\r\n\r\nUsing the above example, `yo angular:route home` would generate this:\r\n\r\n```\r\n|-- src/\r\n|   |-- app/\r\n|   |   |-- home/\r\n|   |   |   |-- home.js\r\n|   |   |   |-- home.spec.js\r\n|   |   |   |-- home.tpl.html\r\n```\r\n\r\nBut instead of defining the route in `app.js`, we would let the `home` module set up its own routing:\r\n\r\n```js\r\nangular.module( 'home', [] )\r\n\r\n.config( function ( $routeProvider ) {\r\n  $routeProvider\r\n    .when( '/home', {\r\n      templateUrl: 'home/home.tpl.html',\r\n      controller: 'HomeCtrl'\r\n    });\r\n})\r\n\r\n.controller( 'HomeCtrl', function ( $scope ) {\r\n    // ...\r\n})\r\n```\r\n\r\nNothing is required in the `app.js` in terms of routing, unless the user should choose to define a default redirect, such as to `/home`.\r\n\r\n### Feature Nesting\r\n\r\nThe existing directory structure is very flat. For small projects, this is perfectly fine, but for non-trivial projects it can become a file management nightmare. If we organize our code by the feature or component they implement and use adjacent templates and tests, it also makes sense to be able to nest them. \r\n\r\nConsidering the route example:\r\n\r\n```\r\n|-- src/\r\n|   |-- app/\r\n|   |   |-- products/\r\n|   |   |   |-- products.js\r\n|   |   |   |-- products.spec.js\r\n|   |   |   |-- products.tpl.html\r\n|   |   |   |-- create/\r\n|   |   |   |   |-- create.js\r\n|   |   |   |   |-- create.tpl.html\r\n|   |   |   |-- ...\r\n```\r\n\r\nIn this case, each directory should roughly correspond to a single \"submodule\". The `products` directory is a module called `products`, making `create` something like `products.create`. Using this pattern, the `products` module can require all requisite submodules:\r\n\r\n```js\r\nangular.module( 'products', [\r\n  'products.list',\r\n  'products.view',\r\n  'products.create',\r\n  'products.search'\r\n]);\r\n```\r\n\r\nAgain, because the target is reusability, each app module is responsible for declaring its own dependencies, which will \"bubble up\" from `products.create` to `products` to `myApp`. Routing would work similarly; each submodule can define its own routing, in theory \"namespacing\" to its parent module. For example, `products.create` could define a route of `/products/create`.\r\n\r\nThis same \"nested\" pattern would also apply to complex components, though they would obviously not include routing. E.g.:\r\n\r\n```\r\n|-- src/\r\n|   |-- components/\r\n|   |   |-- editor/\r\n|   |   |   |-- editor.js\r\n|   |   |   |-- plugins/\r\n|   |   |   |   |-- syntax.js\r\n|   |   |   |   |-- align.js\r\n```\r\n\r\n### Internal \"Components\"\r\n\r\nLastly, I make a distinction between **app code**, the stuff that is somewhat unique to our problem domain, and **components**, the stuff that *may* come from a third party but that is more immediately reusable in unrelated projects.\r\n\r\nWith this concept in mind, we should be able to mix in the `components` directory the third-party libraries that come from Bower, the third-party libraries we download manually, and the reusable components that we are coding for this application specifically. e.g.:\r\n\r\n```\r\n|-- src/\r\n|   |-- components/\r\n|   |   |-- angular-placeholders/     <downloaded>\r\n|   |   |-- angular-ui-bootstrap/     <bower>\r\n|   |   |-- editor/                   <internal>\r\n```\r\n\r\n---\r\n\r\nAll combined, I think this would improve code reusability and readability."},"comment":{"url":"https://api.github.com/repos/yeoman/generator-angular/issues/comments/244240394","html_url":"https://github.com/yeoman/generator-angular/issues/109#issuecomment-244240394","issue_url":"https://api.github.com/repos/yeoman/generator-angular/issues/109","id":244240394,"user":{"login":"Priyanka-Veeranna","id":7449671,"avatar_url":"https://avatars.githubusercontent.com/u/7449671?v=3","gravatar_id":"","url":"https://api.github.com/users/Priyanka-Veeranna","html_url":"https://github.com/Priyanka-Veeranna","followers_url":"https://api.github.com/users/Priyanka-Veeranna/followers","following_url":"https://api.github.com/users/Priyanka-Veeranna/following{/other_user}","gists_url":"https://api.github.com/users/Priyanka-Veeranna/gists{/gist_id}","starred_url":"https://api.github.com/users/Priyanka-Veeranna/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Priyanka-Veeranna/subscriptions","organizations_url":"https://api.github.com/users/Priyanka-Veeranna/orgs","repos_url":"https://api.github.com/users/Priyanka-Veeranna/repos","events_url":"https://api.github.com/users/Priyanka-Veeranna/events{/privacy}","received_events_url":"https://api.github.com/users/Priyanka-Veeranna/received_events","type":"User","site_admin":false},"created_at":"2016-09-01T23:14:38Z","updated_at":"2016-09-01T23:14:38Z","body":"Any thoughts on if/when this generator will be updated to scaffold apps according to the new app structure [ https://docs.google.com/document/d/1XXMvReO8-Awi1EZXAXS4PzDzdNvV6pGcuaF4Q9821Es/pub](url) proposal by Google?"}}
{"actor":{"display_login":"Priyanka-Veeranna"}}