отделение от будущих API-интерфейсов - впервые обнаружение необходимости внедрения зависимостей - PullRequest
1 голос
/ 23 февраля 2012

У меня наивный вопрос о шаблонах проектирования ООП.Это чрезмерная архитектура, но мне нужна рекомендация, а не суждение.Предположим, у вас есть иерархия классов, продиктованная «бизнес-требованиями».Итак, у вас есть более глубокая версия Pizza : Freight, Flowers : Freight и TonOfBricks : Freight, и у вас есть IDispatchService<F> where F : Freight и IDeliveryService<F> where F : Freight.

Теперь предположим, что разные IDeliveryServiceРеализации хотят разную информацию о грузе.То, что они хотят , не соответствует вашей иерархии классов , и вы понятия не имеете, какую службу доставки (т.е. API) вы собираетесь использовать через месяц для какой посылки.Кроме того, у вас может быть достаточно информации, чтобы отправить одну пиццу через вакуумную трубку, но, возможно, не следующую.

Теперь вы поняли, что вы также можете нанять людей для доставки вашей пиццы на роликах, но вам нужноукажите центр массы каждого предмета, доставленного таким образом, иначе страховка вас убьет.Вы реализуете это как IDeliveryService<Pizza>?Вы также добавляете новый интерфейс IHasCenterOfMass и, возможно, реализуете его как IDeliveryService<IHasCenterOfMass>?Если так, то как диспетчеру это понравится?Вы добавляете отношение к вашей базе данных для центра масс?

Ответы [ 3 ]

3 голосов
/ 23 февраля 2012

Планируйте то, что, как вы знаете, будет далеко, что, если кроличья нора будет только создавать код, который вы никогда не будете использовать. Если вы знаете о 3 службах доставки, которые могут отлично реализовать IDeliveryService, то вы можете создать общий интерфейс, но вы можете обнаружить, что он может не соответствовать тому, что вам нужно в будущем.

1 голос
/ 23 февраля 2012

Предположим, у вас есть иерархия классов, продиктованная "бизнес-требованиями".Итак, у вас есть более глубокая версия Pizza: Freight, Flowers: Freight и TonOfBricks: Freight, и у вас есть IDispatchService, где F: Freight и IDeliveryService, где F: Freight

Stopправильно это.Это не правильно ООП.Пицца и цветы - это не груз.Это содержимое в грузе.Различие очень важно, так как оно генерирует более чистый код с единственной ответственностью.

Теперь предположим, что различные реализации IDeliveryService хотят разную информацию о грузе

Не проблема, покапоскольку каждая реализация IPizzaDeliveryService требует один и тот же вид информации.

общая процедура доставки будет выглядеть следующим образом:

foreach (var freight in queue)
{
    var service = GetServiceFor(freight.ContentType);
    service.Dispatch(freight);
}

Обновление

public interface IFreight
{
    IFreightContent Content{get;}
    Type ContentType { get { return Content.GetType() }}
    PostalAddress DeliveryAddress {get;}
}


public interface IFreightContent
{
}

// we don't just deliver the pizza, do we? ;)
public class PizzaBox : IFreightContent
{
}
1 голос
/ 23 февраля 2012

Хитрость заключается в том, чтобы не нарушать принцип подстановки, который гласит, что каждый производный должен быть изменяемым с другим производным, если они имеют один и тот же базовый класс / интерфейс.Поэтому я бы рекомендовал вашим службам принять экземпляр XXXServiceInformation, который содержит конкретную информацию для этого требуемого сервиса и знает, как потенциально прочитать его из источника.Пример:

interface IDeliveryService<F> where F : Freight
{
    void Deliver();
}

class RollerBladesDeliveryService<F> : IDeliveryService<F> where F: Freight
{
    public RollerBladesDeliveryService(RollerBladesDeliveryInformation<F> information){ ... }

    void Deliver() { ... }
}

class RollerBladesDeliveryInformation<F> where F: Freight
{
    public RollerBladesDeliveryInformation(F freight, double centerOfMass) { ... }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...