Прямо сейчас я борюсь с этим понятием СУХОЙ (не повторяй себя) в моем коде. Я создаю эту функцию, в которой я боюсь, что она становится слишком сложной, но я пытаюсь следовать принципу СУХОЙ.
createTrajectoryFromPoint(A a,B b,C c,boolean doesSomething,boolean doesSomething2)
Я говорю, что эта функция принимает 3 входных параметра, а затем функция будет делать что-то немного другое, учитывая логические комбинации doesSomething
и doesSomething2
. Однако проблема, с которой я сталкиваюсь, заключается в том, что эта функция значительно усложняется с каждым добавленным новым логическим параметром.
Поэтому мой вопрос заключается в том, лучше ли иметь кучу различных функций, которые разделяют одну и ту же логику (что нарушает принцип СУХОЙ), или одну функцию, которая ведет себя немного по-разному, учитывая ряд параметров, но делая ее намного более сложной (но сохраняя СУХОЙ)?
createTrajectory...
функции вызывают?boolean
в качестве параметра в лучшем случае подозрительно.Ответы:
логические аргументы для запуска разных путей кода в одной функции / методе - ужасный запах кода .
То , что вы делаете нарушает слабосвязанность и высокое сцепление и единую ответственность принципы, которые являются гораздо более важным , чем DRY в приоритете.
Это означает, что вещи должны зависеть от других вещей только тогда, когда они должны ( Сцепление ), и что они должны делать одно и только одно (очень хорошо) ( Сплоченность ).
По вашему собственному упущению, это слишком тесно связано (все логические флаги являются типом зависимости от состояния, которое является одним из худших!) И имеет слишком много отдельных обязанностей, смешанных (слишком сложных).
То, что ты делаешь, в любом случае не в духе СУХОГО. СУХОЙ больше о повторении (
R
расшифровываетсяREPEAT
). Избегать копирования и вставки является его основной формой. То, что вы делаете, не связано с повторением.Ваша проблема в том, что ваша декомпозиция кода не на должном уровне. Если вы думаете, что у вас будет дублирующийся код, то это должна быть его собственная функция / метод, который соответствующим образом параметризован, а не скопирован и вставлен, а остальные должны быть названы описательно и делегированы основной функции / методу.
источник
Тот факт, что вы передаете логические значения, чтобы функция выполняла разные действия, является нарушением принципа единой ответственности. Функция должна делать одну вещь. Он должен делать только одну вещь, и он должен делать это хорошо.
Он пахнет так, как будто вам нужно разделить его на несколько небольших функций с описательными именами, разделяя пути кода, соответствующие значениям этих логических значений.
Как только вы это сделаете, вы должны найти общий код в результирующих функциях и выделить его в свои собственные функции. В зависимости от того, насколько сложна эта вещь, вы можете даже выделить один или два класса.
Конечно, это предполагает, что вы используете систему контроля версий и что у вас есть хороший набор тестов, так что вы можете выполнять рефакторинг, не опасаясь что-то сломать.
источник
Почему бы вам не создать еще одну функцию, содержащую всю логику в вашей функции, прежде чем вы решите что-то сделать или что-то2, а затем иметь три функции, такие как:
И теперь, передавая три одинаковых типа параметров трем различным функциям, вы снова будете повторять себя, поэтому вы должны определить структуру или класс, содержащий A, B, C.
В качестве альтернативы вы можете создать класс, содержащий параметры A, B, C и список операций, которые необходимо выполнить. Добавьте, какие операции (что-то, что-то2) вы хотите выполнить с этими параметрами (A, B, C), зарегистрировав операции с объектом. Затем есть метод для вызова всех зарегистрированных операций на вашем объекте.
источник
DRY можно зайти слишком далеко, лучше всего использовать принцип единой ответственности (SRP) в сочетании с DRY. Добавление флагов bool к функции, заставляющей ее делать несколько разные версии одного и того же кода, может быть признаком того, что вы слишком много делаете с одной функцией. В этом случае я бы предложил создать отдельную функцию для каждого случая, который представляют ваши флаги, тогда, когда у вас есть каждая записанная функция, это должно быть достаточно очевидно, если есть общий раздел, который можно переместить в приватную функцию, не передавая все флаги Если нет видимого фрагмента кода, то вы действительно не повторяетесь, у вас есть несколько разных, но похожих случаев.
источник
Я обычно делаю несколько шагов с этой проблемой, останавливаясь, когда не могу понять, как идти дальше.
Во-первых, делай то, что сделал. Тяжело с СУХОЙ. Если вы не получите большой волосатый беспорядок, все готово. Если, как и в вашем случае, у вас нет повторяющегося кода, но каждое логическое значение проверяется в 20 различных местах, переходите к следующему шагу.
Во-вторых, разбить код на блоки. На логические значения ссылаются только один раз (ну, может быть, иногда два раза), чтобы направить выполнение к нужному блоку. С двумя логическими значениями вы получите четыре блока. Каждый блок практически идентичен. СУХОЙ нет Не делайте каждый блок отдельным методом. Это было бы более элегантно, но помещение всего кода в один метод облегчает или даже делает возможным для тех, кто занимается техническим обслуживанием, видеть, что они должны вносить каждое изменение в четырех местах. С хорошо организованным кодом и высоким монитором различия и ошибки будут почти очевидны. Теперь у вас есть поддерживаемый код, и он будет работать быстрее, чем исходный запутанный беспорядок.
В-третьих, попытайтесь собрать дубликаты строк кода в каждом из ваших блоков и превратить их в приятные, простые методы. Иногда ты ничего не можешь сделать. Иногда вы не можете сделать много. Но каждый маленький шаг, который вы делаете, возвращает вас к СУХОЙ и делает код чуть легче следовать и безопаснее поддерживать. В идеале ваш оригинальный метод может не иметь дублирующегося кода. В этот момент вы можете разделить его на несколько методов без логических параметров или нет. Удобство вызова кода в настоящее время является главной заботой.
Я добавил свой ответ к большому числу уже здесь из-за второго шага. Я ненавижу повторяющийся код, но если это единственный понятный способ решения проблемы, делайте это так, чтобы кто-нибудь сразу понял, что вы делаете. Используйте несколько блоков и только один метод. Сделайте блоки как можно более одинаковыми в именах, интервалах, выравниваниях ... во всем. Различия должны затем выскочить на читателя. Это может сделать очевидным, как переписать его в СУХОЙ манере, и если нет, то его поддержание будет достаточно простым.
источник
Альтернативный подход заключается в замене логических параметров интерфейсными параметрами кодом для обработки различных логических значений, реорганизованных в реализации интерфейса. Так что вы бы
где у вас есть реализации IX и IY, которые представляют различные значения для логических значений. В теле функции, где бы вы ни находились
вы заменяете его вызовом метода, определенного в IX, с реализациями, содержащими пропущенные блоки кода.
источник