Вопрос

Один из самых частых аргументов, которые я слышу за то, что не придерживался ТВЕРДЫЙ Принципы в объектно-ориентированном дизайне Ягни (Хотя аргумент часто не так называет):

«Это нормально, что я помещаю как функцию x, так и функцию y в один и тот же класс. Это так просто, зачем беспокоиться о добавлении нового класса (т.е. сложности)».

«Да, я могу поместить всю свою бизнес -логику непосредственно в код графического интерфейса, это намного проще и быстрее. Это всегда будет единственным графическим интерфейсом, и крайне маловероятно, что когда -либо появятся значительные новые требования».

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

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

Это было полезно?

Решение

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

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

- Роберт Гласс ' Правила трех, Факты и ошибки разработки программного обеспечения

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

Лучший способ в начальном дизайне показать, когда Ягни не применяется, - это определить конкретные требования. Другими словами, Сделайте рефакторинг перед написанием кода Чтобы показать, что дублирование не просто возможно, но уже существует: это оправдывает дополнительные усилия.


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

Это действительно единственный пользовательский интерфейс? Планируется ли фоновый режим партии? Будет ли когда -нибудь веб -интерфейс?

Каков ваш план тестирования, и будете ли вы тестировать ориентированную функциональность без графического интерфейса? Что облегчит вам тестирование графического интерфейса, так как вы обычно не хотите тестировать внешний код (например, управление графическим интерфейсом с Генеральным интерфейсом платформы), и вместо этого сосредоточитесь на своем проекте.

Это нормально, что я помещаю как функцию X, так и функцию Y в один и тот же класс. Это так просто, зачем беспокоиться о добавлении нового класса (т.е. сложности).

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

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

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

Другие советы

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

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

Мне нравится думать о Ягни с точки зрения «половины, а не наполовину», чтобы одолжить фразу у 37signals (https://gettingreal.37signals.com/ch05_half_not_half_assed.php) Речь идет о ограничении вашей области, чтобы вы могли сосредоточиться на том, чтобы делать самые важные вещи. Это не оправдание, чтобы стать неаккуратным.

Бизнес-логика в графическом интерфейсе кажется мне наполовину. Если ваша система не будет тривиальной, я был бы удивлен, если ваша бизнес -логика и графический интерфейс еще не изменились независимо, несколько раз. Таким образом, вы должны следовать SRP ("S" в твердом) и Refactor - Yagni не применяется, потому что вам это уже нужно.

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

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

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

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

Вам нужны оба, в разные моменты времени.

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

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

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

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

Что касается ваших индивидуальных моментов:

Это нормально, что я помещаю как функцию X, так и функцию Y в один и тот же класс. Это так просто, зачем беспокоиться о добавлении нового класса (т.е. сложности).

Я бы отметил, что иметь все в одном классе более сложный (Потому что взаимосвязь между методами более интимна и труднее понять). Наличие много небольших классов не сложно. Если вы чувствуете, что список доходит до долго, просто организуйте их в пакеты, и все будет в порядке :-). Лично я обнаружил, что просто разделение класса на два или три класса может очень помогать с читаемостью, без каких -либо дальнейших изменений.

Не бойтесь маленьких занятий, они не кусаются ;-).

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

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

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

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

Сплошные принципы позволяют программному обеспечению адаптироваться к изменениям - как в требованиях, так и в технологических изменениях (новые компоненты и т. Д.) Два ваших аргумента предназначены для неизменных требований:

  • «Маловероятно, что новые требования когда -либо пришли».
  • «Если в маловероятном случае новых требований»

Может ли это быть правдой?

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

Здесь есть другие замечательные ответы.

Понятно, гибко и способно исправить и улучшения всегда - это то, что вы находятся собираюсь понадобиться. Действительно, Ягни предполагает, что вы можете вернуться и добавить новые функции, когда они оказываются необходимыми с относительной легкостью, потому что никто не собирается делать что -то сумасшедшее, например, неактуальные функциональные возможности в классе (Yagni в этом классе!) Или бизнес -логику в логику пользовательского интерфейса в пользовательском интерфейсе Анкет

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

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

С помощью модульных тестов (при условии хорошего покрытия кода) вы сможете рефакторировать функцию 1 Safe and Secure, вы не сломаете функцию 2, но без модульных тестов и с функциями в том же классе (просто для того, чтобы быть ленивым в вашем примере) Рефакторинг в лучшем случае рискованен, в лучшем случае катастрофический.

Итог: Следуйте принципу KIS (сохраняйте его простым), или для принципа интеллектуального поцелуя (kis глупо). Возьмите каждый случай по заслугам, нет глобального ответа, но всегда рассматривайте, должны ли другие кодеры читать / поддерживать код в будущем и выгоду от модульных тестов в каждом сценарии.

TLDR;

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

Следовательно, из этого следует, что Solid/SRP просит вас сформировать классы для кода, так что у него будет единственная причина для изменений. Например, небольшое изменение графического интерфейса или смены ServiceCall.

Ягни говорит (если вы хотите заставить применить его в этом сценарии), поскольку вы не знаете, что изменится, и если изменение графического интерфейса приведет к изменению GUI+ServiceCall (аналогично изменение в бэкэнд, вызывая GUI+изменение в севисекол)) , просто поместите весь этот код в одиночный класс.

Длинный ответ:

Прочитайте книгу «Разработка гибких программного обеспечения, принципы, шаблоны и практики»

Я ставлю из него короткую отрывку о твердом/SRP: «Если, [...] применение не меняется таким образом, чтобы две обязанности менялись в разное время, нет необходимости разделять их. Действительно, разделение их будет пахнуть ненужной сложностью.

Здесь есть коррогал. Ось изменения - это ось изменения, только если происходят изменения. Не разумно применять SRP - или какой -либо другой принцип, в этом отношении - если нет симптомов ».

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top