海賊コードと同様に、SRPはルールというよりもガイドラインであり、特に明確な言葉ではありません。ほとんどの開発者は、Martin Fowler(リファクタリング)とRobert Martin(Clean Code)の再定義を受け入れており、クラスには(1つの責任ではなく)変更する理由が1つだけであるべきだと示唆しています。
それは良い、堅実な(しゃれを許さない)ガイドラインですが、それを無視するのと同じくらい、それに固執するのはほとんど危険です。
あなたがタグにポストを追加することができる場合と、その逆、あなたはシングル責任の原則を破っていません。両方とも、そのオブジェクトの構造が変更された場合、変更する理由は1つしかありません。どちらか一方の構造を変更しても、もう一方に追加される方法は変更されないため、新しい「責任」を追加することはありません。
最終的な決定は、フロントエンドで必要な機能によって実際に決定される必要があります。ある時点でタグを投稿に追加する必要がある可能性が高いので、次のようにします。
// C-style-language pseudo-code
class Post {
string _title;
string _content;
Date _date;
List<Tag> _tags;
Post(string title, string content) {
_title = title;
_content = content;
_date = Now;
_tags = new List<Tag>();
}
Tag[] getTags() {
return _tags.toArray();
}
void addTag(Tag tag) {
if (_tags.contains(tag)) {
throw "Cannot add tag twice";
}
_tags.Add(tag);
tag.referencePost(this);
}
// more stuff here, obviously
}
class Tag {
string _name;
List<Post> _posts;
Tag(string name) {
_name = name;
}
Post[] getPosts() {
return _posts.toArray();
}
void referencePost(Post post) {
if (!post.getTags().contains(this) || _posts.contains(post)) {
throw "Only reference a post by calling Post.addTag()";
}
_posts.Add(post);
}
// more stuff here too
}
後で、タグにも投稿を追加する必要がある場合は、addPostメソッドをTagクラスに追加し、referenceTagメソッドをPostクラスに追加するだけです。明らかに、addPostからaddTagを、addTagからaddPostを呼び出して誤ってスタックオーバーフローを引き起こさないように、それらに異なる名前を付けました。