Что должно иметь приоритет: YAGNI или Good Design?


76

В какой момент YAGNI должен иметь преимущество перед хорошими методами кодирования и наоборот? Я работаю над проектом на работе и хочу постепенно внедрить хорошие стандарты кода для моих коллег (в настоящее время их нет, и все просто взломано без всякой рифмы или причины), но после создания серии классов (мы не делайте TDD, или, к сожалению, никакого вида юнит-тестирования) Я сделал шаг назад и подумал, что это нарушает YAGNI, потому что я точно знаю, что нам не нужно расширять некоторые из этих классов.

Вот конкретный пример того, что я имею в виду: у меня есть слой доступа к данным, обертывающий набор хранимых процедур, который использует элементарный шаблон в стиле репозитория с основными функциями CRUD. Поскольку существует несколько методов, которые нужны всем моим классам репозитория, я создал общий интерфейс для своих репозиториев, который называется IRepository. Однако затем я создал «маркерный» интерфейс (т. Е. Интерфейс, который не добавляет никакой новой функциональности) для каждого типа репозитория (например ICustomerRepository), и конкретный класс реализует это. Я сделал то же самое с реализацией Factory для построения бизнес-объектов из DataReaders / DataSets, возвращаемых хранимой процедурой; подпись моего класса репозитория имеет тенденцию выглядеть примерно так:

public class CustomerRepository : ICustomerRepository
{
    ICustomerFactory factory = null;

    public CustomerRepository() : this(new CustomerFactory() { }

    public CustomerRepository(ICustomerFactory factory) {
        this.factory = factory;
    }      

    public Customer Find(int customerID)
    {
        // data access stuff here
        return factory.Build(ds.Tables[0].Rows[0]);
    }
}

Меня беспокоит то, что я нарушаю YAGNI, потому что я знаю с 99% уверенностью, что никогда не будет причины давать что-то, кроме бетона, CustomerFactoryэтому хранилищу; так как у нас нет модульных тестов, мне не нужны MockCustomerFactoryили подобные вещи, а наличие такого большого количества интерфейсов может запутать моих коллег. С другой стороны, использование конкретной реализации фабрики кажется дизайнерским запахом.

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


17
Вы говорите: «поскольку у нас нет модульных тестов, мне не нужен MockX», что, естественно, приводит к «мне не нужен IX, мне нужен только X». Я переверну это, тот факт, что у вас нет модульных тестов, подчеркивает тот факт, что вам нужны IX и MockX, потому что эти вещи помогут вам пройти модульные тесты. Не принимайте реальность отсутствия тестов, рассматривайте это как временную проблему, которая будет исправлена ​​в течение (вероятно, хорошего, длительного) времени.
Энтони Пеграм,

10
Даже если гуглить это несущественно, кто-то должен упомянуть, что YAGNI означает «Тебе это не понадобится»
thedaian

1
Я бы подумал, что если бы вы писали новые классы, подобные этому, вы бы хотели добавить несколько юнит-тестов. Даже если ваши коллеги не будут ими управлять. По крайней мере, позже вы можете сказать: «Смотри! Мои юнит-тесты поймали его, когда ты сломал мой код! В этом случае, сделать его смешным может быть полезным здесь. (Хотя я бы предпочел, чтобы объект мог быть смоделирован без определения интерфейса)
Уинстон Эверт

Разве модульные тесты не заставят меня создать (или использовать) фиктивный фреймворк, чтобы я не использовал живые хранимые процедуры? Это главная причина, по которой я склонен не добавлять тесты - у каждого из нас есть локальная копия рабочей базы данных, с которой мы тестируем и пишем код.
Уэйн Молина

3
@Anthony И всегда ли насмешка оправдывает дополнительные сложности, которые это влечет за собой? Насмешка - прекрасный инструмент, но его полезность также должна быть взвешена с затратами, и иногда весы склоняются в другую сторону из-за чрезмерной косвенности. Конечно, есть инструменты, которые помогут с дополнительной сложностью, но они не уберут сложность. Кажется, существует растущая тенденция рассматривать «тестирование любой ценой» как данность. Я считаю, что это неверно.
Конрад Рудольф

Ответы:


75

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

YAGNI.

Я мог бы пожертвовать немного хорошего дизайна

Ложное предположение.

и базовый интерфейс, а затем один бетон,

Это не «жертва». То есть хороший дизайн.


72
Совершенство достигается не тогда, когда нечего добавить, а когда нечего отнять. Антуан Де Сент-Экзюпери
Ньютопия

5
@Newtopian: у людей смешанные чувства по поводу последних продуктов Apple. :)
Рой Тинкер

