Какие популярные «лучшие практики» не всегда являются лучшими и почему? [закрыто]


100

«Лучшие практики» повсюду в нашей отрасли. Поиск Google на «кодировании лучших практик» появляется около 1,5 миллионов результатов. Идея, кажется, приносит утешение многим; просто следуйте инструкциям, и все будет хорошо.

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

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

Количество лучших практик, о которых я читал, слишком велико, чтобы перечислять их здесь или задавать отдельные вопросы, поэтому я хотел бы сформулировать это как общий вопрос:

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

Я бы предпочел услышать о конкретных примерах и опыте.


8
С какими методами вы не согласны? Просто любопытно.
Серхио Акоста

Любой может написать книгу, и я не обязан с ней соглашаться - это так просто.
Работа

Одна вещь, которая мне нравится в книге «Выполнение кода» Стива Макконнелла, заключается в том, что он подкрепляет все свои советы убедительными доказательствами и исследованиями. Просто
говорю

5
@Walter: это было открыто в течение многих месяцев, это определенно конструктивно, зачем закрывать это?
Orbling

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

Ответы:


125

Я думаю, что вы ударили гвоздь по голове этим заявлением

Я не хотел бы принимать вещи за чистую монету и не думать о них критически

Я игнорирую почти все лучшие практики, когда они не объясняют, почему они существуют.

Раймонд Чен лучше всего описывает эту статью, когда говорит

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


4
Замечательная цитата.
Дэвид Торнли

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

3
Я надеюсь, что люди не воспринимают это как оправдание, чтобы не искать причину лучших практик. ;) К сожалению, я видел разработчиков с таким отношением.
Vetle

3
Обоснование это хорошо. Исследование лучше.
Джон Перди

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

95

Можно также выбросить это на ринг:

Premature optimization is the root of all evil.

Нет, это не так.

Полная цитата:

«Мы должны забыть о малой эффективности, скажем, в 97% случаев: преждевременная оптимизация - корень всего зла. Но мы не должны упускать наши возможности в эти критические 3%».

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

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

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


4
+1 для сильных Нет, это не так.
Стивен

21
Но если вы уже поняли, что одна конкретная оптимизация находится в пределах этих критических 3%, вы преждевременно оптимизируете ее?
Джон

7
@ Роберт: Тогда в чем смысл несогласия с утверждением, что «преждевременная оптимизация - корень всего зла»?
Джон

8
Оптимизация дизайна высокого уровня и технических решений, таких как выбор языка, никогда не бывает преждевременной. Однако часто только после того, как вы в основном завершили проектирование, становится очевидным, что его неэффективность, поэтому Фред Брукс сказал, что большинство команд пишут одноразовую версию, намерены они или нет. Еще один аргумент в пользу прототипирования.
Доминик Макдоннелл

8
@ Роберт, цитата Кнута была оптимизирована преждевременно ...

94

Один возврат на функцию / метод.


7
Я собирался поставить это. Я люблю некоторые ранние ответные заявления.
Карсон Майерс

4
Абсолютно! Люди изобретают довольно интересный поток программ, чтобы избежать ранних returnзаявлений. Либо глубоко вложенные структуры управления или постоянные проверки. Это действительно может раздуть метод, когда if returnдействительно может упростить эту проблему.
snmcdonald

4
Если вам нужно несколько возвратов в функцию (кроме охранников), ваша функция, вероятно, слишком длинная.
EricSchaefer

18
Нет смысла иметь ключевое слово return, если оно не предназначено для нескольких мест. Возвращайся рано, возвращайся часто. Это только послужит дальнейшему упрощению вашего кода. Если люди могут понять, как работают заявления о прерывании / продолжении, почему они борются с возвращением?
Эван Плейс

7
Я думаю, что это очень устаревшая лучшая практика. Я не думаю, что это лучшая современная практика.
Скиллдрик

87

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

Проблема в том, что 100% подходящее решение редко существует. Может существовать 80% подходящее решение, и его использование, вероятно, подойдет. А как на 60% подойдет? 40% Где вы проводите черту? Если вы не проведете линию, вы можете в конечном итоге включить раздутую библиотеку в свой проект, потому что вы используете 10% ее возможностей - просто потому, что вы хотите избежать «изобретать колесо».

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


3
У меня было это наоборот. Я создал свой собственный компонент сетки ajax, потому что в то время не было ни одного, который бы делал то, что я хотел, но позже заменил его сетками Ext JS. Помогло то, что я с самого начала сделал предположение, что слой дисплея будет заменен.
Джори Себрехтс

20
Согласовано. Если бы никто не изобрел велосипед заново, мы бы ездили на наших машинах на деревянных шинах.
Ученик доктора Вилли

6
Я всегда чувствую себя как ваш пример с 10%, когда я добавляю Boost в проект C ++. Мне всегда нужно меньше 10%, напрямую, но, конечно, мне нужны функции импорта других модулей, которые импортируют другие модули, которые ...
Роман Старков

3
+1: только на этой неделе я заново изобрел колесо (например, заменил раздутый, но популярный плагин jquery, который мы использовали чем-то, что соответствует нашим потребностям, но модульным), и это привело к огромному приросту производительности. Кроме того, есть люди, чья работа заключается в том, чтобы буквально заново изобретать колесо: например, компания Michelin занимается исследованиями и разработками для улучшения шин.
wildpeaks

