場合、Demeterの法則(LoD)とTell Do n't Ask(TDA)は、SOLIDを達成するための特定のトリックです。 今日はデメテルの法則についてお話します。
誇張
この原則は、「ネストされたオブジェクトを取得/変更する方法」を決定するのに役立ちます-プロパティとメソッドを使用して「クラス」を定義できる言語に適用できます。
どこかから(たとえば、HTTPリクエストから)エンティティ「a」のIDを取得し、それをデータベースにたどり、エンティティ「a」からメソッド「メソッド」を呼び出してエンティティ「b」を取得/変更する必要がある場合に、状況がよく発生します。
だからウィキペディアは言う:
ʻabMethod() `コードはDemeterの法則に違反しており、ʻa.Method()`コードは正しいです。
例
ユーザーにはコメントのある投稿があります。「最後の投稿コメント」を受け取りたい。
あなたはこれを提出することができます:
const posts = user.posts
const lastPostComments = posts[posts.length-1].comments
またはこのように:
const userLastPostComments = user.getPosts().getLast().getComments()
問題:コードはネストされたデータの階層全体を認識しており、この階層が変更/拡張された場合、このチェーンが呼び出された場所で、変更を加える必要があります(コードとテストをリファクタリングします)。
この問題を解決するには、LoDを適用します。
const userLastPostComments = user.getLastPostComments()
しかし、すでに「ユーザー」には次のように書いています。
class User {
// ...
getLastPostComments(): Comments {
return this.posts.getLastComments()
}
// ...
}
コメントを追加した同じ話。から来ました:
const newComment = new Comment(req.body.postid, req.body.content)
user.getPosts().addComment(newComment)
または、診断を誇示したい場合:
const newComment = new Comment(req.body.postid, req.body.content)
const posts = user.posts
posts[posts.length-1].comments.push(newComment)
これをこれに変える:
const posts = user.addCommentToPost(req.body.postid, req.body.content)
そして `ユーザー`のために:
class User {
// ...
addCommentToPost(postId: string, content: string): void {
// The cleanest
const post = this.posts.getById(postId)
return post.addComment(content)
}
// ...
}
明確化: ` newComment`は` user`または ` post`の外部で作成できます。これはすべて、アプリケーションのロジックの配置方法によって異なりますが、エンティティの所有者(この場合は` post`)に近いほど良いです。
それは何をするためのものか?
私たちは、実装の詳細を隠し、これまでの変更/階層拡張が存在する場合(例えば、位置だけでなく、うその`プロパティになります投稿「)だけmethod`のリファクタリングする必要がありgetLastPostComments ` / ` addCommentToPost `と書き換えユニットテストにのみ、この方法を。
短所は何ですか
余分なものがたくさん コード。
小さなプロジェクトでは、ほとんどのメソッドは単なる ` getter` /` setter`になります。
いつ使用するか
(1)LoDは、深い/複雑な/マージされた接続を持つモデル、エンティティ、集合体、またはクラスに適しています。
(2)コードには、「最後の投稿のコメントを取得する」という概念が必要です。投稿は1番目のプロパティではなく、2つ以上のプロパティにあるため、確かに、 ` getLastPostComments`メソッドを作成し、いくつかのプロパティを異なるプロパティにマージする必要があります。投稿。
(3)データの変換(変更、作成、削除)に関しては、この原則をできるだけ頻繁に使用するようにしています。そして、データの取得に関してはそれほど頻繁ではありません。
(4)常識に基づく。
ライフハック
多くの人がプロキシメソッドの数について心配し始めたので、ここに簡略化
を示します。無限の数のプロキシメソッドを作成しないために、LoDをトップレベルクラス(この場合は「User」)で使用でき、実装内ではすでに法律に違反しています。例えば:
const userLastPostComments = user.getLastPostComments()
class User {
// ...
getLastPostComments(): Comments {
// LoD, Post
const lastPost = this.posts[this.posts.length-1]
return lastPost.comments
}
// ...
}
時間が経つにつれて、 `post`が大きくなると、それをメソッド` getLast() ʻまたは `getLastComments()ʻにすることが可能になり、これは多くのリファクタリングを必要としません。
これに必要なもの
適切なエンティティ依存関係ツリー/階層がある場合、LoDはうまく機能します。
何を読むか
(1)https://qna.habr.com/q/44822
必ずすべてのコメントとコメントのコメントを読んでください(コメントの前にVyacheslav GolovanovSLY_G)、正しい例と間違った例の両方があることを思い出してください (
2)https://ru.wikipedia.org/wiki/Zakon_Demeter
(3)記事
PS
私はいくつかの詳細/例を台無しにするか、それが十分に明確ではないことを説明することができたので、あなたが気づいたコメントに書き留めてください、私は変更を加えます。すべて良い。
PPS
読むコメント行をそれで、我々隠れ家 この記事では、不完全に照らされたケースをより詳細に分析します