14
У меня огромная проблема с такого рода ответами. Является ли «X правдой, потому что Y говорит это, а Y хорошо поддерживается сообществом» обоснованным аргументом? Если бы кто-то в реальной жизни выступил против ЯГНИ, вы бы показали ему этот ответ в качестве аргумента?
vemv

2
@vemv. Здесь никто не разглагольствует против ЯГНИ. Все, что сказал С.Лотт, заключалось в том, что предполагаемое противоречие между двумя достойными целями ОП является ошибкой. Кстати, вы знаете какого-нибудь активного разработчика в современном мире программного обеспечения, который выступал бы против YAGNI? Если вы работаете над реальными проектами, вы знаете, что требования постоянно меняются и что пользователи и менеджеры обычно не знают, что они делают или не хотят, пока вы не поставите их перед ними. Реализация необходимого - МНОГО работы - зачем тратить время, энергию и тратить деньги (или рисковать работой), написав код, который пытается предсказать будущее?
вектор

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

74

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

Самые простые проекты - самые легкие для развития. Ничто так не убивает ремонтопригодность, как бесполезные, сверхпрочные слои абстракции.


8
Я нахожу «избегание кода YAGNI» крайне неоднозначным. Это может означать код, который вам не понадобится, или код, соответствующий принципу YAGNI . (Сравни 'ПОЦЕЛУЙ код')
sehe

2
@sehe: Это совсем не двусмысленно (хотя «придерживается принципа YAGNI» прямо противоречит самому себе), если вы это изложите: что может означать «код, который вам не нужен», но код, который тебе не понадобится?
Майкл Боргвардт

1
Я собираюсь напечатать этот ответ крупным шрифтом и повесить его так, чтобы его могли прочитать все астронавты архитектуры. +1!
kirk.burleson

1
+1. Я до сих пор помню свой первый корпоративный проект, который мне дали поддержать и добавить некоторые новые функции. Первое , что я сделал , было удалить 32000 строк бесполезного кода из программы 40 000 линии без потери какой - либо функциональности. Первоначальный программист был уволен вскоре после этого.
Э.Дж. Бреннан

4
@vemv: читать «бесполезно» как «не используется в настоящее время, кроме как тривиально», то есть случай YAGNI. И «чрезмерно развитый» более специфичен, чем «плохой». В частности, это означает «сложность, вызванную теоретическими концепциями или воображаемыми возможными требованиями, а не конкретными текущими требованиями».
Майкл Боргвардт

62

YAGNI и SOLID (или любая другая методология проектирования) не являются взаимоисключающими. Однако они являются приполярными противоположностями. Вы не должны придерживаться 100% либо, но будут некоторые компромиссы; чем больше вы смотрите на шаблон с высокой абстракцией, используемый одним классом в одном месте, говорите YAGNI и упрощаете его, тем меньше становится твёрдым дизайн. Обратное также может быть правдой; много раз в разработке, дизайн реализован ТВЕРДЫМ «по вере»; Вы не видите, как вам это понадобится, но у вас есть предчувствие. Это может быть правдой (и все больше и больше правдоподобно, если вы приобретете больше опыта), но это также может привести к тому, что у вас будет столько же технического долга, сколько и пощечины «сделай это легко»; вместо DIL-кода "спагетти-код" вы можете получить "код лазаньи", Имея так много слоев, что простое добавление метода или нового поля данных превращается в многодневный процесс перехода через служебные прокси-серверы и слабосвязанные зависимости только с одной реализацией. Или вы можете получить «код равиоли», который состоит из таких маленьких кусочков, что при перемещении вверх, вниз, влево или вправо в архитектуре вы пройдете через 50 методов по 3 строки в каждом.

