Как сервисы должны быть реализованы с помощью доменного дизайна? - PullRequest
1 голос
/ 20 июля 2011

Каков наилучший способ реализации классов обслуживания, если используется проектирование на основе домена?

Например, скажем, я хочу иметь AccountService, который можно использовать для перевода средств с одного счета на другой? Что из нижеперечисленного, если таковое имеется, было бы наилучшим способом реализации этого?

public class AccountService1
{
    private IAccountRepository _accountRepo;

    public AccountService1(IAccountRepository accountRepo)
    {
        _accountRepo = accountRepo;
    }

    public void TransferFunds(double ammount, int sourceAccountNumber, int targetAccountNumber)
    {
        //FUNDS TRANSFER CODE
    }
}

public class AccountService2
{
    public void TransferFunds(double ammount, Account sourceAccount, Account targetAccount)
    {
        //FUNDS TRANSFER CODE
    }
}


public static class AccountService3
{
    public static void TransferFunds(double amount, Account sourceAccount, Account targetAccount)
    {
        //FUNDS TRANSFER CODE
    }
}

public static class AccountService4
{
    public static void TransferFunds(double amount, int sourceAccountNumber, int targetAccountNumber, IAccountRepository repository)
    {
        //FUNDS TRANSFER CODE
    }
}

Ответы [ 3 ]

3 голосов
/ 20 июля 2011

Каждый ваш путь ведет к анемичному домену.

Есть ли какая-то причина, по которой он не может быть методом экземпляра в вашей учетной записи?

2 голосов
/ 21 июля 2011

Неясно, являются ли ваши примеры служб приложений или служб домена.Пример 1 - это то, как должна выглядеть служба приложения, а пример 2 - то, как может выглядеть служба домена.В совокупности это будет выглядеть примерно так:

public class AccountApplicationService
{
    private IAccountRepository _accountRepo;

    public AccountApplicationService(IAccountRepository accountRepo)
    {
        _accountRepo = accountRepo;
    }

    public void TransferFunds(double ammount, int sourceAccountNumber, int targetAccountNumber)
    {
        Account sourceAccount = _accountRepo.GetById(sourceAccountNumber);
        Account targetAccount = _accountRepo.GetById(targeteAccountNumber);

        IAccountDomainService accDomService = new AccountDomainService();

        accDomService.TransferFunds(ammount, sourceAccount, targetAccount);

        using(Transaction tran = _accountRepo.BeginTransaction()) //note: pseudo code.
        {
             _accountRepo.Save(sourceAccount);
             _accountRepo.Save(targetAccount);
             tran.Commit();
        }
    }
}
0 голосов
/ 28 июля 2011

Ваша первая реализация - лучший вариант.Однако вы должны также реализовать метод Transfer для самого класса Account, который также принимает сумму и целевой экземпляр Account.В этом случае роль службы заключается в загрузке экземпляров учетной записи с использованием репозитория, их сохранении, управлении единицами работы, а также предоставлении доступа к любым внешним службам, которые могут потребоваться.Роль метода Transfer в классе Account заключается в защите целостности данных внутри самого класса Account и обеспечении согласованности, исключений и т. Д.

class Account {

  public string State { get; private set; } 

  public decimal Total { get; private set; } 

  public void Transfer(decimal amount, Account dest) {
     if (amount > this.Total) throw Exception();

     if (this.State == "Closed") throw Exception();

     this.Total -= amount;
     dest.Total += amount;

  }
}

Таким образом, класс Account определяет, какие операции возможныуровень обслуживания - это то, что действует на уровне домена и, таким образом, связан со всеми операционными обязанностями.

...