Advertisement
  1. Code
  2. Tools & Tips

3 Основных принципа программного обеспечения, которые вы должны понимать

Scroll to top
Read Time: 17 mins

Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)

Если вы занимаетесь разработкой программного обеспечения, то заметили уже, что все время появляются новые методы, языки и концепции. Мы все время чувствуем эти ворчащие сомнения: «Могу ли я идти в ногу с изменениями и оставаться конкурентоспособными?» Потратьте минутку и суммируйте линию из моего любимого фильма, Касабланка: «Фундаментальные вещи применяются со временем».

Переизданный учебник

Каждые несколько недель мы пересматриваем некоторые любимые статьи наших читателей на протяжении всей истории сайта. Этот учебник был впервые опубликован в апреле 2012 года.

То, что верно для любви, верно для кода.

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


Принцип - не повторяйте себя

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

Этот принцип настолько важен для понимания, что я не буду писать его дважды! Его обычно называют аббревиатурой DRY, и он появился в книге «Прагматический программист» Энди Ханта и Дейва Томаса, но сама концепция была известна уже давно. Она относится к наименьшим частям вашего программного обеспечения.

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

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

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

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

У них должно быть одно представление внутри него.

Каждая часть знания должна иметь единое, недвусмысленное, авторитетное представление внутри системы.

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

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

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

Архитектура программного обеспечения связана с управлением сложностью.

Достижение DRY

DRY - это философия, которая объединяет логику в представления.

Существует много способов достижения DRY. Хант и Томас предложили (помимо прочего) генераторы кода и преобразование данных. Но, судя по всему, DRY - это философия, которая объединяет логику в представления.

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

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

  • Сделайте визуальную иерархию своего программного приложения и сопоставьте с ней основные компоненты. Для сложных проектов может потребоваться выделенная карта для каждого компонента.
  • Если вы достигли уровня связанных обязанностей, вы можете переключиться на UML-диаграммы (или аналогичные).
  • Прежде чем писать фрагмент кода, назовите его иерархию в своем программном проекте. Определите, что он представляет, и убедитесь, что знаете его роль в окружающем компоненте.
  • Определите, какое представление должно быть представлено другим частям (например, функции для выполнения SQL в драйвере базы данных) и что он должен скрывать (например, учетные данные базы данных).
  • Убедитесь, что представления не полагаются на представления другого уровня сложности (например, компонент, который полагается на класс в другом компоненте).

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

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

В реальном мире трудно, если не невозможно, достичь приложения, которое является 100% DRY. Тем не менее, приложения, которые не являются DRY в неприемлемой степени и, следовательно, их трудно поддерживать, - довольно распространенное явление. Следовательно, неудивительно, что более 50% всех программных проектов терпят неудачу - если вы посмотрите на код.

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

Плохой код редко производится плохими программистами.

Пример

DRY достигается благодаря хорошему планированию.

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

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

Существует причина, по которой наиболее успешные корпорации в ИТ-бизнесе были основаны людьми с очень хорошим техническим пониманием - или даже самими программистами: Билл Гейтс, Марк Цукерберг, Стив Возняк, Стив Джобс, Ларри Пейдж, Сергей Брин и Ларри Эллисон знают, какие усилия необходимы для реализации чего-то. Напротив, многие компании склонны закладывать требования к инженерному делу в руки менеджеров по учетным записям, а также отдавать концептуальную часть в руки бизнес-консультантов ... людей, которые никогда ничего не реализовали.

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

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

Если у вас есть свой подход к работе, продолжайте читать! Тебе не понадобится это, этот принцип придет на помощь.


Принцип - Держите вещи простыми и глупыми

Простейшее объяснение имеет тенденцию быть правильным.

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