Я сказал это в других ответах, но вот оно: На первом проходе заставь это работать. На втором проходе сделайте это элегантно. На третьем проходе сделайте его твердым.

Разбивая это:

Когда вы впервые пишете строку кода, он просто должен работать. На данный момент, насколько вы знаете, это одноразовый. Таким образом, вы не получаете никаких стилевых баллов за построение «башни из слоновой кости», чтобы добавить 2 и 2. Делайте то, что вам нужно, и предполагайте, что вы никогда больше этого не увидите.

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

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

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


Я второй удивительный.
Филипп Дупанович

2
Да. Когда я использовал дизайн для повторного использования / расширения заранее, я обнаружил, что когда я хотел бы повторно использовать или расширять его, это было бы иначе, чем я ожидал. Прогнозировать сложно, особенно в отношении будущего. Поэтому я поддерживаю ваше правило 3-х ударов - к тому времени у вас есть разумное представление о том, как оно будет использоваться / расширяться. NB. Исключение составляют случаи, когда вы уже знаете, как это будет (например, из предыдущих проектов, в предметной области или уже указаны).
13

На четвертом проходе сделайте его УДИВИТЕЛЬНЫМ.
Ричард Нил Илаган

@KeithS: Джон Кармак, похоже, сделал нечто похожее: «исходный код Quake II ... объединил Quake 1, Quake World и QuakeGL в одну прекрасную архитектуру кода». fabiensanglard.net/quake2/index.php
13

+1 Думаю, я назову ваше правило: «Практический рефакторинг» :)
Songo

31

Вместо любого из них я предпочитаю WTSTWCDTUAWCROT?

(Что самое простое, что мы можем сделать, это полезно, и мы можем выпустить в четверг?)

В моем списке вещей есть простые сокращения, но они не являются приоритетными.


8
Эта аббревиатура нарушает принцип
ЯГНИ

2
Я использовал именно те буквы, которые мне были нужны - не больше и не меньше. Таким образом, я вроде как Моцарт. Ага. Я Моцарт аббревиатур.
Майк Шеррилл 'Cat Recall'

4
Я никогда не знал, что Моцарт был ужасен в создании сокращений. Я узнаю что-то новое каждый день на сайте SE. : P
Кэмерон МакФарланд,

3
@Mike Sherrill 'CatRecall': Может быть, стоит расширить это до WTSTWCDTUWCROTAWBOF = "Что самое простое, что мы можем сделать, это полезно, мы можем выпустить в четверг и не сломаем в пятницу?" ;-)
Джорджио

1
@ Stargazer712 нет :) это нарушает ПОЛА.
v.oddou

25

YAGNI и хороший дизайн не противоречат друг другу. YAGNI о (не) поддержке будущих потребностей. Хороший дизайн - это прозрачность того, что ваша программа делает прямо сейчас, и как она это делает.

Сделает ли введение фабрики ваш существующий код проще? Если нет, не добавляйте его. Если это так, например, когда вы добавляете тесты (что вы должны делать!), Добавьте его.

YAGNI - это не сложность для поддержки будущих функций.
Хороший дизайн - это устранение сложности при поддержке всех текущих функций.


15

Они не в конфликте, ваши цели неверны.

Что вы пытаетесь достичь?

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

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

Вот как выглядит ваша проблема.

введите описание изображения здесь (кому интересно, это называется испаряющимися облаками )

Итак, что движет этим?

  1. Вы не знаете, что вам не нужно
  2. Вы не хотите тратить время и раздувать свой код

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

