厳密に文書化されているのを見たことはありませんが、通常、「サービス」という言葉を使用して、関連するエンド ユーザー機能のサブセットを処理するクラスを示します。
たとえば、銀行口座システムがあるとします。次のサービスがあるとします。
public class AccountService
{
public boolean transfer(Account src, Account dest, double amt) // ....
public Account create(User user, double initAmt) // ...
public void close(Account account) // ...
}
したがって、ユーザーが実行できる「高レベル」の機能は、私のサービスにカプセル化されています。サービスはデータベースにアクセスし、ヘルパーをインスタンス化し、必要な計算を行います。しかし、私が言ったように、これは私が業界で過ごした時間から観察してきたことです.
SRP に関する限り: SRP は、実行したい機能ごとにまったく新しいクラスが必要だという意味ではありません。プロファイルを失敗としてマークするためのクラス、成功としてマークするためのクラス、およびプロファイルの名前を変更するための別のクラスは必要ありません。
SRP は、各クラスが「1 つのこと」を処理することを意味しますが、その「1 つのこと」は密接に関連する機能のセットになる可能性があります。考慮すべきもう 1 つの重要な OO 設計原則は、カプセル化です。つまり、クラスはクライアントに公開するものを最小限に抑え、他のユーザーが必要とするものだけを公開する必要があります。PaymentProfile の内部状態を管理する小さなクラスがたくさんある場合は、PaymentProfile のすべての詳細を公開していることになります。小さな例を挙げましょう:
PaymentProfile オブジェクトにブール値の isSuccess があるとします。次に、クラス RecurringPaymentProfileMarkAsFailedService は次のようになります。
public class RecurringPaymentProfileMarkAsFailedService {
public void mark(PaymentProfile profile)
{
profile.setSuccess(false);
}
}
クール - すべてうまくいっています。PaymentProfile に「成功」と「失敗」のステータスを設定できるだけでなく、更新中に一部の内部システムがクラッシュしたことを意味する「InternalError」をサポートする必要があるという機能リクエストを受け取りました。ブール値を使用できなくなったため、ブール値の isSuccess を、成功、失敗、エラーのいずれかになる列挙型に変更します。ここで、MarkAsFailedService をリファクタリングする必要があります。
これは単純なリファクタリングです。これは 1 つのクラスにすぎませんが、複雑なクラス ツリーの場合、これらのリファクタリングはシステム全体に反映される可能性があります。これは、PaymentProfile に関する実装の詳細を明らかにしすぎている兆候です。クラスはカプセル化する必要があるため、クラスの実装を変更してもクライアントにはほとんどまたはまったく影響がありません。