diff --git a/public/docs/_examples/style-guide/ts/05-14/app/shared/toast/toast.component.avoid.ts b/public/docs/_examples/style-guide/ts/05-14/app/shared/toast/toast.component.avoid.ts index 5e7a39c758..037ff2c8b5 100644 --- a/public/docs/_examples/style-guide/ts/05-14/app/shared/toast/toast.component.avoid.ts +++ b/public/docs/_examples/style-guide/ts/05-14/app/shared/toast/toast.component.avoid.ts @@ -7,7 +7,7 @@ export class ToastComponent implements OnInit { private defaults = { title: '', - message: 'May the Force be with You' + message: 'May the Force be with you' }; message: string; title: string; diff --git a/public/docs/_examples/style-guide/ts/05-14/app/shared/toast/toast.component.ts b/public/docs/_examples/style-guide/ts/05-14/app/shared/toast/toast.component.ts index 5a56ad6c04..d7b8ea4af0 100644 --- a/public/docs/_examples/style-guide/ts/05-14/app/shared/toast/toast.component.ts +++ b/public/docs/_examples/style-guide/ts/05-14/app/shared/toast/toast.component.ts @@ -14,7 +14,7 @@ export class ToastComponent implements OnInit { // private fields private defaults = { title: '', - message: 'May the Force be with You' + message: 'May the Force be with you' }; private toastElement: any; diff --git a/public/docs/ts/latest/guide/style-guide.jade b/public/docs/ts/latest/guide/style-guide.jade index 20910b5554..2a9e52b935 100644 --- a/public/docs/ts/latest/guide/style-guide.jade +++ b/public/docs/ts/latest/guide/style-guide.jade @@ -37,7 +37,8 @@ include ../_util-fns :marked ## File Structure Conventions - Some code examples display a file that has one or more similarly named companion files. (e.g. hero.component.ts and hero.component.html). + Some code examples display a file that has one or more similarly named companion files. + For example, `hero.component.ts` and `hero.component.html`. The guideline will use the shortcut `hero.component.ts|html|css|spec` to represent those various files. Using this shortcut makes this guide's file structures easier to read and more terse. @@ -47,29 +48,29 @@ a(id='toc') :marked ## Table of Contents - 1. [Single Responsibility](#single-responsibility) + 1. [Single responsibility](#single-responsibility) 1. [Naming](#naming) - 1. [Coding Conventions](#coding-conventions) - 1. [App Structure and Angular Modules](#app-structure-and-angular-modules) + 1. [Coding conventions](#coding-conventions) + 1. [App structure and Angular modules](#app-structure-and-angular-modules) 1. [Components](#components) 1. [Directives](#directives) 1. [Services](#services) - 1. [Data Services](#data-services) - 1. [Lifecycle Hooks](#lifecycle-hooks) + 1. [Data services](#data-services) + 1. [Lifecycle hooks](#lifecycle-hooks) 1. [Appendix](#appendix) .l-main-section :marked ## Single Responsibility - Apply the [Single Responsibility Principle](https://wikipedia.org/wiki/Single_responsibility_principle) to all components, services, and other symbols. + Apply the [Single Responsibility Principle (SPR)](https://wikipedia.org/wiki/Single_responsibility_principle) to all components, services, and other symbols. This helps make the app cleaner, easier to read and maintain, and more testable. ### Rule of One #### Style 01-01 .s-rule.do :marked - **Do** define one thing (e.g. service or component) per file. + **Do** define one thing, such as a service or component, per file. .s-rule.consider :marked @@ -77,7 +78,8 @@ a(id='toc') .s-why :marked - **Why?** One component per file makes it far easier to read, maintain, and avoid collisions with teams in source control. + **Why?** One component per file makes it far easier to read, maintain, and avoid + collisions with teams in source control. .s-why :marked @@ -85,7 +87,7 @@ a(id='toc') .s-why.s-why-last :marked - **Why?** A single component can be the default export for its file which facilitates lazy loading with the Router. + **Why?** A single component can be the default export for its file which facilitates lazy loading with the router. :marked The key is to make the code more reusable, easier to read, and less mistake prone. @@ -93,7 +95,8 @@ a(id='toc') +makeExample('style-guide/ts/01-01/app/heroes/hero.component.avoid.ts', '', 'app/heroes/hero.component.ts')(avoid=1) :marked - Better to redistribute the component and supporting activities into their own dedicated files. + It is a better practice to redistribute the component and its + supporting classes into their own, dedicated files. +makeTabs( `style-guide/ts/01-01/main.ts, @@ -203,7 +206,7 @@ a(href="#toc") Back to top .s-rule.do :marked - **Do** use conventional type names including `.service`, `.component`, `.pipe`, `.module`, `.directive`. + **Do** use conventional type names including `.service`, `.component`, `.pipe`, `.module`, and `.directive`. Invent additional type names if you must but take care not to create too many. .s-why @@ -212,7 +215,7 @@ a(href="#toc") Back to top .s-why :marked - **Why?** Make it easy to find a specific file type using an editor or IDE's fuzzy search techniques. + **Why?** Type names make it easy to find a specific file type using an editor or IDE's fuzzy search techniques. .s-why :marked @@ -221,7 +224,7 @@ a(href="#toc") Back to top .s-why.s-why-last :marked - **Why?** Provides pattern matching for any automated tasks. + **Why?** Type names provide pattern matching for any automated tasks. a(href="#toc") Back to top @@ -236,24 +239,25 @@ a(href="#toc") Back to top .s-rule.do :marked - **Do** use upper camel case for class names. Match the name of the symbol to the name of the file. + **Do** use upper camel case for class names. .s-rule.do :marked - **Do** append the symbol name with the conventional suffix for a thing of that type - (e.g., `Component`, `Directive`, `Module`, `Pipe`, `Service`). + **Do** match the name of the symbol to the name of the file. .s-rule.do :marked - **Do** give the filename the conventional suffix for a file of that type - (e.g., `.component.ts`, `.directive.ts`, `.module.ts`, `.pipe.ts`, `.service.ts`). + **Do** append the symbol name with the conventional suffix (such as `Component`, + `Directive`, `Module`, `Pipe`, or `Service`) for a thing of that type. + +.s-rule.do + :marked + **Do** give the filename the conventional suffix (such as `.component.ts`, `.directive.ts`, + `.module.ts`, `.pipe.ts`, or `.service.ts`) for a file of that type. .s-why :marked - **Why?** Provides a consistent way to quickly identify and reference assets. - -.s-why.s-why-last - :marked - **Why?** Upper camel case is conventional for identifying objects that can be instantiated using a constructor. + **Why?** Consistent conventions make it easy to quickly identify + and reference assets of different types. - var top="vertical-align:top" table(width="100%") @@ -341,11 +345,15 @@ a(href="#toc") Back to top .s-rule.do :marked - **Do** use upper camel case for services. + **Do** suffix a service class name with Service. + For example, something that gets data or heroes + should be called a `DataService` or a `HeroService`. -.s-rule.do - :marked - **Do** suffix services with `Service` when it is not clear what they are (e.g. when they are nouns). + A few terms are unambiguously services. They typically + indicate agency by ending in "er". You may prefer to name + a service that logs messages `Logger` rather than `LoggerService`. + Decide if this exception is agreeable in your project. + As always, strive for consistency. .s-why :marked @@ -409,7 +417,7 @@ a(href="#toc") Back to top .s-rule.avoid :marked - **Avoid** putting app logic in the `main.ts`. Instead consider placing it in a component or service. + **Avoid** putting app logic in the `main.ts`. Instead, consider placing it in a component or service. .s-why :marked @@ -805,7 +813,7 @@ a(href="#toc") Back to top .s-why :marked - **Why?** lower camel case variable names (`heroRoutes`) are easier to read and understand + **Why?** Lower camel case variable names (`heroRoutes`) are easier to read and understand than the traditional UPPER_SNAKE_CASE names (`HERO_ROUTES`). .s-why.s-why-last @@ -822,7 +830,7 @@ a(href="#toc") Back to top :marked **Why?** The tradition of UPPER_SNAKE_CASE remains popular and pervasive, especially in third party modules. - It is rarely worth the effort to change them or the risk of breaking existing code and documentation. + It is rarely worth the effort to change them at the risk of breaking existing code and documentation. +makeExample('style-guide/ts/03-02/app/core/data.service.ts', '', 'app/shared/data.service.ts') :marked @@ -849,7 +857,7 @@ a(href="#toc") Back to top .s-why :marked **Why?** TypeScript guidelines - discourage the "I" prefix. + discourage the `I` prefix. .s-why :marked @@ -946,9 +954,9 @@ a(href="#toc") Back to top All of the app's code goes in a folder named `app`. All feature areas are in their own folder, with their own Angular module. - All content is 1 asset per file. Each component, service, and pipe is in its own file. - All 3rd party vendor scripts are stored in another folder and not in the `app` folder. - You didn't write them and you don't want them cluttering app. + All content is one asset per file. Each component, service, and pipe is in its own file. + All third party vendor scripts are stored in another folder and not in the `app` folder. + You didn't write them and you don't want them cluttering `app`. Use the naming conventions for files in this guide. a(href="#toc") Back to top @@ -1043,11 +1051,11 @@ a(href="#toc") Back to top :marked **Consider** configuring the IDE to hide distracting, irrelevant files such as generated `.js` and `.js.map` files. -s-why.s-why-last +.s-why.s-why-last :marked **Why?** No one wants to search for a file through seven levels of folders. A flat structure is easy to scan. - + On the other hand, psychologists believe that humans start to struggle when the number of adjacent interesting things exceeds nine. @@ -1099,7 +1107,7 @@ a(href="#toc") Back to top .s-rule.consider :marked - **Consider** creating a folder for a component when is has multiple accompanying files (`.ts`, `.html`, `.css` and `.spec`). + **Consider** creating a folder for a component when it has multiple accompanying files (`.ts`, `.html`, `.css` and `.spec`). .s-why :marked @@ -1111,7 +1119,7 @@ a(href="#toc") Back to top a(id='file-tree') :marked - Here is a compliant folder and file structure + Here is a compliant folder and file structure: .filetree .file <project root> @@ -1169,7 +1177,7 @@ a(id='file-tree') .l-sub-section :marked - While components in dedicated folder are widely preferred, + While components in dedicated folders are widely preferred, another option for small apps is to keep components flat (not in a dedicated folder). This adds up to four files to the existing folder, but also reduces the folder nesting. Whatever you choose, be consistent. @@ -1187,7 +1195,8 @@ a(href="#toc") Back to top .s-why :marked - **Why?** A developer can locate the code, identify what each file represents at a glance, the structure is as flat as it can be, and there is no repetitive nor redundant names. + **Why?** A developer can locate the code, identify what each file represents + at a glance, the structure is as flat as it can be, and there are no repetitive or redundant names. .s-why :marked @@ -1214,7 +1223,7 @@ a(href="#toc") Back to top **Why?** Angular modules make it easier to isolate, test, and re-use features. .file-tree-reference - a(href="#file-tree") Refer here to this Folder and File Structure example + a(href="#file-tree") Refer to this _folder and file structure_ example. a(href="#toc") Back to top :marked @@ -1303,7 +1312,19 @@ a(href="#toc") Back to top .s-rule.do :marked - **Do** put common components, directives and pipes that will be used throughout the application by other feature modules in the `SharedModule`, where those assets are expected to share a new instance of themselves (not singletons). + **Do** declare components, directives, and pipes in a shared module when those + items will be re-used and referenced by the components declared in other feature modules. + +.s-rule.consider + :marked + **Consider** using the name SharedModule, when the contents of a shared + module are referenced across the entire application. + +.s-rule.do + :marked + **Do** not provide services in shared modules. Services are usually + singletons that are provided once for the entire application or + in a particular feature module. .s-rule.do :marked @@ -1382,9 +1403,16 @@ a(href="#toc") Back to top ### Core Feature Module #### Style 04-11 -.s-rule.do +.s-rule.consider :marked - **Do** collect single-use classes and hiding their gory details inside `CoreModule`. A simplified root `AppModule` imports `CoreModule` in its capacity as orchestrator of the application as a whole. + **Consider** collecting numerous, auxiliary, single-use classes inside a core module + to simplify the apparent structure of a feature module. + +.s-rule.consider + :marked + **Consider** calling the application-wide core module, `CoreModule`. + Importing `CoreModule` into the root `AppModule` reduces its complexity + and emphasizes its role as orchestrator of the application as a whole. .s-rule.do :marked @@ -1431,7 +1459,7 @@ a(href="#toc") Back to top .s-rule.do :marked - **Do** export all symbols that from the `CoreModule` that the `AppModule` will import and make available for other feature modules to use. + **Do** export all symbols from the `CoreModule` that the `AppModule` will import and make available for other feature modules to use. .s-why :marked @@ -1692,7 +1720,7 @@ a(href="#toc") Back to top .s-why :marked **Why?** If you ever need to rename the property or event name associated with - `@Input` or `@Output`, you can modify it a single place. + `@Input` or `@Output`, you can modify it in a single place. .s-why :marked @@ -1721,7 +1749,8 @@ a(href="#toc") Back to top .s-why.s-why-last :marked - **Why?** May lead to confusion when the output or the input properties of a given directive are named a given way but exported differently as a public API. + **Why?** May lead to confusion when the output or the input + properties of a given directive are named one way but exported differently as a public API. +makeExample('style-guide/ts/05-13/app/heroes/shared/hero-button/hero-button.component.avoid.ts', 'example', 'app/heroes/shared/hero-button/hero-button.component.ts')(avoid=1) :marked @@ -1991,8 +2020,9 @@ a(href="#toc") Back to top .s-why :marked - **Why?** When providing the service to a top level component, that instance is shared and available to all child components of that top level component. - + **Why?** When providing the service to a top level component, + that instance is shared and available to all child components of that top level component. + .s-why :marked **Why?** This is ideal when a service is sharing methods or state. @@ -2022,7 +2052,8 @@ a(href="#toc") Back to top .s-why :marked - **Why?** The Angular DI mechanism resolves all dependencies of services based on their types declared with the services' constructors. + **Why?** The Angular Dependency Injection (DI) mechanism resolves a service's own + dependencies based on the declared types of that service's constructor parameters. .s-why.s-why-last :marked @@ -2061,7 +2092,13 @@ a(href="#toc") Back to top .s-why.s-why-last :marked - **Why?** Data service implementation may have very specific code to handle the data repository. This may include headers, how to talk to the data, or other services such as `Http`. Separating the logic into a data service encapsulates this logic in a single place hiding the implementation from the outside consumers (perhaps a component), also making it easier to change the implementation. + **Why?** The details of data management, such as headers, HTTP methods, + caching, error handling, and retry logic, are irrelevant to components + and other data consumers. + + A data service encapsulates these details. It's easier to evolve these + details inside the service without affecting its consumers. And it's + easier to test the consumers with mock service implementations. a(href="#toc") Back to top @@ -2084,8 +2121,8 @@ a(href="#toc") Back to top .s-why.s-why-last :marked - **Why?** Strongly-typed method signatures. - The compiler and editor can call out misspellings. + **Why?** Lifecycle interfaces prescribe typed method + signatures. use those signatures to flag spelling and syntax mistakes. +makeExample('style-guide/ts/09-01/app/heroes/shared/hero-button/hero-button.component.avoid.ts', 'example', 'app/heroes/shared/hero-button/hero-button.component.ts')(avoid=1) :marked