Я работаю над проектом на работе и хочу постепенно внедрить хорошие стандарты кода для моих коллег (в настоящее время их нет, и все просто взломано без всякой рифмы или причины) [...] Я сделал шаг назад и думал, что это нарушает YAGNI, потому что я точно знаю, что нам не нужно расширять некоторые из этих классов.

Давайте перефразируем все это

  • Нет стандартов кода
  • Планирование проекта не ведется
  • Повсюду ковбои делают свое дело (а вы пытаетесь сыграть в шерифа на диком диком западе), хм-ха.

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

Вам не нужен компромисс, вам нужен кто-то, кто руководит командой, кто компетентен и имеет видение всего проекта. Вам нужен кто-то, кто может спланировать то, что вам нужно, вместо того, чтобы каждый из вас бросал вещи, которые вам НЕ нужны, потому что вы так неуверенны в будущем, потому что ... почему? Я скажу вам почему, потому что ни у кого нет ни одного чертового плана среди всех вас. Вы пытаетесь ввести стандарты кода, чтобы решить совершенно отдельную проблему. Ваша основная проблема, которую вам нужно решить, - это четкая дорожная карта и проект. Получив это, вы можете сказать: «Стандарты кода помогают нам более эффективно достигать этой цели как команда», что является абсолютной истиной, но выходит за рамки этого вопроса.

Найдите менеджера проекта / команды, который может сделать это. Если у вас есть, вам нужно попросить у них карту и объяснить проблему YAGNI, которую представляет отсутствие карты. Если они крайне некомпетентны, напишите план самостоятельно и скажите: «Вот мой доклад для вас о том, что нам нужно, просмотрите его и сообщите нам ваше решение».


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

Это хорошо, это будет немного медленнее, но тогда вам нужно поговорить с ними об их заботах. Объясните, что эта проблема с YAGNI / Бесполезным кодом тратит время, предложите план, дайте ему план, объясните, как он будет работать быстрее. Когда он вступит в игру, войдите с проблемами, которые плохие стандарты имеют к скорости разработки, предложите лучшие. Они хотят, чтобы проект был завершен, они просто не знают, как управлять этим, вам нужно либо заменить его, либо присмотреть за ним ... или бросить.
Инкогнито,

Хм ... Я думаю, что главной целью было бы: "Вы хотите получить хороший, ценный продукт"?
sehe

@ это не его решение: с.
Инкогнито,

3
Отличный ответ. Ему грозит тяжелая битва. Сделать это будет сложно, если не будет никакого участия руководства. И вы правы, что вопрос преждевременен и не решает реальную проблему.
Сет Спирман

10

Учитывая ваш код , который будет расширено с модульными тестами никогда не будет подпадать под YAGNI, потому что вы будете в ней нуждаются. Однако я не уверен, что ваши изменения в дизайне интерфейса с одной реализацией фактически повышают тестируемость кода, потому что CustomerFactory уже наследуется от интерфейса и в любом случае может быть заменен на MockCustomerFactory в любое время.


1
+1 за полезный комментарий о актуальной проблеме, а не только о космическом сражении и / или любви между Good Design и YAGNI.
PSR

10

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

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

YAGNI был задуман для того, чтобы помочь разработчикам избежать какой-то особой переделки: то, что происходит от создания неправильной вещи. Это достигается за счет того, что мы избегаем принимать ошибочные решения слишком рано, основываясь на предположениях или прогнозах относительно того, что, по нашему мнению, изменится или потребуется в будущем. Коллективный опыт говорит нам, что когда мы делаем это, мы обычно ошибаемся. Например, YAGNI бы сказать вам , чтобы не создавать интерфейс с целью повторного использования , если вы не знаете сейчас , что вам нужно несколько исполнителей. Точно так же YAGNI бы сказать , не создают «ScreenManager» для управления единой формы в приложении , если вы не знаете , прямо сейчас , что вы будете иметь более одного экрана.

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

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