2
@Dr. Коварные, эти колеса не были заново изобретены, они были переработаны!

78

«Модульная проверка всего».

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

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


7
Я подозреваю, что «модульное тестирование всего» стало клише, как цитата «преждевременной оптимизации». Я в целом согласен с вашими пропорциями и видел множество примеров того, как разработчики прилагают огромные усилия, чтобы высмеивать объект уровня приложения, усилия, которые лучше потратить на приемочное тестирование.
Роберт Харви

36
Если изменение структуры метода приводит к изменению ваших тестов, возможно, вы неправильно выполняете тестирование. Модульные тесты не должны проверять реализацию, только результат.
Адам Лир

7
@ Анна Лир: я думаю, что он говорил о внесении изменений в дизайн / структурные изменения (рефакторинг). Поскольку дизайн недостаточно развит, когда вы найдете лучший способ сделать это, вам, возможно, придется изменить множество тестов. Я согласен с тем, что когда вы более опытный тестировщик, вам будет легче заметить, где тест будет плохой идеей (по этой и другим причинам), но если дизайн не совсем зрелый, у вас, скорее всего, будут некоторые тесты в путь.
n1ckp

13
Я думаю, что это также, почему идея «делай сначала тест» не работает. Чтобы сделать тесты в первую очередь, вы должны иметь правильный дизайн. Но чтобы иметь правильный дизайн, нужно попробовать и посмотреть, как они работают, чтобы вы могли их улучшить. Таким образом, вы не сможете провести тесты до того, как у вас будет дизайн, и для того, чтобы дизайн был правильным, вам нужно написать код и посмотреть, как он работает. Если у вас нет действительно супер-архитектора, я не понимаю, как эта идея будет работать.
n1ckp

13
@ n1ck TDD на самом деле не столько тестирование, сколько проектирование. Идея состоит в том, что вы развиваете свой дизайн с помощью тестов (поскольку это быстро предоставляет разумный API для ваших вещей), а не приспосабливаете тесты к существующему дизайну (который может быть плохим / недостаточным). Так что нет, вам не нужно иметь право проектировать, чтобы делать тесты в первую очередь.
Адам Лир

57

Всегда программируйте на интерфейсы.

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


4
Согласен, вы программируете интерфейс, когда вам нужен интерфейс (т. Е. Стабильный API для работы).
Роберт Харви

45
В моем прочтении это правило не касается интерфейсов как языковых конструкций. Это означает, что вы не должны делать никаких предположений о внутренней работе класса при вызове его методов и должны полагаться только на контракты API.
Жолт Тёрёк

2
Хорошо, вот интересный вопрос - я в первую очередь разработчик .NET, поэтому для меня мои интерфейсы выглядят как IBusinessManager или IServiceContract. Для меня это очень легко ориентироваться (и я обычно храню свои интерфейсы в другом пространстве имен [или даже в другом проекте]). Когда я использовал Java, я на самом деле находил это непонятным (обычно реализации интерфейса, которые я видел, имеют суффикс .impl - и интерфейсы не имеют границ). Так может ли это быть проблемой стандартов кода? Конечно, интерфейсы в java заставляют код выглядеть загроможденным - они выглядят точно так же, как обычные классы на первый взгляд.
Уотсон,

5
@Watson: одна из затрат заключается в том, что каждый раз, когда я нажимаю F3 («перейти к объявлению») при вызове метода в Eclipse, я перехожу к интерфейсу, а не к одной реализации. Затем мне нужно нажать -T, стрелка вниз, вернуться к реализации. Он также блокирует некоторые автоматические рефакторинги - например, вы не можете встроить метод в определение интерфейса.
Том Андерсон

4
@Tom: Хорошо, сэр, я бы с удовольствием втянул вас в эту войну, «Затмение» против «Интеллидж» - однако у меня есть выдающийся моральный кодекс, который не позволяет мне вступать в физическую конфронтацию с кем-то, кто имеет явные недостатки. БУМ. Я не говорю, что «Затмение - это плохо», я говорю, что если бы силы Оси использовали его для создания или проектирования своих военных машин, Вторая мировая война теперь была бы известна как «Двухдневное столкновение». Если серьезно, я обнаружил, что ему не хватает некоторой полировки, которую я получаю в готовых IDE (Intellij / VS + ReSharper). Я сталкивался с этим не раз, а это слишком много.
Уотсон

46

Не используйте ничего с открытым исходным кодом (или не для Microsoft .NET для вас)

Если Microsoft не разработала его - мы не используем его здесь. Хочешь использовать ORM - EF, хочешь использовать IOC - Unity, хочешь войти - блок приложения корпоративной регистрации. Существует так много лучших библиотек - и все же я всегда зацикливаюсь на заказе в долларовом меню мира разработки. Я клянусь, что каждый раз, когда я слышу о Microsoft Best Practices, я думаю, что «Правила питания McDonald's». Конечно, вы, вероятно, будете жить, если вы последуете за ними, но вы также будете недоедать и иметь избыточный вес.

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