Сотрудник швейцарского патентного ведомства Альберт Эйнштейн предложил избавиться от всей теории эфира, когда он представил простую, но революционную идею: все странности при расчете с большими расстояниями исчезнут, если мы согласимся, что время не Константа; Это относительно. Это невероятное мышление, стало простым объяснением с минимальными предположениями о выборе между конкурирующими сценариями, называется «Бритва Оккама».

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

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

HTTP

Hypertext Transfer Protocol считается прекрасным примером простого решения: предназначен для передачи документов на основе гипертекста, и он является основой высокоинтерактивных приложений для настольных компьютеров в настоящее время. Может быть, нам нужно найти решения для ограничений в протоколе, и, возможно, нам придется что-то заменить. Однако статус-кво: на основе нескольких методов запроса (например, GET и POST), кодов состояния и аргументов открытого текста, HTTP оказался гибким и надежным. Вот почему HTTP неоднократно подталкивался к своему пределу веб-разработчиками - и по-прежнему он на своем месте.

Мы принимаем этот подход как должное, но история разработки и стандартизации программного обеспечения полна чрезмерно сложных решений. Для этого есть даже специальное слово: bloatware. Программное обеспечение, подобное этому, также описано как DOD, мертвое по прибытии. У меня есть теория, которая очень похожа на мою теорию кода неDRY, когда дело доходит до bloatware ... Однако успех Интернета можно охарактеризовать как успех простых, но эффективных решений.

Итак, что требуется, чтобы прийти к самому простому решению? Все сводится к возможности поддерживать приложение и понятности при разработке программного обеспечения. Следовательно, KISS входит в игру на этапе разработки требований. Когда вы думаете о том, как преобразовать требования клиента к реализуемым компонентам, попробуйте определить следующие части:

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

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

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

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

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


Принцип - вам «не это понадобится»

Программирование касается создания вещей.

Когда был запущен Google+, Марк Цукерберг, основатель Facebook, был одним из первых, кто создал учетную запись в социальной сети, которая стремилась забрать его клиентов у его собственной. Он добавил только одну строку в раздел «Обо мне»: «Я создаю вещи». Я честно считаю, что это блестящее предложение, потому что оно описывает чистую сущность кодирования несколькими простыми словами. Почему вы решили стать кодером? Энтузиазм в отношении технических решений? Красота эффективности? Независимо от вашего ответа, это врятли будет «создание 1.000.001-го корпоративного сайта со стандартной функциональностью». Тем не менее, большинство из нас делает деньги именно таким образом. Независимо от того, где вы работаете, вы, вероятно, время от времени будете сталкиваться с скучными и повторяющимися задачами.

80% времени, затраченного на программный проект, инвестируется в 20% функциональности.

Принцип вам это не понадобится (YAGNI), как раз занимается этими задачами. В основном это означает: если это не концепция, это не должно быть в коде. Например, распространенной практикой является абстрагирование доступа к базе данных в слое, который обрабатывает различия между различными драйверами, такими как MySQL, PostgreSQL и Oracle. Если вы работаете на корпоративном веб-сайте, размещенном на стеке LAMP, на общем хосте, какова вероятность, что они изменят базу данных? Помните, что концепция была написана с учетом бюджета.

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

Возможно, вы заметили, разницу вам это не понадобится и модульной архитектуры DRY: последнее снижает сложность, деля проект на управляемые компоненты, в то время как первое снижает сложность за счет сокращения количества компонентов. YAGNI похож на принцип KISS, поскольку он стремится к простому решению. Однако KISS стремится к простому решению, пытаясь реализовать что-то как можно проще; YAGNI стремится к простоте, не реализуя это вообще!

Теодор Стерджон, американский научно-фантастический автор, заявил закон, гласаящий что: «девяносто процентов всего - это дерьмо». Это очень радикальный подход и он не слишком полезен в реальных проектах. Но имейте в виду, что «дерьмо» может быть очень трудоемким. Хорошее эмпирическое правило: примерно 80% времени, затраченного на программный проект, инвестируется в 20% функциональности. Подумайте о своих проектах! Каждый раз, когда я это делаю, меня удивляет точность правила 80:20.

