docs(style-guide): edit copy (#3020)

This commit is contained in:
Kapunahele Wong 2017-01-03 15:43:57 -05:00 committed by Ward Bell
parent d057f73c02
commit 6d431f11ce
3 changed files with 93 additions and 56 deletions

View File

@ -7,7 +7,7 @@ export class ToastComponent implements OnInit {
private defaults = { private defaults = {
title: '', title: '',
message: 'May the Force be with You' message: 'May the Force be with you'
}; };
message: string; message: string;
title: string; title: string;

View File

@ -14,7 +14,7 @@ export class ToastComponent implements OnInit {
// private fields // private fields
private defaults = { private defaults = {
title: '', title: '',
message: 'May the Force be with You' message: 'May the Force be with you'
}; };
private toastElement: any; private toastElement: any;

View File

@ -37,7 +37,8 @@ include ../_util-fns
:marked :marked
## File Structure Conventions ## 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. 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 :marked
## Table of Contents ## Table of Contents
1. [Single Responsibility](#single-responsibility) 1. [Single responsibility](#single-responsibility)
1. [Naming](#naming) 1. [Naming](#naming)
1. [Coding Conventions](#coding-conventions) 1. [Coding conventions](#coding-conventions)
1. [App Structure and Angular Modules](#app-structure-and-angular-modules) 1. [App structure and Angular modules](#app-structure-and-angular-modules)
1. [Components](#components) 1. [Components](#components)
1. [Directives](#directives) 1. [Directives](#directives)
1. [Services](#services) 1. [Services](#services)
1. [Data Services](#data-services) 1. [Data services](#data-services)
1. [Lifecycle Hooks](#lifecycle-hooks) 1. [Lifecycle hooks](#lifecycle-hooks)
1. [Appendix](#appendix) 1. [Appendix](#appendix)
.l-main-section .l-main-section
:marked :marked
## Single Responsibility ## 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. This helps make the app cleaner, easier to read and maintain, and more testable.
### <a id="01-01"></a>Rule of One ### <a id="01-01"></a>Rule of One
#### <a href="#01-01">Style 01-01</a> #### <a href="#01-01">Style 01-01</a>
.s-rule.do .s-rule.do
:marked :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 .s-rule.consider
:marked :marked
@ -77,7 +78,8 @@ a(id='toc')
.s-why .s-why
:marked :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 .s-why
:marked :marked
@ -85,7 +87,7 @@ a(id='toc')
.s-why.s-why-last .s-why.s-why-last
:marked :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 :marked
The key is to make the code more reusable, easier to read, and less mistake prone. 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) +makeExample('style-guide/ts/01-01/app/heroes/hero.component.avoid.ts', '', 'app/heroes/hero.component.ts')(avoid=1)
:marked :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( +makeTabs(
`style-guide/ts/01-01/main.ts, `style-guide/ts/01-01/main.ts,
@ -203,7 +206,7 @@ a(href="#toc") Back to top
.s-rule.do .s-rule.do
:marked :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. Invent additional type names if you must but take care not to create too many.
.s-why .s-why
@ -212,7 +215,7 @@ a(href="#toc") Back to top
.s-why .s-why
:marked :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 .s-why
:marked :marked
@ -221,7 +224,7 @@ a(href="#toc") Back to top
.s-why.s-why-last .s-why.s-why-last
:marked :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 a(href="#toc") Back to top
@ -236,24 +239,25 @@ a(href="#toc") Back to top
.s-rule.do .s-rule.do
:marked :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 .s-rule.do
:marked :marked
**Do** append the symbol name with the conventional suffix for a thing of that type **Do** match the name of the symbol to the name of the file.
(e.g., `Component`, `Directive`, `Module`, `Pipe`, `Service`).
.s-rule.do .s-rule.do
:marked :marked
**Do** give the filename the conventional suffix for a file of that type **Do** append the symbol name with the conventional suffix (such as `Component`,
(e.g., `.component.ts`, `.directive.ts`, `.module.ts`, `.pipe.ts`, `.service.ts`). `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 .s-why
:marked :marked
**Why?** Provides a consistent way to quickly identify and reference assets. **Why?** Consistent conventions make it easy to quickly identify
and reference assets of different types.
.s-why.s-why-last
:marked
**Why?** Upper camel case is conventional for identifying objects that can be instantiated using a constructor.
- var top="vertical-align:top" - var top="vertical-align:top"
table(width="100%") table(width="100%")
@ -341,11 +345,15 @@ a(href="#toc") Back to top
.s-rule.do .s-rule.do
:marked :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 A few terms are unambiguously services. They typically
:marked indicate agency by ending in "er". You may prefer to name
**Do** suffix services with `Service` when it is not clear what they are (e.g. when they are nouns). 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 .s-why
:marked :marked
@ -409,7 +417,7 @@ a(href="#toc") Back to top
.s-rule.avoid .s-rule.avoid
:marked :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 .s-why
:marked :marked
@ -805,7 +813,7 @@ a(href="#toc") Back to top
.s-why .s-why
:marked :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`). than the traditional UPPER_SNAKE_CASE names (`HERO_ROUTES`).
.s-why.s-why-last .s-why.s-why-last
@ -822,7 +830,7 @@ a(href="#toc") Back to top
:marked :marked
**Why?** The tradition of UPPER_SNAKE_CASE remains popular and pervasive, **Why?** The tradition of UPPER_SNAKE_CASE remains popular and pervasive,
especially in third party modules. 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') +makeExample('style-guide/ts/03-02/app/core/data.service.ts', '', 'app/shared/data.service.ts')
:marked :marked
@ -849,7 +857,7 @@ a(href="#toc") Back to top
.s-why .s-why
:marked :marked
**Why?** <a href="https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines" target="_blank">TypeScript guidelines</a> **Why?** <a href="https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines" target="_blank">TypeScript guidelines</a>
discourage the "I" prefix. discourage the `I` prefix.
.s-why .s-why
:marked :marked
@ -946,9 +954,9 @@ a(href="#toc") Back to top
All of the app's code goes in a folder named `app`. 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 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 content is one 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. 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. You didn't write them and you don't want them cluttering `app`.
Use the naming conventions for files in this guide. Use the naming conventions for files in this guide.
a(href="#toc") Back to top a(href="#toc") Back to top
@ -1043,11 +1051,11 @@ a(href="#toc") Back to top
:marked :marked
**Consider** configuring the IDE to hide distracting, irrelevant files such as generated `.js` and `.js.map` files. **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 :marked
**Why?** No one wants to search for a file through seven levels of folders. **Why?** No one wants to search for a file through seven levels of folders.
A flat structure is easy to scan. A flat structure is easy to scan.
On the other hand, On the other hand,
<a href="https://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two" target="_blank">psychologists believe</a> <a href="https://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two" target="_blank">psychologists believe</a>
that humans start to struggle when the number of adjacent interesting things exceeds nine. 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 .s-rule.consider
:marked :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 .s-why
:marked :marked
@ -1111,7 +1119,7 @@ a(href="#toc") Back to top
a(id='file-tree') a(id='file-tree')
:marked :marked
Here is a compliant folder and file structure Here is a compliant folder and file structure:
.filetree .filetree
.file &lt;project root&gt; .file &lt;project root&gt;
@ -1169,7 +1177,7 @@ a(id='file-tree')
.l-sub-section .l-sub-section
:marked :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). 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. This adds up to four files to the existing folder, but also reduces the folder nesting.
Whatever you choose, be consistent. Whatever you choose, be consistent.
@ -1187,7 +1195,8 @@ a(href="#toc") Back to top
.s-why .s-why
:marked :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 .s-why
:marked :marked
@ -1214,7 +1223,7 @@ a(href="#toc") Back to top
**Why?** Angular modules make it easier to isolate, test, and re-use features. **Why?** Angular modules make it easier to isolate, test, and re-use features.
.file-tree-reference .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 a(href="#toc") Back to top
:marked :marked
@ -1303,7 +1312,19 @@ a(href="#toc") Back to top
.s-rule.do .s-rule.do
:marked :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 .s-rule.do
:marked :marked
@ -1382,9 +1403,16 @@ a(href="#toc") Back to top
### <a id="04-11"></a>Core Feature Module ### <a id="04-11"></a>Core Feature Module
#### <a href="#04-11">Style 04-11</a> #### <a href="#04-11">Style 04-11</a>
.s-rule.do .s-rule.consider
:marked :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 .s-rule.do
:marked :marked
@ -1431,7 +1459,7 @@ a(href="#toc") Back to top
.s-rule.do .s-rule.do
:marked :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 .s-why
:marked :marked
@ -1692,7 +1720,7 @@ a(href="#toc") Back to top
.s-why .s-why
:marked :marked
**Why?** If you ever need to rename the property or event name associated with **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 .s-why
:marked :marked
@ -1721,7 +1749,8 @@ a(href="#toc") Back to top
.s-why.s-why-last .s-why.s-why-last
:marked :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) +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 :marked
@ -1991,8 +2020,9 @@ a(href="#toc") Back to top
.s-why .s-why
:marked :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 .s-why
:marked :marked
**Why?** This is ideal when a service is sharing methods or state. **Why?** This is ideal when a service is sharing methods or state.
@ -2022,7 +2052,8 @@ a(href="#toc") Back to top
.s-why .s-why
:marked :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 .s-why.s-why-last
:marked :marked
@ -2061,7 +2092,13 @@ a(href="#toc") Back to top
.s-why.s-why-last .s-why.s-why-last
:marked :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 a(href="#toc") Back to top
@ -2084,8 +2121,8 @@ a(href="#toc") Back to top
.s-why.s-why-last .s-why.s-why-last
:marked :marked
**Why?** Strongly-typed method signatures. **Why?** Lifecycle interfaces prescribe typed method
The compiler and editor can call out misspellings. 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) +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 :marked