13
Звучит ужасно ... = (Я, вероятно, слишком много с другой стороны, хотя я избегаю M $ как можно больше.
Lizzan

Так не должно быть. Библиотека должна быть выбрана за ее ценность, а не только с учетом того, кто ее создал. Например, я люблю EF, но у меня был плохой опыт работы с Enterprise Library, и я нашел лучшие инструменты для проверки и ведения журналов, такие как FluentValidation, log4net и Elmah.
Маттео Моска

4
Вы не будете уволены за покупку IBM ^ wMicrosoft
Кристофер Махан

17
Существует также версия с зеркальным отображением, т.е. никогда не используйте что-либо от Microsoft или никогда не используйте то, за что вы платите.
Ричард Гадсден

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

40

Ориентация объекта

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


7
Я не могу представить себе создание программной системы какого-либо значительного размера без использования организации, которую обеспечивает объектная ориентация.
Роберт Харви

18
Роберт. Unix не является объектно-ориентированным и определенно считается программной системой значительных размеров. Он также кажется довольно популярным (например, Mac OSX, iPhone, телефоны Android и т. Д.)
Кристофер Махан,

7
Я имел в виду, что я думаю, что мы должны использовать наиболее подходящую методологию. Я видел, как люди используют методы и классы там, где это громоздко и не имеет особого смысла, просто потому, что «оно объектно-ориентировано». Это культ груза.
LennyProgrammers

8
Там нет серебряной пули. Функциональное программирование (Haskell) довольно успешно, не будучи объектно-ориентированным. В конце концов, у вас есть несколько инструментов, и ваша задача - выбрать лучший ассортимент для поставленной задачи.
Матье М.

9
Самое смешное, что помимо использования классов, полиморфизма и тому подобного, большая часть объектно-ориентированного кода на самом деле является процедурным кодом.
Оливер Вейлер

35

Весь код должен быть прокомментирован.

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

/** hey you, if didn't get, it's logger. */
private static Logger logger = LoggerFactory.getLogger(MyClass.class);

13
Весь код должен быть понятен . Комментарии являются основным инструментом в этом, но далеко не единственным.
Тревел

Абсолютно, код должен быть понятным. Но нет единой причины написать комментарий, который ничего не добавит, например, к имени метода. Если вы напишите, /** sets rank. */ void setRank(int rank) { this.rank = rank; }я приму комментарий как глупый. Почему это написано?
Владимир Иванов

2
Сгенерированная документация. Вот для чего /** */нужен формат вместо /* */комментария формата. Или для .NET это было бы///
Берин Лорич

10
Используя }//end if, }//end for, }//end whileявляются лучшим примером расточительного комментирования я когда - либо сталкивался. Я видел это много раз, когда открывающая скобка была не более чем на 2 строки выше. ИМХО, если вам нужны эти комментарии, тогда ваш код нуждается в перефакторинге ... или вам нужно потратить 20 долларов и купить IDE / текстовый редактор, который выделяет соответствующие фигурные скобки.
scunliffe

7
Код скажи "как". В комментариях нужно сказать «почему».

32

Методологии, особенно разборки. Я не могу сохранять спокойствие, когда слышу, как взрослые используют фразу «Scrum Master». Я так устал от того, что разработчики протестуют, что некоторые аспекты Методологии X не работают для их компании, а только о том, что Гуру так-то и-то сказал, что причина, по которой он не работает, в том, что они на самом деле не настоящие практики Методологии X. "Скрай сложнее, ты должен, мой ученик падаван!"

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

Ряд ролей определен в Scrum. Все роли делятся на две отдельные группы - свиньи и куры - в зависимости от характера их участия в процессе развития.

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


Интересно. Я согласен в определенной степени. Хотя с этой последней частью: называйте их как хотите, это мнемоника, вот и все.
Стивен Эверс

12
+1 ... ты прав, это сложно воспринимать всерьез. <большой гулкий голос> * Я - скраммастер * </ voice>
GrandmasterB

2
И притчи. Это напоминает мне о церковных проповедях или видах анекдотов, которыми славятся гуру самопомощи (и комедианты): «Возьми моего друга Стива. Стив постоянно спорил со своей женой Шерил. Эти двое шли на это часами, чтобы момент, когда их брак оказался в реальной опасности. Затем, однажды ... "Эти виды дидактических нитей не беспокоят меня в других сферах, но я не хочу видеть их распространение в технических науках.
evadeflow

2
А как насчет Scrum Ninjas?
Берин Лорич

1
Я не согласен со сравнением "Свинья с курицей" ... оно прямо перед лицом Agile Manifesto. А именно, «Сотрудничество с клиентами по договорам». Клиенты так же наделены (если не больше) успехом проекта, как и команда проекта. Называя некоторые роли свиньями и другими ролями, цыплята устанавливают менталитет «мы против них», который ИМХО является самым большим препятствием на пути к успешным проектам.
Майкл Браун

25

Реляционное сопоставление объектов ... http://en.wikipedia.org/wiki/Object-relational_mapping

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


19
Преждевременная оптимизация - корень всего зла. Медленный код в реальной жизни является невероятно редкой проблемой по сравнению с не поддерживаемым кодом. Используйте ORM, затем прорежьте абстракцию только там, где вам это нужно.
Fishtoaster

28
ORM - это инструмент 80-20. Они предназначены для обработки 80% CRUD, который становится настолько утомительным, чтобы писать весь этот бесконечный сантехнический код через некоторое время. Остальные 20% могут быть выполнены более «обычными» способами, такими как использование хранимых процедур и написание обычных SQL-запросов.
Роберт Харви

