Это архитектура слишком сложный или после лучшие практики?


Я работаю на C# в компанию, которая не использует лучшие практики на всех. Мы на .Net 3.5 С, но большая часть кода написана .Чистая 1.1 стиле (например, почти вся логика в коде страницы aspx, все используются нетипизированные наборы данных вместо того, чтобы возвращать объекты, делает безвозмездного пользования сессии и строки запроса для передачи данных, очень мало архитектурных моделей). Я потратил несколько лет изучения передового опыта читать блоги и смотреть видеоролики из верхних эшелонов .Net-разработчиков.

Я недавно была поставлена задача создания новой функции на нашем в-дом ERP-системы, которая записывает данные из XML в формат PDF для просмотра. Было высказано предположение, что нам может понадобиться различные типы PDF-файлов в будущем, поэтому система должна быть гибкой. Я воспользовался возможностью, чтобы применить надлежащий шаблоны проектирования и ДДД подход к коду, с идея в том, чтобы продемонстрировать "лучшего способа" делать вещи со своими сверстниками. Мой код был впоследствии отвергнут в "ревью кода" ведущий разработчик/менеджер по развитию как "слишком сложный" по сравнению с просто писать всю логику в один класс или в коде (что мой коллега сделал бы, если бы они дали проект). Мне удалось получить код, переданный в любом случае, так как они не хотят, чтобы я "тратить время" вернуться и изменить его (они считают рефакторинг пустая трата времени, которая не добавляет ценность для бизнеса), но это заставило меня задуматься, если код действительно слишком сложная; я, кажется, все лучшие практики, я (как мне кажется) все твердые принципы, я, используя правильные шаблоны проектирования и ООП программная инженерия методов.

Здесь является упрощенной версией классы (может или не может быть 100% компилируемый, как это урезанная версия; вы должны хотя вам идею):

// Repositories
public interface IRepository { }
public interface IXmlRepository : IRepository { 
    XmlDocument GetXml();
}

// Repositories.Impl
public abstract class BillingXmlRepository : IXmlRepository {
    protected long quoteID;

    public BillingXmlRepository(long quoteID) { 
        this.quoteID = quoteID;
    }

    public abstract XmlDocument GetXml();
}

public sealed class XmlInvoiceRepository : BillingXmlRepository { 
    public XmlInvoiceRepository(long quoteID) : base(quoteID) { }
    public override XmlDocument GetXml() { 
        // XML retrival here...
    }
}

// DataAggregation
pubilc interface IAggregatableData<T> { 
    T GetData();
}

public abstract class DataAggregator<T> : IAggregatableData<T> { 
    public abstract T GetData();
    protected abstract ICollection<IRepository> GetAllRequiredRepositories();
}

public abstract class XmlDataAggregator : DataAggregator<XmlDocument> { 
    public override XmlDocument GetData() { 
        XmlDocument root = new XmlDocument();
        foreach (IRepository repository in this.GetAllRequiredRepositories()) { 
            XmlDocument xml = (repository as IXmlRepository).GetXml();
            XmlDocumentFragment fragment = root.CreateDocumentFragment();
            fragment.InnerXml = xml.InnerXml;
            root.DocumentElement.AppendChild(fragment);
        }
        return root;
    }
}

public sealed class BillingDataAggregator : XmlDataAggregator {
    private long quoteID;

    public BillingDataAggregator(long quoteID) { 
        this.quoteID = quoteID;
    }

    protected override void ICollection<IRepository> GetAllRequiredRepositories() { 
        return new List<IRepository> { 
            new XmlBillingRepository(this.quoteID);
        }
    }
}

// Mappers to map raw XML to classes
public interface IMappable<T, K> { 
    T Map(K rawData);
}

public interface IXmlMappable<T> : IMappable<T, XmlDocument> { 
}

public sealed class BillingXmlMapper : IXmlMappable<BillingInfo> { 
    public BillingInfo Map(XmlDocument rawData) { 
        // LINQ code to traverse the XML and map it into a BillingInfo DTO
    }
}

// Entities
public sealed class BillingInfo { 
    // simple properties
}

// Consumer example
XmlDataAggregator aggregator = new BillingDataAggregator(1234);
var xml = aggregator.GetData();
var mapper = new BillingXmlMapper();
BillingInfo info = mapper.Map(xml);

Я на правильном пути так далеко, как следующий лучший способ писать модульный код? Я не могу заставить себя игнорировать передовой практики и написать весь код в файлы кода или тому подобное.



Комментарии
4 ответа

Я думаю, что вы не усложняя его слишком много.

Первый вопрос, который всплывает в моей голове, "Почему столько наследства?" Почему наследовать IXmlRepository от IRepository? Какой смысл?

Я также не согласен с вызовом, что "хранилище" - я думаю, что это один из самых заезженных терминов в архитектуре на данный момент. Читать Эванса ДДД или на сайте Фаулера и скажите мне, если вы действительно думаете, что класс попадает под определение "хранилища". И тогда меня убедить, что никто не будет путаться между этой и какой-либо другой тип "хранилище", которое существует в вашем проекте. (просто из моего опыта здесь)

Также в отношении наследства, почему абстрактный DataAggregator? Я понимаю, что вы срубили из фактический код, но из того, что я вижу здесь, это опять же совершенно бессмысленно строить.

Еще одно: у вас есть цепочка наследования XmlInvoiceRepository -> BillingRepository -> IXmlRepository -> IRepository. Да? Почему на земле XmlInvoiceRepository унаследовал от BillingRepository? Надеюсь, не только потому, что счета-фактуры являются частью биллинга в чьем-то концептуальной модели.

Есть какая-то причина XmlInvoiceRepository -> IXmlRepository не хватит?

Кроме того, вы бросали много запечатанытам. Почему? Есть четкие причины для этого выбора, или это просто для хорошей мерой? Если последнее, то избавиться от него. Быть максимально простой, но не проще.

Также, вам действительно нужны два интерфейса для представления функции, которые можно сопоставить с XmlDocument для универсального типа? Сколько мест в том, что действительно привыкла. Тот же вопрос с DataAggregator, сколько разных мест в том, что действительно привыкла.

Ваш пример об использовании права на. Вот что вы должны стремиться. Коротко, сжато, ясно, в точку. Операции происходят на одном уровне абстракции.

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

5
ответ дан 5 мая 2011 в 07:05 Источник Поделиться

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

4
ответ дан 14 мая 2011 в 07:05 Источник Поделиться

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

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

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

3
ответ дан 5 мая 2011 в 03:05 Источник Поделиться

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

Вы можете использовать шаблоны проектирования ООП для этого, конечно, посмотреть на разделение касается и использования МОК, если вам нравится и шаблон стратегии для инкапсуляции некоторые алгоритмы, только не переусердствуйте и наносите слишком много шаблонов проектирования. :)

2
ответ дан 27 августа 2013 в 12:08 Источник Поделиться