Пример скромного объекта .NET - PullRequest
0 голосов
/ 02 апреля 2012

В настоящее время я пытаюсь реализовать шаблон проектирования скромного объекта.Единственный ресурс, который я могу найти по этому поводу, находится на веб-сайте тестирования xunit.К сожалению, я не совсем понимаю, несмотря на то, что я прочитал это несколько разМожет быть, есть другое название, по которому этот шаблон идет?

Вот то, что я имею до сих пор.

public interface IHumbleExchangeWebService
{
    GetItemResult BindToItems(IEnumerable<string> itemIds);
    SyncFolderItemsResult Sync();
    void Subscribe();
}

public class ExchangeWebServiceAdapter
{
    private readonly IHumbleExchangeWebService _humbleExchangeWebService;

    public ExchangeWebServiceAdapter(
        IHumbleExchangeWebService humbleExchangeWebService)
    {
        _humbleExchangeWebService = humbleExchangeWebService;

        Start();
    }

    private void Start()
    {
        SyncFolderItemsResult syncFolderItemsResults;
        while(true)
        {
            syncFolderItemsResults = _humbleExchangeWebService.Sync();

            if(syncFolderItemsResults != null)
                break;
        }

        ProcessSyncResults(syncFolderItemsResults);

        LastSyncDateTime = Time.Now;
        _humbleExchangeWebService.Subscribe();
    }

    private void ProcessSyncResults(SyncFolderItemsResult syncFolderItemsResults)
    {
        if (syncFolderItemsResults.Count <= 0) return;

        var missedItemIds = syncFolderItemsResults.ItemChange
            .ToList()
            .Select(x => x.ExchangeItem.ItemId);

        _humbleExchangeWebService.BindToItems(missedItemIds);
    }

    public DateTime LastSyncDateTime { get; private set; }
}

А что касается тестирования:

[TestFixture]
public class Tests
{
    private Mock<IHumbleExchangeWebService> _humbleExchangeWebServiceMock;

    [SetUp]
    public void SetUp()
    {
        _humbleExchangeWebServiceMock = new Mock<IHumbleExchangeWebService>();

    }

    [Test]
    public void OnInitialiseWillSyncBeforeSubscribing()
    {
        var callOrder = 0;
        _humbleExchangeWebServiceMock
            .Setup(x => x.Sync())
            .Returns(() => new SyncFolderItemsResult(0, false, String.Empty, GetExchangeItemChangeList()))
            .Callback(() => Assert.That(callOrder++, Is.EqualTo(0)));
        _humbleExchangeWebServiceMock
            .Setup(x => x.Subscribe())
            .Callback(() => Assert.That(callOrder++, Is.EqualTo(1)));

        var service = GetConstructedService();

        _humbleExchangeWebServiceMock.Verify(x => x.Sync(), Times.Once());
        _humbleExchangeWebServiceMock.Verify(x => x.Subscribe(), Times.Once());
    }

    [Test]
    public void WhenSyncingIsCompleteWillProcessMissingItem()
    {
        _humbleExchangeWebServiceMock
            .Setup(x => x.Sync())
            .Returns(new SyncFolderItemsResult(1, false, It.IsAny<string>(), GetExchangeItemChangeList()));

        var service = GetConstructedService();

        _humbleExchangeWebServiceMock.Verify(x => x.BindToItems(It.IsAny<IEnumerable<string>>()));
    }

    [Test]
    public void BindingItemsWillProcess()
    {
        _humbleExchangeWebServiceMock
            .Setup(x => x.Sync())
            .Returns(new SyncFolderItemsResult(1, false, It.IsAny<string>(), GetExchangeItemChangeList()));

        var service = GetConstructedService();

        _humbleExchangeWebServiceMock
            .Verify(x => x.BindToItems(new []{"AAA", "BBB", "CCC", "DDD"}), Times.Once());

        _humbleExchangeWebServiceMock.VerifyAll();
    }

    private ExchangeWebServiceAdapter GetConstructedService()
    {
        return new ExchangeWebServiceAdapter(_humbleExchangeWebServiceMock.Object);
    }

    private IEnumerable<ExchangeItemChange> GetExchangeItemChangeList()
    {
        yield return new ExchangeItemChange(ChangeType.Create, new ExchangeItem("AAA"));
        yield return new ExchangeItemChange(ChangeType.Create, new ExchangeItem("BBB"));
        yield return new ExchangeItemChange(ChangeType.Create, new ExchangeItem("CCC"));
        yield return new ExchangeItemChange(ChangeType.Create, new ExchangeItem("DDD"));
    }
}

По существу,Мне просто интересно, нахожусь ли я на правильном пути, чтобы сделать скромный объект немым.Я имею в виду, что это правильный способ извлечь все условия, которые я могу легко выполнить модульным тестом, в класс-оболочку (например, ExchangeWebServiceAdapter).

1 Ответ

4 голосов
/ 02 апреля 2012

Хорошее эмпирическое правило при попытке реализовать шаблон скромного объекта - посмотреть на объект, который вы только что создали, и спросить себя, как вы собираетесь проверить всю логику внутри него. Если у вас есть общее представление о том, что вы собираетесь делать в течение 10 секунд, и это не заставляет вас громко стонать, вы, вероятно, в порядке. Если это займет у вас больше времени или если вам будет трудно думать об этом, вы, вероятно, где-то допустили ошибку.

Что касается понимания скромного шаблона, вы можете думать о нем как о линии сборки автомобилей; вещь, которая заставляет работать эти массивные линии, это то, что все взаимозаменяемо. Только двигатели идут, обогреватели только нагреваются и т. Д. Самый простой способ держать это в уме - назвать свои классы такими, что они являются конкретным объектом, а затем избавиться от всего, что не подпадает под действие этого объекта. , В вашем конкретном примере вы назвали свой класс «адаптером». Хорошо, так что же адаптируется ОТ и К? Какие две несовместимые вещи он делает совместимым? Я полагаю, что часть вашего замешательства состоит в том, что ваш класс на данный момент неправильно назван или слишком широк. По мере того, как растет ваше понимание, ваш словарный запас будет расти, и вы можете обнаружить, что в этот момент это совершенно нормально. Если вы просто изучаете шаблон, это помешает вашему пониманию прыгнуть прямо на язык программирования; многие из этих слов, которые мы используем, имеют плохо определенные значения.

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

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

Надеюсь, это поможет; образец скромного объекта отличается и очень похож на идеал слабой связи, о котором люди будут постоянно говорить. Шаблон скромного объекта - это просто определенный предписанный способ достижения слабой связи с группой объектов, которые традиционно сопротивляются ему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...