18
@ Fishtoaster: Разве вы не имеете в виду: «Мы должны забыть о малой эффективности, скажем, в 97% случаев: преждевременная оптимизация - корень всего зла. Но мы не должны упускать наши возможности в эти критические 3%».?
Роберт Харви

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

12
@Craig: Как ты не узнал иронию в своем заявлении? Потребность в годе, чтобы научиться получать хорошую производительность от ORM, является отличным аргументом против ORM, так же как и необходимость «контролировать» созданный SQL и внедрять хранимые процедуры. Если у вас есть знания для этого, у вас есть знания, чтобы полностью обойти ORM.
Николас Найт

22

Написание имен функций, как если бы они были английскими предложениями:

Draw_Foo()
Write_Foo()
Create_Foo()

и т.д. Это может выглядеть великолепно, но это неприятно, когда вы изучаете API. Насколько проще искать в индексе «Все, что начинается с Foo»?

Foo_Draw()
Foo_Write()
Foo_Create()

и т.п.


2
Вероятно, примерно так же просто, как набрать Foo в списке функций TM.
Джош К

68
Звучит так, будто вы действительно хотите, чтобы это было Foo.Draw(), Foo.Write()и Foo.Create(), чтобы вы могли это сделать Foo.methods.sortилиFoo.methods.grep([what I seek]).sort
Инамати

7
Начиная с «Get» еще один пример.
JeffO

1
Я родом из мира объективного-c и очень скучаю по многословным именам методов и инфиксным обозначениям, когда я делаю Java (моя другая жизнь). С тех пор, как завершение кода начало работать, я также не обнаружил лишней проблемы с типизацией.

2
@Scott Уитлок: Не что из даты для некоторых разработчиков .NET, IIRC, VS 2008 не сделал этого. 2010 год, хотя, и это фантастика.
Стивен Эверс

22

MVC - я часто нахожу, что включение многих проблем веб-дизайна в подход MVC - это больше радость фреймворка (рельсов и т. Д.), Чем простота или структура. MVC является фаворитом "астронавтов архитектуры", которые, кажется, ценят чрезмерные строительные леса за простоту. YMMV.

OO на основе классов - на мой взгляд, поощряет сложные структуры изменяемого состояния. единственные убедительные случаи, которые я обнаружил для ОО на основе классов за эти годы, - это банальные примеры "shape-> rectangle-> square", которые составляют главу 1 любой книги о OO


4
Я занимался веб-разработкой в ​​ASP.NET и ASP.NET MVC, и, хотя MVC действительно выглядит не очень хорошо, я предпочитаю его над ASP.NET по многим причинам: простота, удобство сопровождения и чрезвычайно точный контроль над разметкой. Все имеет свое место, и, хотя все это кажется немного повторяющимся, поддерживать это удовольствие. Это полностью настраиваемый, так что если вам не нравится поведение из коробки, вы можете изменить его.
Роберт Харви

1
Что касается ОО, есть хорошие и плохие способы сделать это. Наследование переоценивается и используется в реальном мире более экономно, чем вы могли бы поверить в большинстве книг; в настоящее время существует тенденция к более функциональному, неизменному стилю разработки даже в мире ОО.
Роберт Харви

1
+1 за упоминание MVC. Хотя концепция MVC (разделять логику уровня данных, логику представления и фоновую логику - хорошая идея) физически разделять их на сложную иерархию папок с путаницей файлов, содержащих фрагменты кода, глупа. Я обвиняю весь этот феномен в недостатке поддержки пространства имен в PHP и в том, что новички-разработчики прославляют методы, разработанные десятилетиями, как «новейшую вещь». Все просто, создайте пространство имен для средств доступа к базе данных, графического интерфейса пользователя и фоновой логики (и подпространств имен, где это необходимо).
Эван Плейс

3
Что касается ОО, вы действительно не увидите его преимуществ, пока ваш проект не достигнет такого размера, когда управление сложностью станет важным. Следуйте принципу единой ответственности везде, где это возможно, и если ваш код доступен публично (например, для .dll), по возможности скрывайте внутреннюю реализацию классов / методов / свойств, чтобы сделать код более безопасным и упростить API.
Эван Плейс

1
Я лично считаю пример shape-> rectangle-> square одним из самых элегантных аргументов против oop. например, для Square(10).Draw()этого достаточно Rectangle(10, 10).Draw(). так что я думаю, это означает, что квадрат является подклассом прямоугольника. Но mySquare.setWidthHeight(5,10)это нонсенс (т.е., он не соответствует принципу подстановки Лискова), квадрат не может иметь разную высоту и ширину, хотя прямоугольник может, так что подразумевается, что прямоугольник является подклассом квадрата. В других контекстах это известно как «проблема круга, эллипса»
SingleNegationElimination

22

YAGNI

( Тебе это не понадобится )

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

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

(Конечно, можно утверждать, что хорошо продуманная кодовая база также позволит добавлять функции позже, но реальность другая)


15
Я согласен с YAGNI, но я вижу, к чему ты клонишь. Цель YAGNI - иметь дело с людьми, которые хотят спланировать все заранее и до мельчайших деталей. Однако в девяти случаях из десяти он используется в качестве предлога для недопущения инженерного кода или полного пропуска планирования.
Джейсон Бейкер

