これは、Angular の公式ドキュメントの Style Guide の章を意訳したものです。所々抜け落ち、翻訳モレがありますがあしからずご了承を。
バージョン v4.3.4, v4.4.0-RC0 のドキュメントをベースにしています。
スタイルガイド
Angular構文、表記法、およびアプリケーション構造に関する有益なガイドをお探しですか?どうぞこちらへ!このスタイルガイドには、好ましい規則が示されています。なぜなら、なぜ重要なのかを説明するためです。
スタイルボキャブラリー
それぞれのガイドラインでは、良い例と悪い例を出すことで、すべてが一貫したプレゼンテーションを持っています。
各ガイドラインの表現は、その推奨がどれほど強いかを示しています。
Do ... 常に守らなければならないものです。常にというのは、言葉が強すぎるかもしれませんが、文字通り必ず従わなければならないガイドラインというのは非常にまれです。一方、Doのガイドラインを破るのであれば、本当に異例のケースが必要です。
Consider ... 一般的なものとして、ガイドラインを守ってください。ガイドラインの背景にある意味を十分に理解し、逸脱する正当な理由がある場合は、そうしてください。一貫性を持つことに努めてください。
Avoid ... 避けた方が良いでしょう。お勧めしません。このアプローチを採らないでください。回避するためのコード例には、間違いなく赤いヘッダーがあります。
Why? ... この推奨事項に従う理由が示されています。
ファイル構造の規則
いくつかのコード例では、1つ以上の同様の名前のコンパニオンファイルを含むファイルが表示されます。たとえば、hero.component.ts
およびhero.component.html
などです。
ガイドラインでは、ショートカット hero.component.ts|html|css|spec
を使用して、これらのさまざまなファイルを表しています。このショートカットを使用すると、このガイドのファイル構造が読みやすくなり、簡潔になります。
単独責任
すべてのコンポーネント、サービス、およびその他のシンボルに単一責任の原則(SRP)を適用します。これは、アプリをよりきれいにし、読みやすく、維持しやすく、テスト可能にするのに役立ちます。
1つのルール
Style 01-01
Do ファイルごとに、サービスやコンポーネントなどの1つを定義します。
Consider ファイルを400行のコードに限定することを検討してください。
Why? ファイルごとに1つのコンポーネントがあるため、ソース管理ツールを用いたチーム開発で生じるコンフリクトコードをより簡単に読み取り、維持し、解消することができます。
Why? ファイルごとに1つのコンポーネントがあるため、変数を共有したり、不要なクロージャを作成したり、依存関係との望ましくない結びつきが発生することがあります。そんなファイル内のコンポーネントを結合する際に、しばしば発生する隠れたバグを回避できます。
Why? 単一のコンポーネントをファイルのデフォルトのエクスポートすることで、Routerでの遅延ロードを容易にします。
ポイントとしては、コードをより再利用しやすく、読みやすく、間違いを少なくすることです。
次のネガティブな例は、AppComponentを定義し、アプリケーションをbootstrapし、Hero
モデルオブジェクトを定義し、サーバーからheroをすべて同じファイルに読み込みます。Don'tと同じようなことはしないでください。
コンポーネントとそのサポートクラスを専用の専用ファイルに再配布する方が良い方法です。
アプリが成長するにつれ、このルールはさらに重要になります。
コンパクトな関数
Style 01-02
Do 関数は小さく定義しましょう
Consider 関数は、75行以下に制限することを検討してください。
Why? 小さな関数は、1つのことだけを行い、1つの目的を果たすことだけに留めることで、テストするのが容易になります。
Why? 小さな関数は再利用を促進します。
Why? 小さな関数は読みやすくなります。
Why? 小さな関数はメンテナンスしやすくなります。
Why? 小さな関数は、外部スコープと変数を共有していたり、不要なクロージャを作成したり、望ましくない依存関係を作り出すことによって、大きな関数内に入り込む隠れたバグを回避します。
ネーミング
命名規則は、保守性と可読性にとって非常に重要です。このマニュアルでは、ファイル名とシンボル名の命名規則を推奨しています。
一般的な命名ガイドライン
Style 02-01
すべてのシンボルに一貫した名前を使用してください。
シンボルの特徴を記述し、そのタイプを記述するパターンに従ってください。推奨パターンはfeature.type.ts
です。
Why? 命名規則は、コンテンツを一目で見つける一貫した方法を提供します。プロジェクト内の一貫性は不可欠です。チームとの一貫性は重要です。企業全体の一貫性は非常に効率的です。
Why? 命名規則は、単に目的のコードをより早く見つけ出し、理解しやすくするために役立つはずです。
Why? フォルダとファイルの名前は、その意図を明確に伝える必要があります。たとえば、app/heroes/hero-list.component.ts
には、ヒーローのリストを管理するコンポーネントが含まれているでしょう。
ファイル名をドットとダッシュで区切る
Style 02-02
Do 説明的な名前で単語を区切るにはダッシュを使用します。
Do わかりやすい名前をタイプと区別するためにドットを使用してください。
Do コンポーネントの機能、そのタイプを記述するパターンに従って、すべてのコンポーネントに対して一貫したタイプ名を使用します。推奨パターンはfeature.type.tsです。
Do .service
、.component
、.pipe
、.module
および .directive
などの慣例の名前を使用します。あまり多くを作成しないように注意しなければならない場合は、追加の型名を作成してください。
Why? タイプ名は、ファイル内の内容をすばやく識別する一貫した方法を提供します。
Why? タイプ名は、エディタやIDEのファイル検索機能を使用して、特定のファイルタイプを簡単に見つけることができます。
Why? .service
のような省略されていない型名は説明的であり、明白です。.srv
、.svc
および.serv
などの略語は混乱する可能性があります。
Why? タイプ名は、自動化タスクのパターンマッチングを提供します。
シンボル(記号)とファイル名
Style 02-03
Do それらが表すものにちなんで命名されたすべてのアセットに対して一貫した名前を使用します。
Do クラス名には、アッパーキャメルケース(upper camel case)を使用してください。
Do シンボルの名前とファイルの名前を一致させます。
Do そのタイプのもののシンボル名に、慣例の接尾辞(Component
, Directive
, Module
, Pipe
, または Service
)を付加します。
Do そのタイプのファイルに対して、ファイル名に通常の接尾辞(.component.ts
、.directive.ts
、.module.ts
、.pipe.ts
、または.service.ts
など)を付けます。
Why? 一貫性の持った規則によって、異なる種類のアセットを迅速かつ容易に識別することができ、参照しやすくなります。
Symbol Name | File Name |
---|---|
@Component({ ... }) export class AppComponent { } |
app.component.ts |
@Component({ ... }) export class HeroesComponent { } |
heroes.component.ts |
@Component({ ... }) export class HeroListComponent { } |
hero-list.component.ts |
@Component({ ... }) export class HeroDetailComponent { } |
hero-detail.component.ts |
@Directive({ ... }) export class ValidationDirective { } |
validation.directive.ts |
@NgModule({ ... }) export class AppModule |
app.module.ts |
@Pipe({ name: 'initCaps' }) export class InitCapsPipe implements PipeTransform { } |
init-caps.pipe.ts |
@Injectable() export class UserProfileService { } |
user-profile.service.ts |
サービス名
Style 02-04
Do その機能の名前を付けられたすべてのサービスに一貫した名前を使用します。
Do Service
でサービスクラス名の後に接尾辞を付けます。 たとえば、データやヒーローを取得するものは、DataService
またはHeroService
と呼びます。
いくつかの用語は明白なサービスです。それらは通常、“-er”で終わる役割を示します。例えばメッセージをロギングするサービスにはLoggerService
ではなくLogger
という名前を付けることをお勧めします。プロジェクトでこの例外(Serviceを末尾につけないこと)が納得できるかどうかを決定します。もちろん、一貫性を保つためのの努力は怠たらないでください。
Why? サービスを迅速に識別して参照できる、一貫した方法を提供します。
Why? Logger
などの明確なサービス名には接尾辞は必要ありません。
Why? Credit
などのサービス名は名詞であり、サフィックスを必要とするため、サービスであれ他のものであれ、明白でない場合は接尾辞を付ける必要があります。
Symbol Name | File Name |
---|---|
@Injectable() export class HeroDataService { } |
hero-data.service.ts |
@Injectable() export class CreditService { } |
credit.service.ts |
@Injectable() export class Logger { } |
logger.service.ts |
Bootstrapping
Style 02-05
Do アプリケーションのBootstrapロジックとプラットフォームに関連するロジックは、main.ts
という名前のファイルに入れてください。
Do Bootstrapロジックにエラー処理を含めます。
Avoid アプリケーションロジックをmain.tsに入れないでください。アプリケーションロジックは、コンポーネントまたはサービスに記述することを検討してください。
Why? アプリケーションの起動ロジックに関する一貫した規約に従います。
Why? 他のテクノロジープラットフォームの慣例に従います。
main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule)
.then(success => console.log(`Bootstrap success`))
.catch(err => console.error(err));
ディレクティブ セレクタ
Style 02-06
Do ディレクティブのセレクタに名前を付けるには、よりロワーキャメルケース(lower camel case)を使用します。
Why? ビューにバインドされたディレクティブで定義されたプロパティの名前を、属性名と一貫して保持します。
Why? Angular HTMLパーサーは大文字と小文字を区別し、キャメルの大文字小文字を認識します。
コンポーネントのカスタム接頭辞
Style 02-07
Do ハイフンで区切られた小文字の要素セレクタ値(例:admin-users)を使用してください。
Do コンポーネントセレクタにはカスタムプレフィックスを使用します。たとえば、接頭辞toh
は Tour of Heroes を表し、接頭辞admin
はAdmin機能ドメインを表します。
Do 機能ドメインまたはアプリケーション自体を識別するプレフィックスを使用します。
Why? 他のアプリケーションのコンポーネントやネイティブHTML要素との要素名のコンフリクトを防ぎます。
Why? 他のアプリでコンポーネントをprovideして共有するのが簡単になります。
Why? コンポーネントはDOMで簡単に識別できます。
ディレクティブのカスタム接頭辞
Style 02-08
Do ディレクティブのセレクタにカスタムプレフィックス(例:Tour of Heroesのプレフィックスtoh
)を使用します。
Do セレクターがネイティブのHTML属性と一致するものでない限り、ロワーキャメルケース(lower camel case)で非要素セレクターを綴ります。
Why? 名前のコンフリクトを防ぎます。
Why? ディレクティブを容易に識別できます。
パイプ名
Style 02-09
Do すべてのパイプには機能にちなんでネーミングしてください。
Why? パイプを素早く識別し参照する一貫した方法を提供します。
Symbol Name | File Name |
---|---|
@Pipe({ name: 'ellipsis' }) export class EllipsisPipe implements PipeTransform { } |
ellipsis.pipe.ts |
@Pipe({ name: 'initCaps' }) export class InitCapsPipe implements PipeTransform { } |
init-caps.pipe.ts |
ユニットテストのファイル名
Style 02-10
Do コンポーネントのユニットテスト用specファイルの名前は、テストするコンポーネントと同じにしてください。
Do ファイル名は、.spec
という接尾辞にしてください。
Why? テストファイルをすばやく識別する一貫した方法を提供します。
Why? karmaまたは他のテストランナーツールに対して、ユニットテストファイル名のパターンマッチングを提供します。
Test Type | File Names |
---|---|
Components | heroes.component.spec.ts, hero-list.component.spec.ts, hero-detail.component.spec.ts |
Services | logger.service.spec.ts, hero.service.spec.ts, filter-text.service.spec.ts |
Pipes | ellipsis.pipe.spec.ts, init-caps.pipe.spec.ts |
End-to-End (E2E) テストのファイル名
Style 02-11
単体テストファイル名
Do テストする機能の後に.e2e-spec
の接尾辞を付けてe2eのテストspecファイルを指定します。
Why? エンドツーエンドのテストを迅速に識別する一貫した方法を提供します。
Why? テストランナーとビルドオートメーションのために、ファイル名のパターンマッチングを提供します。
Test Type | File Names |
---|---|
End-to-End Tests | app.e2e-spec.ts, heroes.e2e-spec.ts |
Angular NgModule のネーミング
Style 02-12
Do 接尾辞Moduleを付けたシンボル名を追加します。
Do ファイル名に.module.ts
拡張子を付けます。
Do モジュールが存在する機能とフォルダの後にモジュール名を付けます。
Why? モジュールを迅速に識別して参照する一貫した方法を提供します。
Why? アッパーキャメルケースは、コンストラクタを使用してインスタンス化できるオブジェクトを識別するための従来のものです。
Why? モジュールを同じ名前のフィーチャーのルートとして簡単に識別します。
Do RoutingModuleでRoutingModule
クラス名に接尾辞を付けます。
Do RoutingModuleのファイル名を-routing.module.ts
で終わらせるようにします。
Why? RoutingModule
は、Angular routerの設定専用のモジュールです。一貫したクラス名とファイル名の規則により、これらのモジュールを簡単に見つけて検証することができます。
Symbol Name | File Name |
---|---|
@NgModule({ ... }) export class AppModule { } |
app.module.ts |
@NgModule({ ... }) export class HeroesModule { } |
heroes.module.ts |
@NgModule({ ... }) export class VillainsModule { } |
villains.module.ts |
@NgModule({ ... }) export class AppRoutingModule { } |
app-routing.module.ts |
@NgModule({ ... }) export class HeroesRoutingModule { } |
heroes-routing.module.ts |
コーディング規則
コーディング、命名、およびホワイトスペースの規則の一貫した組み合わせを持ちましょう。
クラス
Style 03-01
Do クラスに名前を付けるときは、上のラクセルケースを使用してください。
Why? 従来のクラス名の考え方に従います。
Why? クラスをインスタンス化してインスタンスを構築できます。慣例により、アッパーキャメルケースの場合は構築可能なアセットを示しています。
定数
Style 03-02
Do アプリケーションのライフタイム(実行中)に値が変更されるべきでない場合、const
で変数を宣言します。
Why? 値が不変であることをコードの読み手に伝えます。
Why? TypeScriptは、即時の初期化を必要とし、その後の再割り当てを防止することによって、その意図を強化するのに役立ちます。
Consider const
変数は、ロワーキャメルケースを用いてください。
Why? 大文字小文字の変数名(heroRoutes
)は、従来のUPPER_SNAKE_CASE名(HERO_ROUTES
)よりも読みやすく理解しやすいです。
Why? UPPER_SNAKE_CASEでの定数の名前付けの伝統は、すぐにconst
宣言するアプローチはモダンなIDEが普及する前の時代のものです。TypeScriptは偶発的な再割り当てを防ぐことができます。
Do UPPER_SNAKE_CASEで綴られた既存のconst
変数を許容してください。
Why? UPPER_SNAKE_CASEの伝統は、特にサードパーティーモジュールでは広く普及しています。既存のコードとドキュメントを壊すリスクにさらされることはほとんどありません。
app/shared/data.service.ts
export const mockHeroes = ['Sam', 'Jill']; // 好ましい
export const heroesUrl = 'api/heroes'; // 好ましい
export const VILLAINS_URL = 'api/villains'; // 大目に見ようか
インターフェース
Style 03-03
Do アッパーキャメルケースを用いて、インターフェイスの名前を付けてください。
Consider I
プレフィックスを付けないでインターフェイスに名前を付けることを検討してください。
Consider インターフェイスの代わりにクラスを使用することを検討してください。
Why? TypeScriptのガイドラインでは、I
プレフィックスは無視されます。
Why? クラスだけでは、クラスプラスインターフェイスよりもコードが少なくなります。
Why? クラスはインタフェースとして機能することができます(extends
ではなくimplements
を使用します)。
Why? interface-classは、Angularの依存性注入のプロバイダルックアップトークンにすることができます。
プロパティとメソッド
Style 03-04
Do プロパティとメソッドに名前を付けるには、ロワーキャメルケースを使用します。
Avoid プライベートプロパティとメソッドの先頭にアンダースコアを付けないでください。
Why? プロパティとメソッドの従来の考え方に従います。
Why? JavaScriptには真のプライベートプロパティやメソッドがありません。
Why? TypeScriptでは、非公開のプロパティとメソッドを簡単に識別できます。
import 構文の行スペーシング
Style 03-06
Consider サードパーティのインポートとアプリケーションのインポートの間に空白行を1つ残すことを検討してください。
Consider import行は、モジュールによってアルファベット順に並べることw検討してください。
Consider 構造化されたimportシンボルをアルファベット順にリストすることを検討してください。
Why? 空の行はAngularのものと自分のものを分けます。
Why? アルファベット文字を使用すると、シンボルの読み込みと検索が簡単になります。
app/heroes/shared/hero.service.ts
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Hero } from './hero.model';
import { ExceptionService, SpinnerService, ToastService } from '../../core';
アプリケーション構造とNgModule
実装と長期ビジョンの短期的な視点を持っています。 小さいものから始めて、アプリがどこに向かうのかを覚えておいてください。
アプリのコードはすべてsrc
という名前のフォルダに格納されます。すべての機能エリアは、独自のNgModuleを持つ独自のフォルダにあります。
すべてのコンテンツはファイルごとに1つのアセットです。各コンポーネント、サービス、およびパイプは、それぞれのファイルにあります。すべてのサードパーティのベンダースクリプトはsrc
フォルダーに保存されず、別のフォルダーに保存されます。あなたはそれらを書いていないし、src
を混乱させたくない。このガイドのファイルには、命名規則を使用してください。
LIFT
Style 04-01
Do コードをすばやく見つけることができる(Locate code quickly)ように、また一目でコードを特定できる(Identify the code at a glance)ようにするために、できる限りフラットな構造に保ち(Flattest structure)、DRYを意識(Try to be DRY.)して、アプリを構造化してください。
Do これらの4つの基本的なガイドラインに従うように構造を定義し、重要性の順に列挙します。
Why? LIFTコードを素早く見つけることで、スケールがよく、モジュール化され、開発者の効率を向上させる一貫した構造を提供します。特定の構造に関するあなたの直感を確認するには、この機能のすべての関連ファイルをすばやく開いて作業をスタートできますか?
ファイルの配置
Style 04-02
Do コードを直感的に、簡単に、そして速く見つけられるようにしてください
Why? 効率的に作業するには、特にファイル名がわからない(または覚えていない)場合、ファイルをすばやく見つける必要があります。直感的な場所に関連ファイルを近くに置くと、時間が節約されます。記述的なフォルダ構造は、あなたとあなたの後に来る人々に異なる世界を作ります。
一意性
Style 04-03
Do ファイルに含まれているものとその内容を即座に知るように、ファイルに名前を付けてください。
Do ファイル名を記述し、ファイルの内容を正確に1つのコンポーネントに保tてください。
Avoid 1ファイルに複数のコンポーネント、複数のサービス、または複数のファイルが混在する状態は避けてください。
Why? コードハンティングに費やされる時間を少なくし、より効率化できます。長いファイル名は、短くて不明瞭な省略名よりはるかに優れています。
理解される小さな密接に関連した機能が複数ファイルに散らばるよりも、1ファイルの方が見つけやすい状況の方が多い場合は、このルールから逸脱することが有利な場合があります。抜け穴にならないように注意してください。
フラット
Style 04-04
Do できるだけフラットなフォルダ構造にしてください。
Consider フォルダが7つ以上のファイルに達すると、サブフォルダを作成することを検討してください。
Consider 生成された.js
ファイルや.js.map
ファイルなど、無関係な、無関係なファイルを隠すようにIDEを設定することを検討してください。
Why? 誰しも7階層レベルのフォルダからファイルを検索する必要はないでしょう。フラットな構造であれば簡単にスキャンできます。
一方、心理学者は、隣接する興味深いものの数が9を超えると、人間は苦労し始めると信じています。したがってフォルダに10個以上のファイルがある場合は、サブフォルダを作成する必要があります。
(ここでは心理学の話を出しましたが)あなたの快適さのレベルに基づいて決めてください。新しいフォルダを作成した方が明らかに価値があるとわかるまでは、フラットな構造を使用してください。
T-DRY (Try to be DRY)
Style 04-05
Do DRY(Don't Repeat Yourself)の原則に従ってください。
Avoid 読みやすさを犠牲にしないようにDRYを避けてください。
Why? DRYは重要ですが、LIFTの他の要素を犠牲にする場合は重要ではありません。それがT-DRYと呼ばれる理由です。たとえば、テンプレートの名前をhero-view.component.htmlとするのは冗長です。これは、拡張子が.html
の場合は明らかです。しかし何かが明白でないか、または慣習から出発する場合は、それを書き出してください。
全体的な構造ガイドライン
Style 04-06
Do 小さなものから始めて、アプリケーションがどこに向かうのかを覚えておいてください。
Do 実装と長期ビジョンの短期的な見解を持っているか。
Do すべてのアプリケーションのコードをsrc
という名前のフォルダに入れてください。
Consider 付随するファイルが複数ある場合(.ts
、.html
、.css
、.spec
)、コンポーネントのフォルダを作成することを検討してください。
Why? アプリの構造が小さくて簡単に初期段階で維持できるようにする一方で、アプリの成長に伴い進化しやすくなります。
Why? コンポーネントには4つのファイル(例:*.html
、*.css
、*.ts
、*.spec.ts
)が含まれていることが多く、ファイルが増えるとフォルダ内がすぐに混乱させる可能性があります。
ここに準拠したフォルダとファイル構造があります:
専用フォルダのコンポーネントが広く推奨されていますが、小さなアプリケーションの別のオプションはコンポーネントをフラットにすることです(専用フォルダではない)。これにより、既存のフォルダに最大4つのファイルが追加されますが、フォルダの入れ子も縮小されます。 どのようなものを選んでも、一貫性があります。
フォルダ単位の構造
Style 04-07
Do フォルダ名は、機能エリアが表す名前で作成するようにしてください。
Why? 開発者はコードを見つけて、各ファイルが何を表すかを一目で識別することができます。 構造はできるだけフラットであり、繰り返したり冗長な名前はありません。
Why? LIFTガイドラインはすべてカバーされています。
Why? コンテンツを整理し、LIFTのガイドラインに沿って整理しておくことで、アプリが混乱するのを防ぎます。
Why? 例えば10個以上のファイルがある場合は、一貫性のあるフォルダ構造でそれらを見つけるのが簡単で、フラットな構造では難しくなります。
Do 各フィーチャエリアにNgModuleを作成しますか?
Why? NgModuleは、ルーティング可能な機能を遅延ロードするのを容易にします。
Why? NgModuleを使用すると、機能の分離、テスト、再利用が容易になります。
App root module
Style 04-08
Do アプリケーションのルートフォルダ(例えば /src/app
)にNgModule
を作成します。
Why? すべてのアプリケーションには少なくとも1つのルートNgModule
が必要です。
Consider ルートモジュールのファイル名は、app.module.ts
にすることを検討してください。
Why? ルートモジュールの特定と識別が容易になります。
app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { HeroesComponent } from './heroes/heroes.component';
@NgModule({
imports: [
BrowserModule,
],
declarations: [
AppComponent,
HeroesComponent
],
exports: [ AppComponent ],
entryComponents: [ AppComponent ]
})
export class AppModule {}
Feature modules
Style 04-09
Do アプリケーション内の異なる機能単位でNgModule
を作成します。たとえば、Heroes featureです。
Do フィーチャ領域をフィーチャ領域と同じ名前のフォルダに配置します。たとえばapp/heroes
です。
Do フィーチャエリアとフォルダの名前を反映したフィーチャモジュールファイルに名前を付けます。たとえば、app/heroes/heroes.module.ts
などです。
Do フィーチャ領域、フォルダ、ファイルの名前を反映したフィーチャモジュールシンボルに名前を付けます。たとえば、app/heroes/heroes.module.ts
はHeroesModule
を定義します。
Why? フィーチャモジュールは、その実装を他のモジュールから公開または非表示にすることができます。
Why? フィーチャモジュールは、フィーチャエリアを構成する関連するコンポーネントの個別のセットを識別します。
Why? フィーチャモジュールは、簡単に、遅延して簡単にルーティングできます。
Why? フィーチャモジュールは、特定の機能と他のアプリケーション機能との明確な境界を定義します。
Why? フィーチャーモジュールは、異なるチームに開発責任を明確にしやすくするのに役立ちます。
Why? フィーチャモジュールはテストのために簡単に分離できます。
Shared feature module
Style 04-10
Do SharedModule
という名前のフィーチャモジュールを共有フォルダに作成します。たとえば、app/shared/shared.module.ts
はSharedModule
を定義します。
Do それらのアイテムが他の機能モジュールで宣言されたコンポーネントによって再利用され参照されるときに、共有モジュールのコンポーネント、ディレクティブ、パイプを宣言します。
Consider 共有モジュールの内容がアプリケーション全体で参照されている場合は、SharedModuleという名前を使用します。
Avoid 共有モジュールでサービスを提供する。サービスは、通常、アプリケーション全体または特定のフィーチャーモジュールで1回provideされるシングルトンです。
Do SharedModule内のアセットで必要なすべてのモジュールをインポートします。たとえば、CommonModuleとFormsModuleです。
Why? SharedModuleには、別の共通モジュールの機能が必要なコンポーネント、ディレクティブ、パイプが含まれます。 たとえば、CommonModuleのngForです。
Do SharedModule内のすべてのコンポーネント、ディレクティブ、およびパイプを宣言します。
Do 他のフィーチャモジュールが使用する必要があるSharedModuleからすべてのシンボルをエクスポートします。
Why? SharedModuleは、一般的に使用されるコンポーネント、ディレクティブおよびパイプを他の多くのモジュールのコンポーネントのテンプレートで使用できるようにするために存在します。
Why? SharedModuleでのアプリケーション全体のシングルトンプロバイダの指定は避けてください。 意図的なシングルトンはOKです。 世話をする。
Why? その共有モジュールをインポートする遅延ロードされた機能モジュールは、サービスの独自のコピーを作成し、望ましくない結果をもたらす可能性があります。
Why? 各モジュールが独自のサービスのインスタンスを持つことは望ましくありません。 それでもSharedModuleがサービスを提供する場合、実際に起こる危険があります。
Core feature module
Style 04-11
Consider フィーチャモジュールの見かけ上の構造を簡素化するために、コアモジュール内に多数の補助的な単一使用クラスを収集することを検討してください。
Consider アプリケーション全体のコアモジュールCoreModuleを呼び出すことを検討してください。CoreModuleをルートAppModuleにインポートすると、その複雑さが軽減され、アプリケーション全体のオーケストレーターとしての役割が強調されます。
Do コアフォルダにCoreModuleという名前のフィーチャモジュールを作成します(例:app / core / core.module.tsはCoreModuleを定義します)。
Do CoreModule内のアプリケーション全体でインスタンスが共有されるシングルトンサービスを配置します(ExceptionServiceやLoggerServiceなど)。
Do CoreModule(例えば、CommonModuleとFormsModule)のアセットで必要なすべてのモジュールをインポートします。
Why? CoreModuleは、1つ以上のシングルトンサービスを提供します。 Angularはプロバイダにアプリのルートインジェクタを登録し、各サービスのシングルトンインスタンスを、それが必要なコンポーネント(そのコンポーネントが熱心に遅延ロードされているかどうか)に利用できるようにします。
Why? CoreModuleにはシングルトンサービスが含まれます。 遅延ロードされたモジュールがこれらをインポートすると、意図されたアプリケーション全体のシングルトンではなく新しいインスタンスが取得されます。
Do CoreModule内のアプリケーション全体の単一使用コンポーネントを収集します。 AppModuleで一度読み込んでから、アプリケーションを起動し、他の場所には絶対にインポートしないでください。(NavComponentやSpinnerComponentなど)。
Why? 現実世界のアプリケーションは、AppComponentテンプレートにのみ現れる複数の使い捨てコンポーネント(スピナー、メッセージトースト、モーダルダイアログなど)を持つことができます。 彼らは他の所でimportされないので、その意味では共有されません。 しかし、彼らはあまりにも大きくて面倒なので、ルートフォルダには残っていません。
Avoid CoreModuleをAppModule以外でインポートするのは避けてください。
Why? CoreModuleを直接インポートする遅延ロードされたフィーチャモジュールは、独自のサービスコピーを作成し、望ましくない結果をもたらす可能性があります。
Why? 熱心に読み込まれたフィーチャモジュールは、すでにAppModuleのインジェクタ、したがってCoreModuleのサービスにアクセスできます。
Do AppModuleがインポートし、他の機能モジュールが使用できるようにするCoreModuleからすべてのシンボルをエクスポートします。
Why? CoreModuleは、他の多くのモジュールでよく使われるシングルトンサービスを利用できるようにするために存在します。
Why? あなたは、アプリケーション全体が1つのシングルトンインスタンスを使用することを望みます。各モジュールが独自のサービスのインスタンスを持つことは望ましくありません。しかし、CoreModuleがサービスを提供する場合、誤ってそれが起こる危険性があります。
多くのapp/rootクラスが他のモジュールに移動しているため、
AppModule
は少し小さくなります。AppModule
は将来のコンポーネントとプロバイダを他のモジュールに追加するので安定しています。AppModule
では作業を行うのではなくインポートされたモジュールに委譲します。
AppModule
は主なタスクに焦点を当てており、アプリ全体のオーケストレーションを行っています。
コアモジュールの再インポートを防止する
Style 04-12
ルートの AppModule
でのみ、 CoreModule
をインポートする必要があります。
Do CoreModule
の再インポートを防ぎ、ガードロジックを追加することで高速に動作します。
Why? CoreModuleの再インポートを防ぎます。
Why? シングルトンを意図した複数のインスタンスのアセットを作成することを防ぎます。
フォルダの遅延ロード
Style 04-13
アプリケーションの起動時ではなく、個別のアプリケーション機能またはワークフローが遅延ロードまたはロードされる場合があります。
Do 遅延ロードされた機能の内容を遅延ロードされたフォルダに入れてください。一般的な遅延読み込みフォルダには、ルーティングコンポーネント、その子コンポーネント、および関連するアセットとモジュールが含まれています。
Why? このフォルダを使用すると、機能コンテンツを簡単に識別して隔離することができます。
遅延読み込みフォルダを直接インポートしない
Style 04-14
Avoid 兄弟や親フォルダ内のモジュールを遅延ロード機能で直接インポートすることを避けてください。
Why? モジュールを直接インポートして使用すると、必要に応じてモジュールをロードすることが意図されているときにすぐにロードされます。
Components
コンポーネントセレクタ名
Style 05-02
Do コンポーネントの要素セレクタに名前を付けるには、ダッシュケースまたはケバブケースを使用します。
Why? 要素名をカスタム要素の仕様と一致させたままにします。
要素としてのコンポーネント
Style 05-03
Do 属性セレクタまたはクラスセレクタとは対照的に、コンポーネントセレクタに要素セレクタを与えるようにします。
Why? コンポーネントにはHTMLとオプションのAngularテンプレート構文を含むテンプレートがあります。 彼らはコンテンツを表示します。 開発者は、ネイティブのHTML要素やWebコンポーネントと同じように、コンポーネントをページに配置します。
Why? テンプレートのhtmlを見ることで、シンボルがコンポーネントであることを認識することは簡単です。
独自したファイルにテンプレートとスタイルを記述する
Style 05-04
3行以上のときに、テンプレートとスタイルを別々のファイルに抽出します。
Do テンプレートファイルに [component-name].component.html
という名前を付けます。ここでの[component-name]
はコンポーネント名です。
Do スタイルファイル [component-name].component.css
に名前を付けます。ここでの[component-name]
はコンポーネント名です。
Do 接頭辞が ./
のコンポーネント相対URLを指定します。
Why? 大規模なインラインテンプレートとスタイルは、コンポーネントの目的と実装を覆い隠し、可読性と保守性を低下させます。
Why? ほとんどのエディタでは、インラインテンプレートとスタイルを開発するときに構文ヒントとコードスニペットは使用できません。 Angular TypeScript Language Service(今後の予定)は、HTMLテンプレートをサポートするエディタのHTMLテンプレートの欠点を克服することを約束します。CSSスタイルには役立ちません。
Why? コンポーネントの相対URLは、コンポーネントファイルを移動するときに、ファイルが一緒に存在する限り変更する必要はありません。
Why? ./
接頭辞は、相対URLの標準構文です。Angularの現在のプレフィックスなしの能力には依存しません。
input と output のプロパティをデコレートする
Style 05-12
Do @Directive
および@Component
メタデータのinputs
およびoutputs
プロパティを使う代わりに、@Input()
および@Output()
クラスデコレータを使用してください。
Consider @Input()
または@Output()
を、装飾するプロパティと同じ行に配置することを検討してください。
Why? クラス内のどのプロパティがInput/Outputであるか、より簡単で読みやすくなります。
Why? @Input
または@Output
に関連付けられたプロパティまたはイベント名の名前を変更する必要がある場合は、一箇所で変更できます。
Why? ディレクティブに添付されているメタデータ宣言は、より短く、より読みやすくなります。
Why? デコレータを同じ行に配置すると、通常はコードが短くなり、プロパティを入力または出力として簡単に識別できます。それが明らかに読みやすくなったら上の行に置きます。
input/outputのエイリアスを避ける
Style 05-13
Avoid 重要な目的を果たす場合を除き、inputとoutputのエイリアスは避けてください。
Why? 同じプロパティ(2つのプライベート、1つのパブリック)の2つの名前は本質的に混乱します。
Why? ディレクティブ名が入力プロパティでもあり、ディレクティブ名がプロパティを記述していない場合は、別名を使用する必要があります。
メンバシーケンス
Style 05-14
Do プロパティ、メソッドの順で記述するようにしてください。
Do アルファベット順に並べたpublicメンバの後に、privateメンバを記述してください。
Why? メンバを一貫した順序で配置することで、読みやすいようになり、コンポーネントのどのメンバがどの目的に役立つかを即座に特定するのに役立ちます。
複雑なコンポーネントロジックをサービスに委譲する
Style 05-15
Do コンポーネントのロジックをビューに必要なロジックだけに制限します。他のすべてのロジックはサービスに委任されるべきです。
Do 再利用可能なロジックをサービスに移行し、コンポーネントをシンプルにしましょう。コンポーネントは意図した目的だけに集中させます。
Why? ロジックはサービス内に配置され、関数を介して公開されると、複数のコンポーネントによって再利用できる可能性があります。
Why? ユニットテストでは、サービス内のロジックをより簡単に分離することができますが、コンポーネント内の呼び出しロジックを簡単にモックすることができます。
Why? 依存関係を排除し、コンポーネントから実装の詳細を隠すことができます。
Why? コンポーネント内の無駄をそぎ落とし、スリムな状態を維持できます。
出力プロパティのプレフィックスを付けない
Style 05-16
Do 接頭辞on
のないイベント名にしてください。
Do 接頭辞on
の後にイベント名を付けたイベントハンドラメソッド名にしてください。
Why? これは、ボタンクリックなどの組み込みイベントと一致します。
Why? Angularでは、on-*
の代替構文を使用できます。イベント自体に接頭辞が付いていると、on-onEvent
バインディング構文になります。
プレゼンテーションロジックをコンポーネントクラスに配置する
Style 05-17
Do プレゼンテーションロジックをテンプレート内ではなくコンポーネントクラスに配置します。
Why? ロジックは2つの場所に分散するのではなく、1つの場所(コンポーネントクラス)にまとめるべきです。
Why? テンプレートの代わりにクラスのコンポーネントのプレゼンテーションロジックを保持することで、テストの容易性、保守性、および再利用性が向上します。
ディレクティブ
ディレクティブを使用して要素を拡張する
Style 06-01
Do テンプレートなしでプレゼンテーションロジックを使用するときに属性ディレクティブを使用してください。
Why? 属性ディレクティブには関連付けられたテンプレートはありません。
Why? エレメントには、複数の属性ディレクティブが適用されている場合があります。
HostListener/HostBinding デコレータ vs host メタデータ
Style 06-03
Consider @Directive
および@Component
デコレータのhost
プロパティに@HostListener
および@HostBinding
を優先させることを検討してください。
Do 一貫性のある選択をとるようにしてください。
Why? @HostBinding
に関連付けられたプロパティまたは@HostListener
に関連付けられたメソッドは、ディレクティブのクラス内の単一の場所でのみ変更できます。ホストのメタデータ・プロパティを使用する場合は、コントローラー内のプロパティ宣言と、ディレクティブに関連付けられたメタデータの両方を変更する必要があります。
あまり推奨されないホストメタデータの代替案と比較してください。
Why? ホストメタデータは覚えておくべき1つの用語であり、追加のES importsを必要としません。
サービス
サービスはシングルトン
Style 07-01
Do 同じインジェクタ内でシングルトンとしてサービスを使用してください。データと機能の共有に使用します。
Why? サービスは、feature領域またはアプリケーション全体でメソッドを共有するのに最適です。
Why? サービスは、ステートフルなメモリ内データを共有するのに最適です。
単一責任
Style 07-02
Do コンテキストによってカプセル化された、単一の責任でサービスを作成してください
Do サービスがその単独の目的を超え始めたときは、新しいサービスを作成してください。
Why? サービスに複数の責任がある場合は、テストするのが難しくなります。
Why? サービスに複数の責任がある場合、それをインジェクトするすべてのコンポーネントまたはサービスは、現在、それらのすべての重みを運びます。
サービスの提供
Stlye 07-03
Do サービスが共有されるべき最も親にあたるコンポーネントのAngular インジェクタに対してサービスをprovideします。
Why? Angularインジェクタは階層構造です。
Why? トップレベルのコンポーネントにサービスを提供する場合、そのインスタンスは共有され、そのトップレベルのコンポーネントのすべての子コンポーネントが利用できます。
Why? これは、サービスがメソッドや状態を共有しているときに理想的です。
Why? これは、2つの異なるコンポーネントがサービスの異なるインスタンスを必要とする場合には理想的ではありません。このシナリオでは、新規および別個のインスタンスを必要とするコンポーネントレベルでサービスを提供する方がよいでしょう。
@Injectable()
クラスデコレータの使用
Style 07-04
Do サービスの依存関係の型をトークンとして使用する場合は、@Inject
パラメータデコレータの代わりに@Injectable()
クラスデコレータを使用してください。
Why? Angular Dependency Injection(DI)機構は、サービスのコンストラクタパラメータの宣言された型に基づいて、サービス自身の依存関係を解決します。
Why? サービスが型トークンに関連付けられた依存関係のみを受け入れる場合、@Injectable()
構文は、個々のコンストラクタパラメータごとに@Inject()
を使用するよりもはるかに冗長です。
データサービス
サービスを通じてサーバとやりとりする
Style 08-01
Do データ操作を行い、サービスとデータとのやりとりを行うためにロジックをリファクタリングしてください。
Do データサービスは、XHR呼び出し、ローカルストレージ、メモリ内のスタッシュ作業、またはその他のデータ操作に関与します。
Why? コンポーネントの役割は、ビューの情報の表示と収集です。どのようにデータを取得するのか気にする必要はありません。誰がデータを要求するのか分かります。データサービスを分離することで、データサービスへのアクセス方法のロジックが移動し、コンポーネントのビューに対するシンプルさと集中性が向上します。
Why? これによりデータサービスを使用するコンポーネントをテストするときに、データコールのテスト(モックまたはリアル)が容易になります。
Why? ヘッダー、HTTPメソッド、キャッシュ、エラー処理、再試行ロジックなどのデータ管理の詳細は、コンポーネントや他のデータコンシューマとは関係ありません。
データサービスは、これらの詳細をカプセル化します。サービス内でこれらの詳細をサービスの呼び出し元に影響を与えずに進化させる方が簡単です。モックサービスの実装でサービス呼び出し元をテストする方が簡単です。
ライフサイクルフック
Lifecycleフックを使用して、Angularによって公開された重要なイベントを利用する。
ライフサイクルフックインタフェースの実装
Style 09-01
Do ライフサイクルフックインターフェイスを実装(implements)します。
Why? ライフサイクルインタフェースは、型付きメソッドのシグネチャを規定します。これらのシグネチャを使用して、スペルミスや文法ミスのフラグを立てます。
付録
Angularの便利なツールとヒントをご紹介します。
Codelyzer
Style A-01
Do このガイドに従ってcodelyzerを使用してください。
Consider 必要に応じてcodelyzerでルールを調整することを検討してください。
ファイルテンプレートとスニペット
Style A-02
Do ファイルテンプレートやスニペットを使用して、一貫したスタイルとパターンに従います。ここには、Web開発エディタやIDEのテンプレートやスニペットがあります。
Consider ここで紹介したスタイルとガイドラインに準拠したVisual Studio Code用のスニペットを使うことを検討してください。
Consider ここで紹介したスタイルとガイドラインに準拠したAtomのスニペットの使用を検討してください。
Consider ここで紹介したスタイルとガイドラインに準拠したSublime Textのスニペットの使用を検討してください。