Рядом со мной сидит коллега, который разработал такой интерфейс:
public interface IEventGetter {
public List<FooType> getFooList(String fooName, Date start, Date end)
throws Exception;
....
}
Проблема в том, что сейчас мы не используем этот «конечный» параметр где-либо в нашем коде, он просто есть, потому что нам, возможно, придется использовать его когда-нибудь в будущем.
Мы пытаемся убедить его, что плохая идея - помещать параметры в интерфейсы, которые сейчас бесполезны, но он продолжает настаивать на том, что придется проделать большую работу, если мы когда-нибудь реализуем использование даты окончания позже и потом придется адаптировать весь код.
Теперь мой вопрос: есть ли источники, которые занимаются темой «уважаемых» программистов, с которой мы можем связать его?
end
параметр к этому объекту и даже установить его по умолчанию, чтобы не нарушать кодnull
. Реализующие классы могут затем переопределять при необходимости.IQueryable
(может принимать только определенные выражения) кода вне DALОтветы:
Пригласите его узнать о ЯГНИ . Обоснование части страницы Википедии может быть особенно интересным здесь:
Другие возможные аргументы:
«80% стоимости срока службы программного обеспечения уходит на техническое обслуживание» . Написание кода как раз вовремя , снижает затраты на техническое обслуживание: один должен поддерживать меньше кода, и может сосредоточиться на коде на самом деле необходимо.
Исходный код пишется один раз, но читается десятки раз. Дополнительный аргумент, нигде не используемый, приведет к потере времени на понимание, почему существует аргумент, который не нужен. Учитывая, что это интерфейс с несколькими возможными реализациями, все усложняется.
Ожидается, что исходный код самодокументируется. Фактическая подпись вводит в заблуждение, поскольку читатель может подумать, что это
end
влияет либо на результат, либо на выполнение метода.Люди, пишущие конкретные реализации этого интерфейса, могут не понимать, что не следует использовать последний аргумент, что приведет к различным подходам:
Мне не нужно
end
, поэтому я просто проигнорирую его значение,Мне не нужно
end
, поэтому я скину исключение, если это не такnull
,Мне не нужно
end
, но я постараюсь как-то им воспользоваться,Я напишу много кода, который можно будет использовать позже, когда
end
это будет необходимо.Но знайте, что ваш коллега может быть прав.
Все предыдущие пункты основаны на том факте, что рефакторинг прост, поэтому добавление аргумента позже не потребует больших усилий. Но это интерфейс, и как интерфейс он может использоваться несколькими командами, участвующими в разработке других частей вашего продукта. Это означает, что изменение интерфейса может быть особенно болезненным, и в этом случае YAGNI здесь не применяется.
Ответ от hjk дает хорошее решение: добавить метод к уже используемому интерфейсу не особенно сложно, но в некоторых случаях он также имеет существенную стоимость:
Некоторые фреймворки не поддерживают перегрузки. Например, и если я хорошо помню (поправьте меня, если я ошибаюсь), WCF .NET не поддерживает перегрузки.
Если интерфейс имеет много конкретных реализаций, добавление метода к интерфейсу потребует прохождения всех реализаций и добавления метода там же.
источник
(немного позже)
Это все, что вам нужно, метод перегрузки. Дополнительный метод в будущем может быть введен прозрачно, не затрагивая вызовы существующего метода.
источник
end
параметр сейчас не нужен, и продолжает использоватьend
метод -less во всех проектах, то обновление интерфейса - это наименьшее их беспокойство, поскольку становится необходимостью обновления классы реализации. Мой ответ нацелен конкретно на часть «Адаптировать весь код», потому что похоже, что коллега думал о том, чтобы обновлять вызывающие методы исходного метода во всех проектах, чтобы ввести третий параметр по умолчанию / фиктивный ,Обращения к власти не особенно убедительны; лучше представить аргумент, который действителен независимо от того, кто это сказал.
Вот сокращение до абсурда, которое должно убедить или продемонстрировать, что ваш коллега застрял на том, что он «прав» независимо от чувствительности:
Что вам действительно нужно, так это
Вы никогда не знаете, когда вам придется интернационализироваться для клингона, поэтому вам лучше позаботиться об этом сейчас, потому что для его модернизации потребуется много работы, а клингоны не известны своим терпением.
источник
You never know when you'll have to internationalize for Klingon
, Вот почему вы должны просто передать aCalendar
и позволить клиентскому коду решить, хочет ли он отправить aGregorianCalendar
или aKlingonCalendar
(держу пари, некоторые уже сделали). Duh. :-pStarDate sdStart
иStarDate sdEnd
? Мы не можем забыть о Федерации в конце концов ...Date
!HebrewDate start
иHebrewDate end
.С точки зрения разработки программного обеспечения, я считаю, что правильное решение для такого рода проблем заключается в модели построения. Это определенно ссылка авторов «гуру» для вашего коллеги http://en.wikipedia.org/wiki/Builder_pattern .
В шаблоне компоновщика пользователь создает объект, который содержит параметры. Этот контейнер параметров затем будет передан в метод. Это позаботится о любом расширении и перегрузке параметров, которые понадобятся вашему коллеге в будущем, в то же время сделав все это очень стабильным, когда необходимо внести изменения.
Вашим примером станет:
источник
IEventGetter
кISearchFootRequest
. Вместо этого я бы предложил что-то вродеpublic IFooFilter
члена,public bool include(FooType item)
который возвращает, включить или нет элемент. Тогда отдельные реализации интерфейса могут решить, как они будут выполнять эту фильтрациюВам это не нужно сейчас, так что не добавляйте его. Если вам это понадобится позже, расширьте интерфейс:
источник
Ни один принцип разработки не является абсолютным, поэтому, хотя я в основном согласен с другими ответами, я решил сыграть адвоката дьявола и обсудить некоторые условия, при которых я рассмотрю вопрос о принятии решения вашего коллеги:
Now()
, то добавление параметра удаляет побочный эффект, который имеет преимущества для кэширования и модульного тестирования. Возможно, это допускает более простую реализацию. Или, может быть, это более соответствует другим API в вашем коде.Тем не менее, по моему опыту, самым большим следствием для YAGNI является YDKWFYN: вы не знаете, какая форма вам понадобится (да, я только что сделал эту аббревиатуру). Даже если какой-либо параметр ограничения может быть относительно предсказуемым, он может принимать форму ограничения страницы или количества дней или логического значения, определяющего использование даты окончания из таблицы пользовательских настроек, или любого количества вещей.
Поскольку у вас еще нет требований, у вас нет возможности узнать, какой тип должен иметь этот параметр. У вас часто бывает неловкий интерфейс, который не совсем подходит под ваши требования, или вам все равно придется его менять.
источник
Недостаточно информации для ответа на этот вопрос. Это зависит от того, что на
getFooList
самом деле делает, и как это делает.Вот очевидный пример метода, который должен поддерживать дополнительный параметр, используется или нет.
Реализация метода, который работает с коллекцией, в которой вы можете указать начало, но не конец коллекции, часто глупо.
Вы действительно должны взглянуть на саму проблему и спросить, является ли параметр бессмысленным в контексте всего интерфейса, и действительно, какую нагрузку накладывает дополнительный параметр.
источник
Боюсь, у твоего коллеги может быть очень веское замечание. Хотя его решение на самом деле не самое лучшее.
Из его предложенного интерфейса ясно, что
возвращает экземпляры, найденные в течение определенного промежутка времени. Если клиенты в настоящее время не используют конечный параметр, это не меняет того факта, что они ожидают экземпляры, найденные в течение определенного промежутка времени. Это просто означает, что в настоящее время все клиенты используют открытые интервалы (от начала до вечности)
Таким образом, лучший интерфейс будет:
Если вы предоставляете интервал статическим фабричным методом:
тогда клиенты даже не будут чувствовать необходимость указывать время окончания.
В то же время ваш интерфейс более правильно передает то, что он делает, поскольку
getFooList(String, Date)
не сообщает, что это имеет дело с интервалом.Обратите внимание, что мое предложение вытекает из того, что метод делает в настоящее время, а не из того, что он должен или мог бы сделать в будущем, и как таковой принцип YAGNI (который действительно очень актуален) здесь не применим.
источник
Добавление неиспользуемого параметра сбивает с толку. Люди могут вызывать этот метод, предполагая, что эта функция будет работать.
Я бы не добавил это. Позднее добавить его с помощью рефакторинга и механического исправления сайтов вызовов. На статически типизированном языке это легко сделать. Не нужно охотно добавлять его.
Если есть причина , чтобы этот параметр можно предотвратить путаницу: Добавить Assert в реализации этого интерфейса для обеспечения , что этот параметр передается в качестве значения по умолчанию. Если кто-то случайно использует этот параметр, по крайней мере, он немедленно заметит во время тестирования, что эта функция не реализована. Это устраняет риск попадания ошибки в производство.
источник