12
П. Флойд, @ Джейсон Бейкер: +1 Абсолютно верно. Старая поговорка здесь применима: «месяцы в лаборатории могут сэкономить часы в библиотеке»
Стивен Эверс

Спецификация часто (и в большинстве случаев должна) оставлять большую часть реализации и некоторые интерфейсы открытыми. все, что не входит в спецификацию напрямую, но требуется для реализации спецификации, будь то решение о реализации, пользовательский интерфейс или что-то еще, также является косвенным требованием спецификации. Если функция не входит в спецификацию и не подразумевается в спецификации, то она вам не нужна. Как это может сбить с толку?
SingleNegationElimination

1
@TokenMacGuy решающий аспект подразумевается частью спецификации . Вот где мнения сильно отличаются.
Шон Патрик Флойд

20

Для SQL

  1. Не используйте триггеры
  2. Всегда скрывать таблицы за представлениями

Для того, чтобы:

  1. Они особенность, которая имеет свое место. У вас есть несколько путей обновления таблицы или требуется 100% аудит?

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

Редактировать:

Номер 3: Избегать * с EXISTS. Попробуйте 1/0. Оно работает. Список столбцов не оценивается в соответствии со стандартом SQL. Страница 191


3
# 2 - это лучшая практика?
Хоган

2
@Hogan: Да, это задокументировано во многих местах vyaskn.tripod.com/sql_server_security_best_practices.htm и flylib.com/books/en/3.404.1.34/1 И менее здесь: simple-talk.com/community/blogs/tony_davis/ архив /
2009/08/06

1
@Hogan: представление, которое просто отражает базовую таблицу, не добавляет безопасности по сравнению с использованием базовой таблицы напрямую. Если вы присоединяетесь к таблице securityuser или маскируете некоторые столбцы, то это достаточно справедливо. Но ВЫБЕРИТЕ каждый столбец из таблицы или представления: без разницы. Лично я все равно использую хранимые процедуры.
ГБН

3
@Hogan: я знаю кое-что о SQL Server :-) stackoverflow.com/users/27535/gbn Я имею в виду, что GRANT SELECT по таблице ничем не отличается от GRANT SELECT ON VIEW, если представление SELECT * FROM TABLE
gbn

