Должен ли мой код быть СУХИМ или читаемым, если он не может быть и тем, и другим?


14

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

Мой самый последний пример: моя программа принимает ввод, и из-за жестких правил форматирования, она может легко определить, должен ли ввод быть зашифрован или расшифрован. Чтобы упростить, после того, как ключ шифрования и сообщение преобразованы / сгенерированы для совместимости, необходимо вычесть ключ из зашифрованного сообщения или добавить ключ в незашифрованное сообщение, чтобы получить желаемый результат (думайте о ключе как о шифровании, сообщение + шифрование = код; код - шифрование = сообщение). Позиция СУХОЙ говорит мне, что я должен преобразовать свое зашифрованное сообщение не так, как мое незашифрованное сообщение, так что функция, которая берет ключ шифрования и применяет его к сообщению, никогда не должна различаться. Я обнаружил, что это означает, что мне нужны вложенные операторы if в функции, но логика кажется твердой. Этот код, однако, не легко читается.

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

Должен ли я склоняться к читабельному коду или лаконичному коду? Или я пропустил другой способ получить эту функциональность и удовлетворить оба принципа? Является ли это позицией такого масштаба, в которой нужно учитывать цель проекта и принимать наилучшие решения для достижения этой цели?

Пока что я склонен подчеркивать сжатый, СУХОЙ код над читаемым кодом.


2
Используется во-первых, СУХОЙ во-вторых, Читаемый третий. Очень удобный код приводит к получению очень удобочитаемого кода, который легче соответствует DRY и читаем. Вот почему вы хотите взять неприятные сложности и собрать их где-нибудь с хорошим API, если они не могут быть улучшены; по крайней мере, код, который взаимодействует с ними, будет избавлен от того, чтобы быть плохим также с этим подходом.
Джимми Хоффа

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

2
Не дубликат Краткий v. Читаемый и DRY v. Читаемый два очень разных сравнения. Не быть СУХОЙ намного опаснее, чем не быть кратким.
Джечлин

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

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

Ответы:


20

СУХОЙ - это руководство, а не религия. Те, кто доводит это до уровня СУХОГО превыше всего, зашли слишком далеко.

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

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

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

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


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

1
@lutze Я программист на Perl, а иногда и на Ruby, и, конечно, могу понять искушение написать там умный код. Предварительная версия этого ответа включала цитату Ларри Уолла о высокомерии - я считаю, что это очень важное достоинство при работе с кодом, который когда-нибудь будет поддерживаться. Из-за возможной краткости языков иногда бывает трудно получить преимущество написания большего количества кода, чем пытаться создать умный плотный код ... пока вам не придется его поддерживать.

17

Я не уверен, исходя из вопроса, который вы понимаете, СУХОЙ. СУХОЙ код не совпадает с кратким. Довольно часто это наоборот.

Здесь я не уверен, в чём дело для этого примера. Сделайте функцию для шифрования, функцию для дешифрования, вспомогательные средства для общей функциональности (смесь байтов) и простой интерфейс для ввода и определения шифрования / дешифрования ... Не повторяйте себя.

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

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


Замечательные моменты, я действительно немного скомбинировал принцип DRY с целью создания краткого кода.
Лутце

12

Я не знаком с вашим конкретным случаем, но могу дать некоторые общие рекомендации.

Целью как читаемости, так и СУХОГО является ремонтопригодность .

Поддержка в большинстве случаев важна, так как вы тратите больше времени на поддержку кода, чем на его написание. Это особенно верно, если вы считаете написание кода специальным видом обслуживания.

К сожалению, СУХОЙ часто понимают неправильно. Это отчасти потому, что это кажется таким простым, но, как и множество простых вещей, это может быть, ну ... сложно.

Целью СУХОГО является то, что каждая функциональная единица существует только в одном месте. Если следовать этому принципу, сопровождающий код, которому поручено изменить или проверить эту функциональность, может обработать код за один раз. Если DRY не соблюдается, существует реальная опасность того, что некоторая копия функциональности не будет поддерживаться должным образом.

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

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

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

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

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

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

В заключение, ответ на ваш вопрос заключается в том, чтобы сделать то, что делает ваш код максимально поддерживаемым. Что это означает в вашем сценарии, решать вам.


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

+1. В настоящее время я имею дело с системой, которая злоупотребляет копированием и вставкой до смешного уровня. Выделение одного метода из кода копирования / вставки удалило более 400 строк из одного из моих классов сегодня. К сожалению, я нашел это в методе с 900
строками

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

7

Если ваши функции становятся более сложными и более длинными (то есть менее читабельными), когда вы пытаетесь сделать их СУХИМЫМИ, то вы делаете это неправильно. Вы пытаетесь поместить слишком много функциональности в одну функцию, потому что думаете, что это единственный способ избежать повторения одних и тех же фрагментов кода во второй функции.

Создание кода СУХОЙ почти всегда означает рефакторинг общей функциональности для более мелких функций. Каждая из этих функций должна быть проще (и, следовательно, более читабельной), чем оригинальная. Чтобы сохранить все в исходной функции на том же уровне абстракции, это также может означать рефакторинг дополнительных деталей, которые не используются в других местах. Ваша исходная функция затем становится «функцией высокого уровня», вызывая меньшие, и она также становится меньше и проще.

Следовательно, это в основном приводит к различным уровням абстракций в вашем коде - и некоторые люди считают, что такой код менее читабелен. По моему опыту, это заблуждение. Ключевой момент здесь состоит в том, чтобы дать мелким функциям хорошие имена, ввести хорошо названные типы данных и абстракции, которые могут быть легко поняты вторым человеком. Таким образом, «СУХОЙ» и «читабельность» должны очень и очень редко вступать в конфликт.


2

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


0

Я бы выбрал удобочитаемый (= поддерживаемый) вместо СУХОГО в любой день недели. В действительности оба часто совпадают, и тот, кто понимает DRY, обычно создает (в основном) читаемый код.


2
без объяснения этот ответ может стать бесполезным в случае, если кто-то постит противоположное мнение. Например, если кто-то публикует утверждение типа «Я бы выбрал СУХОЙ (= ремонтопригодный) вместо читабельного в любой день недели», как этот ответ поможет читателю выбрать два противоположных мнения? Подумайте об изменении его в лучшую форму
комнат

0

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

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

Повторный код должен быть либо реорганизован в свой собственный метод, либо извлечен в свой собственный класс.

Повторяющийся код должен быть последним средством. Сначала читаемые и СУХИЕ, не читаемые, если вы ограничиваете область повторного кода.

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