![Что является злейшим врагом программирования?](https://hackernoon.imgix.net/images/eQHzh6rz7ETBHLjs0KzCl1Dooqp2-1x832xd.jpeg)
Что является злейшим врагом программирования?
18 февраля 2024 г.Изображение создано с помощью инструмента искусственного интеллекта DALL·E 3 — у автора есть происхождение и авторские права.
Что такое программирование? Это письменный набор инструкций (программ), которые будет выполнять машина. Итак, можно сказать, что программист является «создателем» кода, но кто является его «пользователем»? Может машина? Нет, это не машина.
Машина не понимает современные языки программирования высокого уровня; в стандартных случаях программы, написанные на таких языках, «переводятся» в инструкции низкого уровня с помощью компиляторов. «Пользователями» кода являются другие программисты. Программирование — это групповой вид спорта.
В одиночку вы можете писать простые или даже сложные программы, но если вы хотите создать передовое программное обеспечение корпоративного уровня, которое можно будет надежно разрабатывать и использовать, вам нужно больше программистов, которые будут работать вместе в командах.
Таким образом, в большинстве случаев многие программисты, организованные в группы, активно модифицируют код на протяжении всего цикла разработки. По этой причине современный подход к программированию заключается в том, чтобы писать код больше для коллег, а не для машины. Этот сдвиг в перспективе делает программирование более ориентированным на написание понятного кода, который должен работать так, как ожидается.
Код должен быть простым для понимания человеком. Что является самым большим врагом понимания? Это сложность. Имея это в виду, давайте рассмотрим некоторые известные принципы/правила программирования, которые обещают справиться со сложностью, а именно:
Лучшие практики и принципы программирования — это рекомендации и правила, которые помогают разработчикам писать эффективный, читаемый, поддерживаемый и масштабируемый код. Эти методы необходимы отдельным разработчикам и командам для создания высококачественного программного обеспечения.
Вот некоторые из наиболее широко признанных лучших практик и принципов программирования:
* Пишите читаемый код: используйте осмысленные имена переменных и функций. Следуйте единообразному стилю и соглашениям кодирования. Комментируйте свой код там, где это необходимо, чтобы объяснить, «почему» что-то делается, а не «что» делается, поскольку последнее должно быть очевидно из самого кода.
* Сохраняйте простоту (KISS): стремитесь к простоте в своих проектах. Избегайте чрезмерного проектирования и реализации ненужных функций.
* Не повторяйтесь (СУХОЙ): избегайте дублирования кода. Используйте функции, классы и модули для инкапсуляции многократно используемой логики.
* Регулярно проводите рефакторинг: постоянно совершенствуйте кодовую базу путем рефакторинга старого или неэффективного кода.
* Используйте шаблоны проектирования с умом: шаблоны проектирования предоставляют решения распространенных проблем. Понимайте и применяйте их там, где это необходимо, но не принуждайте к их использованию.
* Документируйте свой код и используйте его. Напишите документацию для своего кода и способов использования вашего программного обеспечения, что имеет решающее значение для пользователей и будущих разработчиков.
* ТВЕРДЫЕ Принципы: * Принцип единой ответственности (SRP): у класса должна быть одна и только одна причина для изменения.
-
<ли>
Принцип открытости/закрытости (OCP): программные объекты должны быть открыты для расширения, но закрыты для модификации.
* Принцип замены Лискова (LSP): объекты в программе следует заменять экземплярами их подтипов без нарушения корректности программы.
* Принцип разделения интерфейсов (ISP): многие клиентские интерфейсы лучше, чем один интерфейс общего назначения.
* Принцип инверсии зависимостей (DIP): Зависите от абстракций, а не от конкретики.
* Не заставляйте меня думать: сделайте код максимально интуитивным, уменьшив усилия, необходимые для его понимания.
* YAGNI (вам это не понадобится): не добавляйте функциональность до тех пор, пока она не станет необходимой.
Эти принципы хорошо звучат на бумаге, и если их использовать с умом, они действительно могут замедлить скорость роста сложности вашего кода. Помните, сложность всегда ваш хозяин. В разработке программного обеспечения по мере того, как проект растет и добавляется все больше и больше функций, вы можете замедлить усложнение, но никогда не остановить его.
Большинство разработчиков учатся этому на собственном горьком опыте. Исходя из моей практики, такие принципы/советы/правила следует применять в каждом конкретном случае и в зависимости от контекста.
Я видел, как многие старшие программисты применяли такие методы независимо от контекста и случая, и в результате и без того сложная кодовая база усложнялась.
Например, давайте подробнее рассмотрим наше излишне сложное приложение-калькулятор.
OverEngineeredCalculator/
│
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ ├── com/
│ │ │ │ ├── overengineeredcalculator/
│ │ │ │ │ ├── calculator/
│ │ │ │ │ │ ├── core/
│ │ │ │ │ │ │ ├── CalculatorEngineInterface.java
│ │ │ │ │ │ │ ├── CalculatorEngineImpl.java
│ │ │ │ │ │ │ ├── OperationStrategyInterface.java
│ │ │ │ │ │ │ ├── OperationFactoryInterface.java
│ │ │ │ │ │ │ ├── OperationFactoryImpl.java
│ │ │ │ │ │ │ ├── CalculatorContextInterface.java
│ │ │ │ │ │ │ ├── CalculatorContextHolder.java
│ │ │ │ │ │ ├── operations/
│ │ │ │ │ │ │ ├── base/
│ │ │ │ │ │ │ │ ├── Operation.java
│ │ │ │ │ │ │ │ ├── OperationImpl.java
│ │ │ │ │ │ │ │ ├── ValidatorInterface.java
│ │ │ │ │ │ │ │ ├── ValidatorImpl.java
│ │ │ │ │ │ │ ├── addition/
│ │ │ │ │ │ │ │ ├── AdditionStrategyInterface.java
│ │ │ │ │ │ │ │ ├── AdditionStrategyImpl.java
│ │ │ │ │ │ │ │ ├── AdditionValidatorInterface.java
│ │ │ │ │ │ │ │ ├── AdditionValidatorImpl.java
│ │ │ │ │ │ │ ├── subtraction/
│ │ │ │ │ │ │ │ ├── SubtractionStrategyInterface.java
│ │ │ │ │ │ │ │ ├── SubtractionStrategyImpl.java
│ │ │ │ │ │ │ │ ├── SubtractionValidatorInterface.java
│ │ │ │ │ │ │ │ ├── SubtractionValidatorImpl.java
│ │ │ │ │ │ │ ├── multiplication/
│ │ │ │ │ │ │ │ ├── MultiplicationStrategyInterface.java
│ │ │ │ │ │ │ │ ├── MultiplicationStrategyImpl.java
│ │ │ │ │ │ │ │ ├── MultiplicationValidatorInterface.java
│ │ │ │ │ │ │ │ ├── MultiplicationValidatorImpl.java
│ │ │ │ │ │ │ ├── division/
│ │ │ │ │ │ │ │ ├── DivisionStrategyInterface.java
│ │ │ │ │ │ │ │ ├── DivisionStrategyImpl.java
│ │ │ │ │ │ │ │ ├── DivisionValidatorInterface.java
│ │ │ │ │ │ │ │ ├── DivisionValidatorImpl.java
│ │ │ │ │ ├── ui/
│ │ │ │ │ │ ├── framework/
│ │ │ │ │ │ │ ├── UIFrameworkInterface.java
│ │ │ │ │ │ │ ├── UIFrameworkImpl.java
│ │ │ │ │ │ │ ├── UIElementFactoryInterface.java
│ │ │ │ │ │ │ ├── UIElementFactoryImpl.java
│ │ │ │ │ │ ├── console/
│ │ │ │ │ │ │ ├── ConsoleUIInterface.java
│ │ │ │ │ │ │ ├── ConsoleUIImpl.java
│ │ │ │ │ │ ├── gui/
│ │ │ │ │ │ │ ├── SwingUIInterface.java
│ │ │ │ │ │ │ ├── SwingUIImpl.java
│ │ │ │ │ │ │ ├── JavaFXUIInterface.java
│ │ │ │ │ │ │ ├── JavaFXUIImpl.java
│ │ │ │ │ │ │ ├── GUIFactoryInterface.java
│ │ │ │ │ │ │ ├── GUIFactoryImpl.java
│ │ │ │ │ ├── utils/
│ │ │ │ │ │ ├── LoggerInterface.java
│ │ │ │ │ │ ├── LoggerImpl.java
│ │ │ │ │ │ ├── ConfigLoaderInterface.java
│ │ │ │ │ │ ├── ConfigLoaderImpl.java
│ │ │ │ │ │ ├── ValidatorInterface.java
│ │ │ │ │ │ ├── ValidatorImpl.java
│ │ │ │ │ ├── exceptions/
│ │ │ │ │ │ ├── CustomExceptionBase.java
│ │ │ │ │ │ ├── InvalidInputException.java
│ │ │ │ │ │ ├── OperationNotSupportedException.java
│ │ │ │ │ ├── integration/
│ │ │ │ │ │ ├── ExternalServiceAdapterInterface.java
│ │ │ │ │ │ ├── ExternalServiceAdapterImpl.java
│ │ │ │ │ │ ├── HistoryRecorderInterface.java
│ │ │ │ │ │ ├── HistoryRecorderImpl.java
│ │ ├── resources/
│ │ │ ├── config.properties
│ │ │ ├── logging.properties
│ ├── test/
│ │ ├── java/
│ │ │ ├── com/
│ │ │ │ ├── overengineeredcalculator/
│ │ │ │ │ ├── calculator/
│ │ │ │ │ │ ├── CalculatorEngineTest.java
│ │ │ │ │ │ ├── OperationFactoryTest.java
│ │ │ │ │ ├── operations/
│ │ │ │ │ │ ├── addition/
│ │ │ │ │ │ │ ├── AdditionStrategyTest.java
│ │ │ │ │ │ ├── subtraction/
│ │ │ │ │ │ │ ├── SubtractionStrategyTest.java
│ │ │ │ │ │ ├── multiplication/
│ │ │ │ │ │ │ ├── MultiplicationStrategyTest.java
│ │ │ │ │ │ ├── division/
│ │ │ │ │ │ │ ├── DivisionStrategyTest.java
Это приложение служит ярким примером чрезмерного проектирования, когда применение таких принципов, как SRP и ISP, а также чрезмерное количество интерфейсов и реализаций для простых операций привело к раздутой структуре, которая скорее скрывает основные функции. чем улучшить его.
Чтобы эффективно бороться со сложностью:
Сохраняет как можно меньшее количество файлов/модулей/пакетов проекта. Очень важно критически оценивать необходимость каждого компонента в вашем проекте.
Объединение функций там, где это имеет смысл, может значительно снизить когнитивную нагрузку для новых разработчиков, присоединяющихся к проекту.
Подумайте об удалении кода, а не о добавлении его.
Примените рефакторинг с целью упрощения. Прежде чем добавлять новую функцию или рефакторить существующую, оцените общее влияние на сложность проекта. Иногда лучший код — это не написанный код.
Всегда нарушайте «лучшие практики», если это упростит ваш код.
Контекст имеет решающее значение. Если придерживаться определенного принципа или практики не имеет смысла в вашей конкретной ситуации, разумно отклониться. Целью всегда должно быть сохранение простоты и ясности, даже если это означает отказ от общепринятых представлений.
Критически изучив пример с калькулятором, мы можем извлечь ценные уроки о подводных камнях чрезмерного проектирования. Такой образ мышления поможет вам устранить мертвый код и вознаградит вас компактной и простой для понимания кодовой базой.
Великие инженеры-программисты стремятся к простоте, а не к сложности, понимая, что самые элегантные решения часто являются самыми простыми.
Также опубликовано здесь
Оригинал