1
@gbn: я согласен. Там нет никакой разницы там. Я думаю, что мы могли бы сказать то же самое. Я предполагаю, что мой оригинальный комментарий («# 2 - это лучшая практика?») Основывался больше на моем личном опыте, что представления (например, триггеры) чаще используются неправильно, чем используются правильно. Таким образом, такая лучшая практика приведет только к злоупотреблению, а не к совершенствованию. Если это считается лучшей практикой, вы на 100% правы, это плохая практика.
Хоган

20

Дизайн моделей в основном. Они более и менее используются.


13
+1 Я до сих пор не понимаю, как Design Patterns - это красивые или элегантные решения. Это обходные пути для языковых недостатков, не более того.
Оливер Вейлер

2
Просто посмотрите на это как на искоренение языкового запаха с помощью самого языка.
Филипп Дупанович

15

Принцип единой ответственности

(«У каждого класса должна быть только одна ответственность; иными словами, у каждого класса должна быть одна и только одна причина для изменения»)

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

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

Представьте себе, если бы у создателей .Net API был такой менталитет: вместо List.Sort (), List.Reverse (), List.Find () и т. Д. У нас были бы классы ListSorter, ListReverser и ListSearcher!

Вместо того, чтобы больше спорить с SRP (что само по себе не страшно в теории) , я поделюсь некоторыми из моих давних анекдотических событий:


В одном месте, где я работал, я написал очень простое средство определения максимального потока, которое состояло из пяти классов: узла, графа, создателя графа, решателя графа и класса, чтобы использовать создателя / решателя графа для решения задачи. реальная проблема. Ни один из них не был особенно сложным или длинным (решатель был самым длинным в ~ 150 строк). Однако было решено, что у классов слишком много «обязанностей», поэтому мои коллеги приступили к рефакторингу кода. Когда они были сделаны, мои 5 классов были расширены до 25 классов, чьи строки кода были более чем в три раза больше, чем они были изначально. Поток кода больше не был очевиден, как и цель новых юнит-тестов; Теперь мне было трудно понять, что сделал мой собственный код.


В то же время почти у каждого класса был только один метод (его единственная «ответственность»). Следование потоку внутри программы было почти невозможно, и большинство юнит-тестов состояло из проверки того, что этот класс вызывал код из другого класса , оба из которых были для меня загадкой. Были буквально сотни классов, в которых (ИМО) должны были быть только десятки. Каждый класс делал только одну «вещь» , но даже с соглашениями об именах, такими как «AdminUserCreationAttemptorFactory» , было трудно определить связь между классами.


В другом месте (где также существовал менталитет « класс должен иметь только один метод» ), мы пытались оптимизировать метод, который занимал 95% времени во время определенной операции. После некоторой (довольно глупой) оптимизации его я переключил свое внимание на то, почему его называют баджиллионным разом. Он вызывался в цикле в классе ... чей метод вызывался в цикле в другом классе ... который также вызывался в цикле ...

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

Моя просьба о реорганизации этих 13 классов в один класс была отклонена.


6
Похоже, что кто-то получил "Лихорадка образца" или в этом случае "Лихорадка принципа" на этой работе. Класс списка не нарушает SRP. Все его функции служат одной цели, манипулируя коллекцией объектов. Мне кажется, что иметь в классе только одну функцию - это излишне. Принцип, лежащий в основе SRP, заключается в том, что единица кода (будь то метод, класс или библиотека) должна нести единственную ответственность, которая может быть изложена кратко.
Майкл Браун

3
Я начал видеть такое безумие от людей, которые считают невозможным писать чистый простой функциональный код. Слишком много просвещения, что каждая проблема в мире может быть решена из книги шаблонов. Не хватает мысли о прагматизме. Как и вы, я видел некоторый OO-код на основе классов, который настолько ужасен, что выполнить его совершенно невозможно. И его огромный и раздутый.
quick_now

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

«Представьте, что у создателей .Net API был такой менталитет: вместо List.Sort (), List.Reverse (), List.Find () и т. Д. У нас были бы классы ListSorter, ListReverser и ListSearcher !». Это именно то, что сделано в C ++, и это прекрасно . Алгоритмы отделены от структур данных, поэтому, если я напишу свой собственный контейнер, все алгоритмы, которые работают со стандартной библиотекой, просто работают с моим новым контейнером. Это должно быть ужасно в .Net land, писать новую функцию сортировки для каждого нового контейнера, который вы хотите отсортировать.
Манкарс

14

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

Кроме того, заменяя простые элементарные вещи, такие как

0 == memberArray.length

в классе с помощью вызова собственного метода класса, такого как

isEmpty()

это сомнительное "улучшение" ИМХО. Дополнение: Разница в том, что первая проверка делает именно то, что говорит: проверяет, равна ли длина массива 0. Хорошо, isEmpty()может проверить длину массива тоже. Но это также может быть реализовано так:

return null != memberArray ? 0 == memberArray.length : true;

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


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

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


6
Я редко вижу это как проблему. В основном это потому, что я обычно вижу слишком много в одном методе, а не слишком мало. Однако, согласно некоторым исследованиям, очень низкая сложность методов также имеет немного более высокую частоту ошибок, чем умеренно низкая сложность. enerjy.com/blog/?p=198
МВД

Да, это определенно проблема только в Чистом коде. В реальной жизни методы, как правило, слишком длинные, как вы сказали. Но интересно увидеть эту кривую! Действительно, все должно быть сделано как можно проще, но не проще.
Joonas Pulakka

1
Я считаю ваш второй пример более читабельным, и эта форма (или что-то похожее, например, свойство Length в самом классе) является обязательной, если вы делаете ее общедоступной.
Роберт Харви

@ Роберт Харви: Второй пример - хороший публичный метод, но вызов его изнутри самого класса сомнителен, потому что вы не знаете точно, что он делает, прежде чем посмотреть, как он реализован. Это может проверить на ноль, например. Смотрите мое дополнение выше.
Joonas Pulakka

@Joonas: Достаточно справедливо.
Роберт Харви

13

«Будьте либеральны с комментариями»

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


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

6
Я должен согласиться с тем, как сова выразил это. Чистый код предпочтительнее комментариев.
riwalk

4
Вам все еще нужно "почему" там!

Я бы предпочел комментарии, объясняющие почему. Это означает, что я должен меньше ДУМАТЬ при обратном проектировании намерений кода, когда прихожу посмотреть на него.
быстро,

12

GoTo считается вредным

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

Любая «лучшая практика», которая не допускает разумных и документированных исключений из ее правил, просто страшна.


16
Я продолжаю программирование в течение девяти лет без единого оператора goto (включая несколько конечных автоматов, как вы упомянули). Расширьте свой кругозор для новых идей.
riwalk

3
@Mathieu M. - согласен - смешивать GOTO со структурированными управляющими операторами нецелесообразно. (Это был чистый C, и это не было проблемой.
MZB

1
@ Stargazer2 - с помощью простого FSM зависит, дает ли состояние переменную состояние и использует его в качестве индекса для вызова процедуры (разве это не то же самое, что вычисляемый GOTO?), Дает более четкий / быстрый код, чем при использовании счетчика программы в качестве госслужащего. Я не защищаю это как лучшее решение в большинстве случаев, просто лучшее решение в некоторых обстоятельствах. Расширьте свой разум до альтернативных подходов.
MZB

5
@ MZB, не согласитесь ли вы, что вызов функции - это тоже просто вычисляемый GOTO? То же самое относится и к конструкциям / while / if / else / switch. Разработчики языка по какой-то причине абстрагируют прямые изменения в счетчике программы. Не используйте goto.
riwalk

3
Непосредственная реализация государственной машины, вероятно, является антипаттерном. Есть много способов иметь конечный автомат без буквального выражения состояний и переходов. например,import re
SingleNegationElimination

12

Мы приносим жертвы, чтобы сделать код тестируемым

Я прыгаю через много обручей, чтобы сделать мой код тестируемым, но я не претендую на то, что я бы не стал, если бы у меня был выбор. Однако я часто слышу, как люди выдвигают идею, что это «лучшие практики». Эти практики включают в себя (написано на языке .Net, но относится и к другим языкам) :

  • Создание интерфейса для каждого класса. Это удваивает количество классов (файлов) и дублирует код. Да, программирование интерфейса хорошо, но для этого предназначены публичные / приватные спецификаторы.
  • Каждый класс, который не создается при запуске, нуждается в фабрике. Понятно, что new MyClass()это намного проще, чем написать фабрику, но теперь метод, который ее создает, нельзя тестировать изолированно. Если бы не этот факт, я бы сделал только 1/20 числа фабричных классов, которые я делаю сейчас.
  • Сделайте все классы общедоступными, что лишает цели наличия спецификаторов доступа к классам вообще. Тем не менее, недоступные классы не могут быть доступны (и, следовательно, протестированы) из других проектов, поэтому единственный другой вариант - переместить весь код тестирования в тот же проект (и, таким образом, выпустить его вместе с конечным продуктом).
  • Внедрение зависимости. Ясно, что каждый другой класс, который я использую, использует поле, а параметр-конструктор - это значительно больше, чем просто создание их, когда они мне нужны; но тогда я больше не могу тестировать этот класс в изоляции.
  • Принцип Единой Ответственности, который вызвал у меня столько головных болей, что я перенес его в свой ответ .

Итак, что мы можем сделать, чтобы это исправить? Нам нужно радикальное изменение в языковой архитектуре:

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

Короче говоря, нам нужен язык, разработанный с нуля с учетом тестируемости .


Я полагаю, вы никогда не слышали о TypeMock ? Это позволяет издеваться над классами, рядовыми, статиками (фабриками), чем угодно.
Аллон Гуралнек

@Allon: у меня есть, но это далеко не бесплатно , что делает его не вариант для большинства людей.
BlueRaja - Дэнни Пфлюгофт

Если вам приходится писать множество фабричных классов, значит, вы делаете что-то не так. Библиотеки Smart DI (например, Autofac для C #) могут использовать Func <T>, Lazy <T>, Delegates и т. Д. Для фабрик, не создавая никаких шаблонов самостоятельно.
gix

10

Разделение приложений на уровни; Уровень данных, бизнес-уровень, уровень пользовательского интерфейса

Основная причина, по которой мне это не нравится, заключается в том, что большинство мест, которые следуют этому методу, используют очень хрупкие фреймворки для его выполнения. IE UI Layer кодируется вручную для работы с объектами бизнес-уровня, объекты бизнес-уровня кодируются вручную для работы с бизнес-правилами и базой данных, база данных является SQL и уже довольно хрупкая и управляется группой «DBA», которой не нравятся изменения.

Почему это плохо? Наиболее распространенным запросом на улучшение является, вероятно, «Мне нужно поле на экране X с Y». Взрыв! У вас просто есть новая функция, которая влияет на каждый слой, и если вы разделяете слои с разными программистами, это просто стало большой проблемой, затрагивающей несколько человек и группы, для очень простого изменения.

Кроме того, я не знаю, сколько раз я был в спорах, которые приводят что-то вроде этого. «Максимальная длина поля имени - 30, это уровень пользовательского интерфейса, бизнес-уровень или проблема уровня данных?» И есть сто аргументов, и нет правильного ответа. Ответ один и тот же, он влияет на все слои, вы не хотите, чтобы пользовательский интерфейс был немым, и вам нужно было пройти через все слои и потерпеть неудачу в базе данных, просто чтобы пользователь обнаружил, что его запись слишком длинная. Если вы измените его, это повлияет на все слои и т. Д.

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

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

Я, вероятно, получу удар за это, но это так :)


+1, звучит как мое последнее место работы до мельчайших деталей! Я уважаю многоуровневые приложения в принципе, однако слишком многие люди относятся к нему как к серебряной пуле, когда это не имеет смысла. Большинство бизнес-программ имеет потрясающе низкое количество бизнес-логики, и то, что у них есть, относительно просто. Это может сделать многоуровневую бизнес-логику кошмаром стандартного кода. Во многих случаях границы между доступом к данным и бизнес-логикой могут быть размытыми, потому что запрос - это бизнес-логика.
maple_shaft

... кроме того, большинство магазинов абсолютно не в состоянии распознать логику пользовательского интерфейса или логику представления. Поскольку они не понимают, насколько мало бизнес-логики существует в типичном приложении CRUD, они чувствуют, что должны делать что-то не так, когда большая часть их логики находится на уровне представления в качестве логики представления. Он ошибочно идентифицируется как бизнес-логика, а затем люди отправляют его на сервер для еще одного вызова сервера. Тонкий клиент может и должен иметь логику представления, например. (Скрыть textField2, если опция выбрана в dropDown3).
maple_shaft


7

Истории пользователей / Случаи использования / Персоны

 

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


7

80 знаков / строка ограничены

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

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

Конечно, есть редакторы CLI, неукоснительно используемые * nix динозаврами, которые следуют устаревшим ограничениям своих терминалов VT220, но почему остальные из нас придерживаются того же стандарта?

Я говорю, винт предел 80 символов. Если динозавры достаточно эпичны, чтобы взломать emacs / vim весь день, почему они не могут создавать расширение, которое автоматически оборачивает строки или предоставляет возможности горизонтальной прокрутки для их IDE CLI?

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

Ограничения в 80 символов не лучшая практика, но нишевая практика для очень небольшого числа программистов, и к ней следует относиться как к таковой.

Редактировать:

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

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


1
@ Orbling Хорошая логика GWB с ___ - злой угол. Итак, вы ненавидите hScroll, есть ли у вас веская причина, почему ширина col должна быть ограничена 80 символами? Почему не 160 или 256? Я думаю, что все мы можем предположить, что большинство разработчиков удалили свои терминалы VT220 и заменили их на puTTY, чтобы они в любом случае могли программно увеличивать ширину.
Эван Плейс

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

2
как бы вы распечатать это?

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

3
Отступ на 2 пробела. И используйте редактор с автоматическим трекером отступов. Я делал это годами, ничего страшного. (Emacs с правильными режимами помогает здесь.)
quick_now

5

Измерить, измерить, измерить

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

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


5

Мой учитель требует, чтобы я начинал все свои идентификаторы (не включая константы) строчными буквами, например myVariable.

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


9
У меня был учитель, которому требовался CamelCase, потому что он настаивал на том, что именно этим люди пользуются в реальном мире ... В то же время я программировал в двух разных группах на работе - обе группы настаивали на under_scores. Важно то, что использует ваша группа. Он мог бы определить себя в качестве ведущего программиста, и все было бы хорошо в моей книге - мы следуем его правилам - но он всегда высказывал свое мнение как «как все делается в реальном мире», как если бы не было другого действительного путь.
xnine

@xnine У меня пока недостаточно представителей на этом сайте, чтобы оценить ваш комментарий, поэтому я просто отвечу этим комментарием одобрения.
Maxpm

5
Верблюжий регистр (первая буква в нижнем регистре) является довольно распространенным соглашением, как и регистр Паскаля (первая буква каждого слова с заглавной буквы). В большинстве языков camelCase используется для закрытых / внутренних переменных, где PascalCase используется для классов, методов, свойств, пространств имен, открытых переменных. Это не плохая практика, чтобы привыкнуть просто быть готовым к проектам, которые могут использовать другую схему именования.
Эван Плейс

2
Просто к вашему сведению. Некоторые языки определяют значение того, является ли первая буква переменной заглавной или нет. В одном таком языке, если первая буква является заглавной, переменная рассматривается как константа - любая попытка изменить ее приведет к ошибке.
Берин Лорич

1
В Go открытые методы и члены в классах начинаются с заглавной буквы; частные с строчной буквы.
Джонатан Леффлер

5

Используйте синглтоны

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


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

1
@Paul Butcher: я ненавижу синглтоны, и их никогда не следует использовать

1
@ rwong: Лично я не думаю, что любая причина является законной причиной. Просто напишите это как обычный класс. На самом деле, нет причин использовать синглтон, кроме лени, и пропагандировать вредные привычки или дизайн.

6
Кто сказал, что использование Singeltons - лучшая практика?
Фил Мандер

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

5

Использование unsigned int в качестве итератора

Когда они узнают, что использование подписанного int намного безопаснее и менее подвержено ошибкам. Почему так важно, чтобы индекс массива мог быть только положительным числом, чтобы все были рады игнорировать тот факт, что 4 - 5 - это 4294967295?


Хорошо, теперь мне любопытно - почему ты так говоришь? Я чувствую себя немного глупо - не могли бы вы привести примеры кода для поддержки ваших утверждений?
Пол Натан

4
@Paul Натан: что касается ошибки, вот один пример: for (unsigned int i = 0; i <10; i ++) {int crash_here = my_array [max (i-1,0)];}
AareP

@AareP: Чтобы быть уверенным - я предполагаю, что вы ссылаетесь на тот факт, что когда unsigned int 0уменьшается на 1, вы фактически получаете максимальное положительное значение, которое может хранить unsigned int?
Адам Пейнтер

1
@ Адам Пейнтер: да. Это может показаться нормальным для программистов на c ++, но давайте посмотрим правде в глаза, "unsigned int" - это одна из "плохих" реализаций "только положительных чисел".
AareP

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

4

Методы не должны быть длиннее одного экрана

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

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

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

Вот мое правило ...

Напишите функции / методы для достижения чего-либо

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

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

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

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

Ограничьте ненужные абстракции и не загрязняйте автозаполнение.


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

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

1
@ Джереми Как? Каким образом абстрагирование фрагмента кода и помещение его в собственный метод делает его более читабельным, чем просто размещение однострочного комментария в верхней части фрагмента кода, описывающего, что он делает? Предполагая, что этот блок кода используется только один раз в этом разделе кода. Является ли это на самом деле , что трудно для большинства программистов , чтобы разложить рабочие части кода , пока они читают его и / или разместить несколько однострочный комментарий , чтобы напомнить им , что он делает , если они не могут?
Эван Плейс

4
@Evan: Помещение частей кода в функции эффективно дает им имя , надеюсь, хорошо объясняя, что делает этот кусок кода. Теперь, где бы ни вызывался этот фрагмент кода, вы можете видеть имя, объясняющее, что делает код , вместо того, чтобы анализировать и понимать сам алгоритм. Если все сделано правильно, это может значительно облегчить чтение и понимание кода.
ВОО

1
+1, и я бы дал больше, если бы мог. Нет ничего плохого в куске кода на C, который состоит из 1000 строк в одной функции (например, синтаксический анализатор с массивным переключателем ()), ПРЕДОСТАВЛЯЯ, что цель ясна и проста. Уничтожение всех маленьких кусочков и вызов их просто усложняет понимание. Конечно, этому тоже есть пределы ... разумное суждение - это все.
fast_now
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.