Есть 5 твердых принципов, чтобы смотреть на. S является единственной ответственностью. Это ничего не говорит об интерфейсе, но может сказать что-то о ваших конкретных классах. Можно утверждать, что обработку самого доступа к данным лучше всего возложить на один или несколько других классов, в то время как ответственность репозиториев заключается в переводе из неявного контекста (CustomerRepository неявно является хранилищем для сущностей Customer) в явные обращения к Обобщенный API доступа к данным с указанием типа объекта Customer.

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

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

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

D - инъекция зависимостей. Здесь мы возвращаемся к той же точке, что и S. Если вы разделили использование API доступа к данным на отдельный объект, этот принцип говорит, что вместо того, чтобы просто обновлять экземпляр этого объекта, вы должны передать его при создании хранилище. Это облегчает управление временем жизни компонента доступа к данным, открывая возможность делиться ссылками на него между вашими репозиториями, не прибегая к созданию единого пакета.

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

Таким образом, после всего этого мы находим, что YAGNI и SOLID действительно предоставляют один общий надежный совет, имеющий непосредственное отношение: вероятно, нет необходимости создавать общий универсальный интерфейс хранилища.

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


Я думаю, что большинство обсуждений на этой странице не учитывают двух больших претендентов: «слабая связь» и «высокая сплоченность» GRASPrinciples. Более дорогие конструкторские решения вытекают из принципа «низкого сцепления». Например, когда «активировать» SRP + ISP + DIP для слабой связи. Пример: один класс -> 3 класса в шаблоне MVC. Или даже дороже: разбить на .dll / .so модули / сборки. Это очень дорого из-за последствий сборки, проектов, make-списков, сервера сборки, добавления файлов с исходными версиями ...
v.oddou

6

Кажется, вы верите, что «хороший дизайн» означает следование некоторой идеологии и формальному набору правил, которые всегда должны применяться, даже когда они бесполезны.

ИМО это плохой дизайн. YAGNI - это составляющая хорошего дизайна, никогда не противоречащая ему.


2

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

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


Ваши первая и третья ссылки идут в одно и то же место.
Дэвид Торнли

2

Некоторые люди утверждают, что имена интерфейсов не должны начинаться с I. Конкретно, одна из причин заключается в том, что вы фактически теряете зависимость от того, является ли данный тип классом или интерфейсом.

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

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

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

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

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


0

Вы создаете interfaceмногократные реализации в будущем. С таким же успехом вы можете иметь I<class>для каждого класса в вашей кодовой базе. Не.

Просто используйте один конкретный класс в соответствии с YAGNI. Если вы обнаружите, что вам нужен «фиктивный» объект для целей тестирования, превратите исходный класс в абстрактный класс с двумя реализациями, одна с исходным конкретным классом, а другая с фиктивной реализацией.

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

YAGNI говорит не писать код, прежде чем он будет написан.

Хороший дизайн говорит об использовании абстракции.

Вы можете иметь оба. Класс - это абстракция.


0

Почему маркер взаимодействует? Меня поражает, что он делает только пометки. С каким "тегом" для каждого типа фабрики, какой смысл?

Цель интерфейса состоит в том, чтобы дать классу «действия как» поведение, чтобы дать им, так сказать, «способность хранилища». Таким образом, если все ваши конкретные типы репозитория ведут себя как один и тот же IRepository (все они реализуют IRepository), то все они могут обрабатываться одинаково другим кодом - точно таким же кодом. На данный момент ваш дизайн является расширяемым. Добавление более конкретных типов репозитория, все они обрабатываются как универсальные IRepository (s) - тот же код обрабатывает все конкретные типы как «универсальные» репозитории.

Интерфейсы предназначены для управления вещами на основе общности. Но пользовательские интерфейсы маркеров а) не добавляют поведения. и б) заставить вас справиться с их уникальностью.

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

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


0

Можете ли вы прямо сейчас записать неопределенно разумный репозиторий ICustomer? Например, (действительно показательно, вероятно, плохой пример), в прошлом ваши клиенты всегда использовали PayPal? Или все в компании гудят в связи с Alibaba? Если это так, вы можете использовать более сложный дизайн сейчас и показаться дальновидным своим боссам. :-)

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.