что значит чистый код
Чистый код: причины и следствия
Автор: Виктор Свирский, Senior Python Developer / Team Lead, DataArt
Сколько программистов, столько и определений, что такое чистый код. Часто, проводя собеседование, я слышу, что хороший код — это такой, который легко читается. Согласен, но как подсказывает мой личный опыт, это только вершина айсберга.
Первый звоночек, который нам сообщает, что код перестает быть чистым — это рост времени разработки новой функциональности и увеличение регрессионного скоупа при малейшем изменении в системе. Это следствие того, что технический долг накапливается, компоненты в системе очень тесно связаны, автотесты отсутствуют. Причины этого могут быть:
Что такое чистый код?
Получается, чтобы сказать, что код чистый и система спроектирована грамотно, легкого чтения кода недостаточно. Он должен обладать и другими качествами:
Стоит ли писать чистый код?
Однозначно стоит! Но не всегда и не везде стоит уделять чистоте слишком много внимания.
Не стоит забывать о целесообразности и сроке жизни вашего кода. Например, если перед вами стоит задача разработки концепции — PoC (Proof of concept), и вы доказываете, что выбранный стек технологий выполняет поставленную задачу, ваш код станет неактуален уже через неделю или две. Не стоит тратить силы на совершенствование этого функционала.
Бытует мнение, что не нужно следить за качеством кода или части системы, которые в скором времени будут заменены. И это неверно по нескольким причинам. Высокое качество исполнения сделает переход или интеграцию с новыми частями более простыми, бесшовными и быстрыми. Оно наверняка упростит жизнь в тех случаях, когда несколько версий кода придется поддерживать одновременно. Количество регрессионных ошибок с чистым кодом будет в разы меньше. Также не стоит забывать, что нет ничего более постоянного, чем временное. Возможно, задачи по улучшению этой части кода еще несколько месяцев будут лежать в бэклоге.
Что поможет улучшить ваш код?
Большинство программистов мечтают писать код быстро и максимально красиво, причем так, чтобы все идеально работало с первого раза. Но далеко не каждому удается сделать код не просто работающим, но и понятным. Как же добиться успеха в написании чистого кода? Есть два пути — самоорганизация и командная работа.
Самоорганизация
Рассмотрим несколько возможных способов улучшить индивидуальное качество кода. Эти рекомендации подойдут разработчику любого уровня.
Не спешите решать задачи в лоб. Задавайте вопросы старшим разработчикам и самому себе. Всегда важно понимать причинно-следственную связь тех или иных решений. Хорошо понимая проблему, вы сможете эффективно ее решить.
Любой опыт лучше, чем его отсутствие.
Командная работа
Большинство задач решается в команде. Очень важно разделять ответственность за качество между ее участниками. Чем больше команда, тем сложнее поддерживать продукт в хорошем состоянии. Рассмотрим несколько подходов удержания кода в вышеуказанных условиях.
Во время проверки кода необходимо учитывать несколько вещей:
Суть непрерывной интеграции в том, что она позволяет быстро получить множество отзывов о текущем состоянии кода.
Непрерывная интеграция работает, когда вы следуете двум простым правилам:
Важно иметь список соглашений о кодировании. Но прежде чем вы начнете составлять список, все в команде должны понимать значимость этого соглашения. Не рассчитывайте, что такое соглашение будет принято с первого раза, вас ожидает множество дискуссий.
Составьте список соглашений о кодировании, в которых вы обозначаете то, как переменные должны объявляться, соглашения об именах и т. д. Количество правил, которые вы можете добавить в этот список, не ограничено и может варьироваться. Просто делайте то, что работает для вас и вашей команды. Не стесняйтесь добавлять новые правила в список соглашений, если команде это подходит. Это же касается и удаления соглашений из списка.
После того, как вы получили свой список соглашений о кодировании, крайне важно придерживаться их. Наиболее предпочтительный способ — проверить соглашения о кодировании с помощью статических анализаторов и непрерывной интеграции, поскольку он не требует каких-либо ручных действий.
Чем меньше ошибок в коде, тем выше его качество. Тщательное тестирование отфильтровывает критические ошибки и гарантирует, что код работает так, как задумано.
Наличие четкой стратегии тестирования важно, когда дело доходит до улучшения качества кода. Как минимум, ваш код должен быть модульным. Еще лучше, если вы хотите использовать и другие способы, например интеграционное или регрессионное тестирование.
Наличие ошибок в вашем коде, вероятно, неизбежно. Поэтому анализ и способ обработки этих ошибок очень важны. Если вы хотите улучшить свои навыки, важно учиться на собственных ошибках.
Когда возникает ошибка, проанализируйте ее с помощью нескольких вопросов:
Есть несколько метрик, которые вы можете использовать для количественной оценки качества вашего кода. С такой задачей легко справляется SonarQube. Он с легкостью поможет вам собрать все необходимо важные метрики:
Используется при тестировании программного обеспечения. Она показывает процент исходного кода программы, который был выполнен в процессе тестирования. Задайте планку, ниже которой процентное соотношение ваших тестов не опускается.
Ошибки в коде чем-то сродни углеродному следу. Избежать совсем невозможно, а лишний выхлоп сам по себе не убьет ни человечества, ни окружающей его природы. Тем не менее, снизить негативный эффект от своего пребывания на планете сегодня кажется естественной потребностью. Примерно так же и написание чистого кода оказывается ответственностью каждого разработчика. Независимо от того, какой именно путь вы выберете, необходимо стремиться писать работающий и понятный код.
Хорошо, если удастся не превращать чистоту в фетиш, учитывая срок жизни нашего кода и оценивая целесообразность дальнейших улучшений. Главное помнить о людях: пользователях, которых может подвести внезапный отказ даже небольшой части разработанной нами системы, и инженерах, которым предстоит эту систему поддерживать.
Грязный, чистый, устремлённый
Грязный
Давайте вместе поразмыслим — что же такое чистый код, и что такое код грязный? Или, как говорят американцы – «hairy code», т.е. волосатый?
Чем чистый код отличается от грязного – или, как говорят в этих наших интернетах, от «говнокода»? Да и нужен ли он вообще, этот чистый код?
Давайте сначала разберёмся с определениями.
Мне кажется, что дать чёткого определения «чистому» коду просто невозможно. Отчасти это – как с красотой: смотришь на картину, или там скульптуру – и видишь: да, красива. Или, наоборот, уродлива.
Да, мы научились определять общие закономерности, скажем, в лицах, которые считаются красивыми. Но готовы ли мы дать чёткое определение красоте? Думаю, нет.
Эта аналогия не вполне корректна (как и большинство аналогий), но примерно передаёт ощущения, возникающие при работе с кодом. Неважно – чужим ли, своим ли, написанном пару месяцев назад и уже прочно забытым. Код либо нравится, либо нет. Он либо красив, чист и приятен – либо волосат, уродлив и дурно пахнет.
И, конечно же, у каждого есть свои критерии «красоты кода». Свой, так сказать, вкус.
Но, тем не менее, есть какие-то общие точки, о которых если и спорят, то вяло и соглашательски. Не о сути, а об обрамлении.
Давайте попробуем их перечислить.
Легко читается и понимается | Запутан, неочевиден, трудно понимаем |
Легко поддаётся изменениям | Закостенел в своих внутренних связях; изменить что-либо стоит неимоверных усилий и жертв |
Может быть расширен, либо встроен куда-нибудь в виде отдельного модуля | Для расширения требует переписывания, для встраивания – обёрток |
Поддаётся автоматизированному тестированию | Может быть протестирован, лишь как «чёрный ящик» |
Конечно, можно начать спор о «читабельности» или «понимабельности» кода. Это совсем не формализованные термины.
Но и они интуитивно понятны: если, например, кто-то станет доказывать окружающим, что он привык писать всю программу в виде одной-двух огромных функций, «которые делают всё», а решение тех же задач при помощи хотя бы разбиения на большое количество небольших процедур и функций для него непонятно – ему намекнут, что надо бы подтянуть азы.
А желательно – основательно поковырять ООП и стараться инкапсулировать логику в отдельных классах, чтобы не приходилось напрягать головной мозг ни разбором огромных «портянок» кода на десятки экранов, ни запутанными связями процедур и функций, которые к тому же (omg) оперируют кучей глобальных переменных.
Примерно так же дело обстоит и с остальным: конечно, даже среди приведённых 4х пунктов есть взаимоисключающие параграфы (легко читаемый код далеко не всегда будет легко изменяемым, лёгкость расширяемости может конфликтовать с автоматизацией тестирования и т.п.) – но в целом обстановка понятна.
В принципе, руководствуясь этими пунктами (усиливая или ослабляя каждый из них в зависимости от требований конкретных задач), можно легко отличить грязный код от чистого.
Хотя лучше всего, если это происходит само собой, без чересчур подробного анализа. Когда есть «нюх», позволяющий быстро понять, что код грязен и воняет.
Чистый
Теперь давайте всё-таки попробуем разобраться – зачем же он вообще нужен, этот чистый код? И так ли уж плох код грязный и волосатый?
Ну, для начала нужно сказать: it depends.
Бывают моменты, когда написать «быстро и грязно» куда важнее, чем «долго и чисто». Хотя нужно отметить, что «грязно» далеко не всегда означает «быстро». Бывает, что ровно наоборот.
В общем, давайте попробуем рассмотреть более-менее жизненные примеры и постараться понять в каждом случае – когда грязное кодирование бывает оправдано, а когда абсолютно недопустимо.
Например
На сервере что-то происходит, логи пишутся – но они огромны, и читать их некому. Нужно написать небольшую утилитку, которая прочитает логи, вытащит оттуда какие-то численные данные и представит их в виде таблицы. На входе – лог-файл, на выходе – текст с цифирями.
Такую задачу вполне можно написать как угодно грязно – лишь бы утилька работала, а написание не заняло много времени. Ведь мы решаем здесь одну сиюминутную задачу.
Решить же задачу долговременную куда как лучше, изменив систему регистрации ошибок (писать те же численные данные в базу, например).
То есть утилиту эту в идеале используют один-два раза, после чего выкинут. Чистота кода здесь совершенно не важна.
Другой пример
Сервер иногда падает, почему – никто не знает. Анализатор логов позволил понять, что падение вызывается большим количеством однотипных запросов, приходящих с вполне определёнными значениями параметров, и эту ситуацию необходимо срочно воспроизвести.
Нужно написать небольшую утилитку, которая будет в точности воспроизводить это поведение.
Казалось бы – всё один в один повторяет первый пример. Однако здесь возникает вопрос: раз процесс тестирования не предусматривает воспроизведение подобных ситуаций, то не возникнет ли необходимость дальнейшего развития этой утилиты в качестве инструмента тестирования? Не станет ли она самостоятельным приложением, которым пользуются регулярно?
Если ответ – «да» или хотя бы «возможно», то стоит уделить немного внимания тому, чтобы код был понятен хотя бы самому разработчику через месяц-другой, и в то же время позволял бы как-то себя расширять.
К примеру, добавлять другие последовательности запросов, конфигурировать адрес сервера и число запросов, значения ключевых параметров и т.д.
Это ненамного замедлит разработку утилиты «здесь и сейчас» — зато, когда вновь встанет вопрос о воспроизведении последовательности запросов на сервер – утилита будет тут как тут и потребует минимального допиливания; а главное – минимального времени на вспоминание, что там к чему.
Третий пример
Разработка программного модуля для основного программного продукта компании, уже несколько лет успешно развивающегося на рынке.
Казалось бы – модуль изолирован, интерфейсы взаимодействия с другими модулями определены. «Кручу-верчу, говнокод писать хочу». Но тут возникает серьёзное «НО».
Что будет с этим модулем через полгода? Год? Потребует ли он поддержки? Изменения? Расширения функционала? Возможно, в итоге разовьётся в отдельный продукт?
Если хотя бы на один вопрос можно дать хотя бы ответ «вероятно» — то говнокодить, увы и ах, строго не рекомендуется.
Но это не весь список вопросов. А кто будет работать с этим модулем через два-три года? Тот, кто его писал, или кто-то другой?
Если кто-то другой – то ведь ему придётся в этом коде разбираться.
И если это будет плохой, негодный код – то либо плакать и жевать кактус, проклиная создателя, либо выкинуть всё на помойку и переписать заново, получая при этом поджопники от начальства за срыв сроков.
Если же работать с этим кодом будет сам разработчик – то тем более. Да он через полгода уже не будет помнить: что, где и как работает! Ему придётся разбираться в этом коде так, как будто код совершенно чужой. Не враг же он самому себе?
Четвёртый пример
Разработка приложения (сайта, базы данных с простейшим интерфейсом – чего угодно) под заказ в сжатые сроки за небольшие деньги.
С одной стороны – code and forget, можно писать что угодно и как угодно, лишь бы работало.
С другой стороны – а что, если этот заказчик через месяц вернётся и попросит за дополнительные деньги что-то добавить или переделать? Будем плакать, колоться, но жевать кактус? Откажемся от заказа?
А что, если он обратится к другому разработчику (компании), получит негативный feedback о качестве исполнения проекта, и больше никогда не вернётся к «злым говнокодерам», да ещё своим друзьям отсоветует?
Я уже не говорю о таких вещах, как качество кармы и память потомков.
Пятый пример
Самый жёсткий случай абсолютного недопущения говнокодирования.
Мне сложно даже представить себе какие-либо аргументы в пользу осознанного выбора плохого кода в случае командной разработки.
Да что там говорить – один говнокодер способен принести вреда больше, чем вражеский агент в тылу врага!
Если команда не изолирует его, бросив на написание никому не вредящих, ни с чем не связанных, абсолютно левых утилит и мини-приложений – то его продуктивность в команде будет не то, что нулевой – она будет отрицательной!
Необходимость читать, вникать, исправлять, матерясь – а в итоге выкидывать и переписывать заново – мало того, что занимает больше времени, чем самостоятельная разработка хорошего кода, так ещё и портит общую атмосферу в команде и минусует мораль всех разработчиков, вынужденных сталкиваться с говнокодом не по своей вине.
А тестирование? Сопровождение? Расширение функционала??
Я мог бы написать ещё пару хулительных абзацев – но нет. Не могу.
Клавиатура выпадает из ослабевших пальцев при мысли о том, сколько вреда может принести говнокод в команде…
Это ужасно… ужасно…
Устремлённый
Итак, мы примерно понимаем, что такое грязный код и чем он плох. Мы всё ещё не вполне понимаем, что такое чистый код, но ощущаем его необходимость.
Почему же он всегда есть, этот грязный код, почему он всегда присутствует и портит жизнь всем – в том числе и своим авторам?
На мой взгляд, всё предельно просто: писать чистый код – это искусство, это сверхспособность, развить которую в себе может практически каждый; но далеко не каждый даже задумывается о необходимости её развития.
Не говоря уже о том, чтобы получать представление о сиём предмете в профильном университете или на профильных курсах – там дают лишь самые верхушки «нужных» технологий, платформ и языков – немногие вообще уделяют специальное внимание улучшению собственных навыков чистого кодирования.
Конечно, с течением времени, если у разработчика развит «нюх на грязый код», он неизбежно начинает писать всё чище и лучше.
Он читает на досуге интересные статьи, он изучает паттерны проектирования. Но бывает, что он делает это потому, что ему интересно – а не потому, что осознаёт необходимость развития своих навыков написания чистого кода.
И при этом, в идеале, он всегда ощущает, что его код всё ещё недостаточно хорош, что ему ещё далеко до совершенства. И пусть его сегодняшний «говнокод» на голову выше самого лучшего, что он писал два-три года назад – всё равно есть куда расти.
В связи с этим мне вспоминается один интереснейший разговор с моим коллегой, которому, как и мне, довелось провести не одно собеседование с кандидатами на должность разработчика – возможно, даже больше, чем собеседований в качестве такового кандидата.
Мы говорили о молодых программистах и о том, какие их качества более всего свидетельствуют о потенциале профессионального развития.
В итоге всё свелось к нескольким простейшим пунктам, в порядке важности:
1) Хорошо работающая голова (поэтому у нас всегда есть задачки на логику)
2) Высокий уровень самокритичности (поэтому всегда есть задачки на написание кода и поиск ошибок в нём)
3) Интерес к программированию (важен в меньшей степени, задачками не определяется в принципе)
То есть понятно, что если голова работает плохо – то разработчиком не станешь при всём желании и старании. Однако, если она даже золотая и светится от разумности – это ещё далеко не гарантия.
Частенько бывает, что молодой специалист, видя, как легко ему всё даётся (особенно – в сравнении с большинством своих одногруппников, сокурсников, просто ровесников) начинает искренне считать, что круче бывают только яйца.
И, хотя наверняка к этому есть некоторые основания, но ЧСВ зашкаливает настолько, что в итоге в один прекрасный момент он просто перестаёт развиваться, считая, что «я и так умный, а кто пытается это оспорить – тот дундук».
И хорошо, если при этом у него остаётся живой, острый интерес к своей работе. Если он продолжает читать статьи и книги «потому, что интересно». Тогда у него остаётся небольшой шанс не застыть, а продолжать развиваться.
И, наконец, бывает, что парень (или девушка – что встречается гораздо реже, уж извините меня за эту неполиткорректную реальность) и умный, и самокритичный – редко остаётся довольным своим кодом и вообще считает, что ему ещё расти и расти – в какой-то момент теряет (хорошо, если не полностью) интерес к профессии, начинает меньше читать, меньше экспериментировать.
Начинает чаще выполнять задачи «строго по спецификации», желательно – уже знакомые задачи, из знакомых сфер. Меньше уделять внимания новым языкам, платформам, концепциям.
И становится вполне хорошим, годным специалистом. Зачастую даже не очень узким, а относительно многопрофильным. Вполне себе уважаемым.
Но так и не достигает вершины своего изначального потенциала.
И лишь в очень редких случаях умный, способный, в высшей степени самокритичный молодой человек с горящими глазами растёт ежегодно, ежечасно – и в итоге становится звездой. Бывает, что очень быстро становится «локальным светилом» – но не застывает, не ограничивается этим, а продолжает расти, развиваться, совершенствоваться.
Ах, как прекрасна эта картина – так и хочется смахнуть несуществующую слезу! Как прекрасен он, этот устремлённый в бесконечность молодой человек, своим духовным порывом приподнимающий самые небеса, в которые нацелен его всепроникающий взгляд!
Как счастливы люди, окружающие его, когда они понимают, сколь величествен его путь, и делают, в свою очередь, хоть два-три шага рядом с ним. Приближаясь хоть на волос к той прекрасной бесконечности возможностей, куда летит он на всех парах!
Как хочется видеть побольше горящих глаз, светлых умов, обращённых в эту бесконечность. Как хочется хотя бы немного помочь этим атлантам на их пути, хоть на мгновение поддержать, подтолкнуть ввысь, приблизить их к этой недостижимой и прекрасной цели.
И остаться внизу, с щемящей радостью наблюдая, как пронизывают они пространство и время в своём стремлении.
И знать, что хотя бы немного, хотя бы чуть-чуть – помог, поддержал, а не стоял в стороне, застывший в своём упоении собственной важностью, не бросал презрительных взглядов – «пхе… молодёжь..»
9 крышесносных правил для тех, кто хочет писать чистый код
Они взорвали мой мозг, и я мгновенно стал программировать лучше.
Джордж Студенко
(George Studenko)
Разработчик ПО. Увлечён искусственным интеллектом и компьютерным зрением.
Фулстек-разработчик. Любимый стек: Java + Angular, но в хорошей компании готова писать хоть на языке Ада.
Вы слышали про объектную гимнастику (Object Calisthenics)? Если нет, то вам точно стоит её освоить! Тем более что это всего-то девять правил.
Я рассказывал о них многим разработчикам, и все они реагировали схоже. Сначала думали, что это шутка: «Как вообще можно хоть какой-то код написать по этим правилам?» Но, поприменяв их, обычно соглашались, что код и правда становится чище — причём почти мгновенно.
Так что же это?
Применяя объектную гимнастику, можно сделать код:
Считайте это упражнением. Вам нужно научиться выполнять эти правила при кодинге. А вот в повседневном программировании какими-то из них всегда можно пожертвовать — если следовать им слишком сложно или результат того не стоит.
Итак, выберите себе кодерскую задачку, начните её решать и постарайтесь строго следовать этим принципам. Даже если некоторые из них поначалу кажутся глупыми, просто продолжайте.
1. Только один уровень вложенности в каждом методе
То есть одно значение отступа на весь метод. Так его легче будет читать.
Вам придётся извлечь и вынести в отдельные методы некоторые фрагменты кода — например, условия и циклы. Этим новым методам нужно будет дать говорящие имена и вызвать их из исходного метода.
В чём профит
2. Не используйте else
Вложенные условия усложняют код, делают его нелинейным.
Как обойтись без else
Мы решили слегка отойти от оригинальной статьи и добавили пояснения к каждому способу. — Пер.
Например, ваша программа работает с объектами-фруктами: яблоками и грушами. По конвейеру движутся коробки с фруктами. Некоторые коробки подписаны, некоторые — нет. Если коробка не подписана, то вы считаете, что в ней лежат яблоки, — ну, так договорились.
В этом случае вы можете написать что-то вроде:
если коробка подписана, считать, что внутри те фрукты, которые указаны на коробке
иначе считать, что там яблоки
А ещё вы можете по умолчанию считать, что в коробке яблоки, и менять это значение, только если встретите надпись «груши».
Этот способ подойдёт для тривиального случая.
если условие1 выполняй действие1
иначе выполняй действие2
если условие1 выполняй действие1 и вернись
а ниже внутри того же метода расположить обработку второго условия — ведь исполнение дойдёт до него, только если не сработает условие1.
В этом случае методы будут просто вызываться друг за другом, а проверки условий окажутся у них внутри. Если условие не выполнится, программа вернётся на уровень выше и вызовет следующий метод со следующей проверкой.
Полиморфизм — один из столпов ООП. Благодаря ему один и тот же метод может по-разному реализовываться в иерархии классов.
Здесь автор говорит о том, что конструкцию с несколькими условиями иногда бывает уместно заменить вызовом одного метода.
Так получится сделать, если создать систему классов-наследников, в которых по-разному определить этот один метод.
Шаблон проектирования «Состояние» полезен, когда в зависимости от состояния системы одно и то же действие (переход к следующему этапу) должно обрабатываться по-разному.
Например, кофейный автомат сначала ждёт выбора напитка, потом оплаты, а только после этого готовит кофе.
Метод перехода на следующий шаг можно написать с кучей проверок типа «если сейчас я на шаге N, то делай то-то», а можно создать классы для каждого состояния и прописать действия по переходу на следующий шаг в них.
Шаблон проектирования «Стратегия» определяет семейство схожих алгоритмов и помещает каждый из них в отдельный класс.
В вызывающем классе хранится ссылка на стратегию, которую сейчас нужно использовать. Так что вместо множества проверок типа «если. то. » вызывается один метод класса-стратегии.
В чём профит
3. Оборачивайте примитивные типы
Оборачивая примитивные типы в классы, мы инкапсулируем (скрываем) тип. Если позже в ходе рефакторинга мы захотим изменить примитивные типы, это можно будет сделать в одном месте.
А ещё такой код легче воспринимать, ведь по сигнатуре объекта-обёртки сразу ясно, что передавать методу в качестве параметров.
В оригинальной книге правило звучит так: «оборачивайте примитивы и строки».
Например, если метод принимает параметр типа int, это мало о чём говорит. Другое дело, если тип параметра будет, скажем, Hour. Мы оборачиваем целое число (часов) в класс. В тот же класс можно добавить проверку допустимых значений, и тогда никто не сможет передать в метод 36 или другое неподходящее число.
В чём профит
4. По одной точке в строке
Это следствие закона Деметры: «Общайся только с друзьями» (речь об общении между классами с помощью вызова методов друг друга. — Пер.).
Точку вы используете для вызова методов в Java или С#. Вызовы типа object.getProperty().getSubProperty().doSomething() — это очень плохая практика! Классы не должны знать так много деталей реализации других классов.
В чём профит
5. Не сокращайте имена
Вы когда-нибудь встречали странное сокращённое название метода или переменной. Такое, что назначение их без контекста можно понять пятью разными способами?
Если вам приходится сокращать название метода, возможно, этот метод делает больше, чем должен. То есть нарушен принцип единственной ответственности. Поразмыслите над этим.
Поразмыслили? А теперь не сокращайте наименования!
В чём профит
6. Не раздувайте классы
Делайте их небольшими:
В конце концов, если ваш класс специализируется на чём-то одном, он не должен быть большим, верно?
В чём профит
7. Не больше двух переменных экземпляра (instance variable) на класс
Один класс должен иметь дело с одним состоянием, максимум с двумя. Так что, если в классе более двух переменных экземпляра, возможно, он нарушает принцип единственной ответственности.
Переменная экземпляра (instance variable, атрибут) — переменная, которая хранит свойство объекта — экземпляра класса. Этим она отличается от статической переменной (относится к классу, а не к его экземпляру) и от локальной переменной, которая объявляется в членах класса — например, в методах.
Кажется, это требование очень сложно выполнить. Уверен, вы видели классы с десятками параметров в конструкторе, так ведь?
Отлично! Почему бы не сгруппировать их в один объект? Или ещё раз хорошенько подумать о том, точно ли у этого класса идеальная архитектура и не делает ли он слишком много лишнего.
В чём профит
8. Первоклассные коллекции
Это похоже на правило №3, только применительно к коллекциям.
Внутри вашего класса может быть по-прежнему простая коллекция. Но, обернув её в класс, вы в будущем сможете легко провести рефакторинг: например, изменить тип коллекции.
В книге The ThoughtWorks Anthology автор акцентирует внимание на том, что в таком классе — обёртке над коллекцией вообще не должно быть других членов, кроме этой коллекции. Зато туда можно добавить методы фильтрации или добавления/удаления элементов.
В чём профит
9. Никаких геттеров и сеттеров
Не принимайте решений вне класса, позвольте ему самому заниматься своим делом. Иными словами, следуйте принципу «Рассказывай, а не спрашивай».
В чём профит
Что дальше?
Теперь вы знаете всё! Следовать этим принципам сперва будет сложно. Появится искушение всё бросить. Но воспринимайте это как вызов себе — соберитесь и упражняйтесь (никаких оправданий!).
А вот строго выполнять все эти правила в ежедневной разработке вовсе не обязательно. Помните про компромиссные варианты и выбирайте то, что лучше.
обложка: zaidi razak / Shutterstock
Где учиться программированию?
У Skillbox — более 50 крутых курсов по программированию. Разработка на Java, PHP, C#, Python и других языках, Data Science, создание игр на Unity, кибербезопасность, разработка мобильных приложений…
Начать учиться можно сразу, а платить за учёбу — позже. Обучение онлайн, в удобном для вас режиме. А ещё мы помогаем с трудоустройством.
ThoughtWorks — знаменитая американская компания с филиалами в 17 странах. Занимается разработкой ПО и консалтингом. Именно в её недрах родился манифест Agile — методологии гибкой разработки. А ещё там в разное время трудились гуру программирования и авторы книг Мартин Фаулер (Martin Fowler) и Джим Хайсмит (Jim Highsmith)
Объектно-ориентированное программирование (ООП) — парадигма разработки, при которой программы состоят из объектов. Объекты обладают свойствами и с помощью методов реализуют своё поведение.
Принцип единственной ответственности (англ. Single Responsibility Principle, SRP) — один из пяти основных принципов ООП, сформулированных Робертом Мартином. Это программист, консультант и автор многих классических книг о программировании.
Принцип гласит, что у каждого класса должна быть только одна ответственность (обязанность) и она должна быть полностью зашита внутри класса (инкапсулирована). И, конечно, все методы класса должны быть направлены исключительно на реализацию этой ответственности.
Принцип открытости/закрытости говорит, что программные сущности (классы, модули, функции) должны быть открыты для расширения, но закрыты для изменений.
Считается, что у хорошо спроектированной системы сильная связность (high cohesion) и слабое зацепление (low coupling).
Чем сильнее связность, тем лучше программная сущность (например, класс) сфокусирована на выполнении своих задач.
Чем слабее зацепление, тем меньше один модуль программы знает о своих соседях и тем меньше зависимостей между ними.