80% затрат времени на программный проект инвестируется в 20% функциональности.

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

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

Планирование проекта

Когда вы готовите свой список дел для проекта, рассмотрите следующие мысли:

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

Окунемся немного в детали! Я уже представил пример для первого элемента в списке: не переносите драйвер базы данных вокруг уровня абстракции базы данных. Будьте подозрительны ко всему, что добавляет сложности вашему стеку программного обеспечения. Обратите внимание, что абстракция часто предоставляется сторонними библиотеками. Например, в зависимости от вашего языка программирования уровень хранения данных, такой как Hibernate (Java), Doctrine (PHP) или Active Record (Ruby), содержит абстракцию базы данных и объектно-реляционное сопоставление. Каждая библиотека добавляет сложности. Которая должна поддерживаться. Необходимо применять обновления, патчи и фиксы безопасности.

Мы реализуем функции каждый день, потому что мы ожидаем что они будут полезны. Следовательно, мы думаем заранее и реализуем слишком много всего. Например, многие клиенты хотят иметь мобильный сайт. Mobile - это очень широкий термин; Это не дизайнерское решение. Это сценарий действия! Люди, которые используют мобильный сайт, скажем что они мобильны. Это означает, что они могут захотеть получить доступ к другой информации или функциям, в отличие от пользователя, который посещает сайт, открытый на рабочем столе. Подумайте о сайте кино: пользователи на автобусе, скорее всего, захотят получить доступ к стартовому времени предстоящих фильмов, а не к трейлеру на 50 МБ.

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

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

Нефункциональные требования не описывают поведение программного обеспечения, они описывают дополнительные свойства, которые могут использоваться для оценки качества программного обеспечения. Поскольку описание качества программного обеспечения предполагает знание о программном обеспечении, плохие концепции часто можно определить из-за отсутствия нефункциональных требований. Поддержание работоспособности, уровень документации и простота интеграции являются примерами нефункциональных требований. Нефункциональные требования должны быть измеримыми. Следовательно, требование «страница должна загружаться быстро» слишком размытое. "Страница должна загружаться в течение двух секунд максимум во время теста средней производительности" - очень конкретный пример, поддающийся измерению. Если вы хотите применить принцип YAGNI, используйте умеренные нефункциональные требования, если они не упоминаются в концепции (или если они упомянуты, но небезопасны). Если вы сами пишете нефункциональные требования, будьте реалистичны: небольшая корпорация с посещением 20-50 страниц в день не требует трех дней настройки производительности - поскольку страница должна загружаться достаточно быстро, потому что сервер не занят. Если корпорация может увеличить количество ежедневных посещений, лучший сервер или пакет хостинга не будут слишком дорогими.

И последнее, но не менее важное, помните правило 80:20!

И последнее, но не менее важное, помните правило 80:20! Мы должны идентифицировать трудоемкие детали. Если какая-либо часть абсолютно необходима, вы должны ее реализовать. Вопрос должен быть: как вы это реализуете? Должен ли это быть самый последний фреймворк с небольшим сообществом? Нужно ли вам переключиться на только что выпущенную версию библиотеки, если ее документация еще даже не обновлена? Следует ли использовать новую CMS, если пока доступны не все расширения? Сколько исследований потребуется для этого? «Так мы всегда это делали». Это не захватывающий подход, но он будет работать без сюрпризов.

Важно понимать, что все это не означает, что вы можете начать писать грязный код с использованием хаков! Вы пишете легкое приложение, а не грязное! Однако вам это не понадобится является практическим подходом. Если это приведет к тому, что уберуться многие ненужные строки кода, я лично считаю, что вы можете связать усилия с бюджетом, привести свой проект в порядок согласно принципу DRY. Это небольшое приложение. Следовательно, добавленная сложность обслуживания приемлема. Мы в реальном мире.

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

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

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


Заключение

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

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.