В блоге на этой неделе о Чистом коде я немного расскажу о классах. Хотя объектно-ориентированное программирование (ООП) само по себе является чрезвычайно обширной темой, в которую я не могу вникать слишком глубоко, на данный момент достаточно сказать, что объекты - это фрагменты кода, которые позволяют нам хранить данные и работать с ними. . Используя ООП, мы скрываем детали наших программ, что делает наш код более гибким, модульным и абстрактным. ООП очень полезно при написании больших программ, особенно в случае совместной работы над надежным приложением.
Как и в случае с любым другим кодом, который мы пишем, у нас больше шансов на успех, если мы поддерживаем наш код в чистоте, и у дяди Боба есть несколько полезных рекомендаций, которые помогут нам сделать это для классов. Чтобы понять некоторые из этих моментов при написании чистых классов, мы спроектируем парковку на JavaScript. Когда мы закончим, у нас будет лучшее представление о функциональных возможностях, которые дают нам классы, а также о том, как поддерживать их в чистоте. Я хочу отметить, что есть некоторые концепции ООП, которые просто выходят за рамки этого сообщения в блоге, в частности Инкапсуляция, Принцип открытого-закрытого (OCP) и Принцип инверсии зависимостей (DIP). Хотя мы не будем здесь подробно обсуждать эти вопросы, связанные статьи дадут вам более широкое представление о классах.
Дизайн парковки
Скажем откровенно: вы, наверное, никогда раньше не проектировали парковку. Не позволяйте этому относительно распространенному вопросу на собеседовании удерживать вас. Начнем с выяснения некоторых предположений об указанной парковке. Хорошие вопросы о разработке этой системы могут включать:
- Какие автомобили разрешено парковать на стоянке?
- Есть ли у участка несколько уровней?
- Может ли небольшой автомобиль поместиться в пространстве, предназначенном для более крупного транспортного средства?
- Могут ли одновременно въезжать на стоянку более одного автомобиля?
Уточняя предположения относительно участка, мы получаем лучшее представление о том, как эта система должна работать, что позволит нам построить более эффективную парковку в целом. Чтобы избавить себя от множества дискуссий о том, как спроектировать парковку в коде, мы возьмем пример из этой замечательной публикации StackExchange:
Класс Spot
:
ParkingLotManager
класс:
Классы Vehicle
, Motorcycle
, Car
и Truck
:
Теперь, когда у нас построены следующие классы, мы можем создавать их новые экземпляры и выполнять с ними операции. Например, если мы создадим следующие объекты:
Наша программа дает нам следующий результат:
Опять же для целей этого блога я не буду вдаваться в подробности о полезности ООП. А пока я просто скажу, что ООП позволяет нам модулировать наши программы, разбивая их на все более мелкие части, уменьшая сложность и облегчая устранение ошибок. Поскольку это очень важная концепция для того, чтобы стать компетентным инженером-программистом, важно, чтобы мы могли содержать наши классы в чистоте. Посмотрим, какие рекомендации дает нам дядя Боб.
Классы должны быть небольшими
Как пишет Мартин: «Первое правило классов - они должны быть маленькими. Второе правило классов - они должны быть меньше ». Если это звучит так, как будто Мартин и его соавтор повторяют свои рекомендации по размеру функции, это так. Как и функции, классы должны быть компактными и модульными. Однако вместо того, чтобы измерять размер класса по количеству занимаемых ими строк, как мы это делали бы с функциями, мы измеряем размер класса по количеству возложенных на него обязанностей. Давайте посмотрим на один из наших классов сверху:
Как мы видим, класс Motorcycle
невелик как по количеству занимаемых им строк, так и по количеству выполняемых им обязанностей. Мы знаем, что Motorcycle
наследует свойство id
от класса Vehicle
и имеет атрибут, определяющий его размер. Как и в случае с функциями, мы предоставляем больше возможностей для появления ошибок, чем сложнее становится класс. И наоборот, мы делаем классы чище, сокращая их.
Один из способов уменьшить размер классов - это дать им описательные имена. Если вы помните из нашего обзора главы Чистый код, посвященной Именам, мы должны позаботиться о том, чтобы обозначения наших объектов были ясными и значимыми. Вам не понадобится множество комментариев, чтобы описать обязанности класса. Чтобы взять конкретный пример из нашей системы классов парковки:
Truck
класс ясно указывает, чего мы ожидаем от этого класса. Просто взглянув на названия, мы можем увидеть, что грузовик - это тип транспортного средства, а его размер - одна из его определяющих характеристик. Хотя я знаю, что некоторые из приведенных выше фрагментов кода нарушают это правило, в целом классы Motorcycle
, Car
и Truck
демонстрируют, насколько маленькими должны быть классы.
Принцип единой ответственности
Одна из основных концепций ООП и дизайна программного обеспечения в целом, Принцип единой ответственности (SRP) гласит, что у класса или модуля должна быть одна, единственная причина для изменения. Если у класса слишком много обязанностей, вы можете провести рефакторинг части своего кода и забыть, что какой-то метод все еще работает с другой частью логики в вашей кодовой базе. Имея обширные, всеобъемлющие классы, сложно поддерживать порядок в коде. Например, давайте вернемся к нашему классу ParkingLotManager
:
Хорошо, ParkingLotManager
явно немного раздут. Во-первых, в 40 строк он просто занимает значительный объем места в нашей программе. Но что еще более важно, мне кажется, что мы слишком много полагаемся на ParkingLotManager
, чтобы эффективно управлять нашей системой. В настоящее время ParkingLotManager
необходимо отслеживать размер пространства и определять, следует ли добавить или удалить транспортное средство. В лучшем дизайне системы можно экстраполировать метод _getSizeIndex
из класса ParkingLotManager
, отделив эти проблемы и упростив понимание нашей программы.
Вы можете подумать, что создание слишком большого количества классов имеет свои недостатки. Вы спросите, действительно ли я сэкономлю себе время, если мне придется прокручивать экран компьютера вверх и вниз, просматривая десятки небольших классов, чтобы иметь возможность нащупать всю программу? Тем не менее, Мартин говорит нам, что несколько небольших классов могут иметь столько же движущихся частей, сколько несколько больших классов, и мы, вероятно, достигли бы наших целей более эффективно, если бы организовали наши инструменты в чистый, организованный набор инструментов с достаточным количеством меток для этих инструментов. Если SRP вам не нравится, это сообщение в блоге дает хорошее объяснение, как будто я 5 объяснений по теме.
В главе о классах Чистый код есть отличное отступление, где Мартин обсуждает, почему чистый код настолько редок. «Слишком многие из нас, - утверждает Мартин, - думают, что мы закончили (писать код), как только программа заработает». Как Чистый код снова и снова повторяет, написание кода, понятного компьютеру, - это только часть битвы. Настоящая проблема программирования заключается в написании программ, понятных людям.
Как и системы в реальном мире, компьютерные программы меняются. В наши системы вписываются новые рамки и / или логика, при этом накапливается технический долг. Как разработчики наших систем, каждое изменение, которое мы вносим, подвергает нас риску того, что система больше не будет полностью функциональной. Однако при написании чистого кода мы снижаем риск того, что эти программы - и наша команда - потерпят неудачу. Я надеюсь, что вы нашли этот блог полезным для понимания объектно-ориентированного дизайна и того, как можно писать чистые классы.