Неизменяемые модели объекта к модели домена


Я пытаюсь ввести неизменяемые типы в коде, и я пытаюсь определить хороший шаблон, который является интуитивно понятным для нашей команды. Я читал про эскимо шаблон и что казалось сложным. Я также видел много моделей застройщика. Но те, казалось, как Overkill, а также. В примере ниже я хотел бы сделать FlexSession объект неизменным, чтобы гарантировать, что это всегда в допустимом состоянии.

Неизменную часть я особенно пытаясь определить хорошего рисунка в контроллере ниже. Поскольку FlexSession является неизменным, я добавил создать функцию, которая будет клонировать объект FlexSession и при этом обновляет свойства. Я видел другие примеры использования строителями, чтобы построить новый объект, но я боролся, чтобы видеть, как это может работать для сравнения существу другая картина.

Моя базовая архитектура-это контроллер MVC называет хранилище для запроса объекта. Контроллер обновляет объекта и передает объект в хранилище, чтобы сохранить изменения.

В репозитории есть сервис, который беседует с в DynamoDB. Я рассматриваю поставив преобразования из объекта документа в объект домена. Где объект домена является неизменным.

Документ В DynamoDB

public class FlexSessionDocument
{
    public string SortKey { get; set; }

    public List<int> PriceTypes { get; set; }
}

Репозиторий

public class Repository
{
    private readonly Service service;

    public Repository(Service service)
    {
        this.service = service;
    }

    public FlexSession Get(string sessionKey, string packageId, string token)
    {
        var query = BuildQueryByKeys(sessionKey, packageId, token);

        var model = this.service.Get<FlexSessionDocument>(query);

        return new FlexSession(model);
    }

    public void Update(FlexSession session)
    {
        var sortKey = BuildKey(session);

        var model = new FlexSessionDocument();

        model.SortKey = sortKey;
        model.PriceTypes = session.PriceTypes.ToList();

        this.service.Put(model);
    }

    private Query BuildQueryByKeys(string sessionKey, string packageId, string token)
    {
        ...
    }

    private string BuildKey(FlexSession session)
    {
        return session.SessionKey + "|" + session.PackageId + "|" + session.Token;
    }
}

Контроллер

public class Controller
{
    private readonly Repository repository;

    public Controller(Repository repository)
    {
        this.repository = repository;
    }

    public ActionResult Put(string sessionKey, string packageId, string token, int[] priceTypes)
    {
        var flexSession = this.repository.Get(sessionKey, packageId, token);

        var newFlexSession = flexSession.Create(priceTypes);

        this.repository.Update(newFlexSession);

        return Ok();
    }
}

Модель Домен

public class FlexSession
{
    public FlexSession(FlexSessionDocument document)
    {
        var parts = ParseSortKey(document.SortKey);

        SessionKey = parts.Item1;
        PackageId = int.Parse(parts.Item2);
        Token = parts.Item3;

        PriceTypes = document.PriceTypes == null ? ImmutableList.Create<int>() : ImmutableList.Create(document.PriceTypes.ToArray());
    }

    private FlexSession(string sessionKey, int packageId, string token, ImmutableList<int> priceTypes)
    {
        SessionKey = sessionKey;
        PackageId = packageId;
        Token = token;
        PriceTypes = priceTypes;
    }

    public string SessionKey { get; }

    public int PackageId { get; }

    public string Token { get; }

    public ImmutableList<int> PriceTypes { get; }

    public FlexSession Create(int[] priceTypes)
    {
        if (priceTypes.Length > 100)
        {
            throw new Exception("Invalid price type quanity");
        }

        var result = new FlexSession(SessionKey, PackageId, Token, ImmutableList.Create(priceTypes));

        return result;
    }

    private Tuple<string, string, string> ParseSortKey(string sortKey)
    {
        if (string.IsNullOrWhiteSpace(sortKey))
        {
            throw new Exception($"Invalid flex session sort key value: {sortKey}");
        }

        var keyparts = sortKey.Split('|');

        if (keyparts.Length != 3)
        {
            throw new Exception($"Failed to split the flex session sort key. Value: {sortKey}");
        }

        if (string.IsNullOrWhiteSpace(keyparts[0]))
        {
            throw new Exception($"Invalid flex session sort key, tessitura session key was missing. Value: {sortKey}");
        }

        var sessionKey = keyparts[0];

        if (string.IsNullOrWhiteSpace(keyparts[1]))
        {
            throw new Exception($"Invalid flex session sort key, package id was missing. Value: {sortKey}");
        }

        var packageId = keyparts[1];

        if (string.IsNullOrWhiteSpace(keyparts[2]))
        {
            throw new Exception($"Invalid flex session sort key, flex token was missing. Value: {sortKey}");
        }

        var token = keyparts[2];

        return Tuple.Create(sessionKey, packageId, token);
    }
}

Я видел ImmutableList "добавить" функцию, которая будет возвращать новый список с новыми данными. Вместо "создать" будет функция под названием "Обновление" будет более уместным.



195
1
задан 11 апреля 2018 в 02:04 Источник Поделиться
Комментарии
1 ответ

Несколько советов в коде. Используйте внедрение зависимостей для лучшего тест-способность


  1. В Контроллер

    public class Controller
    {
    private readonly IRepository _repository = null;
    public Controller(IRepository repository)
    {
    this._repository = repository;
    }
    }

  2. В Репозитории

    public class Repository 
    {
    private readonly IService _service;

    public Repository(IService service)
    {
    this.service = service;
    }


  3. В Flex сессии

    public class FlexSession
    {
    public FlexSession(IDocument flexSessionDocument)
    {
    ......
    }
    }

3
ответ дан 11 апреля 2018 в 05:04 Источник Поделиться