Есть две вещи: программирование и хорошее программирование. Программирование — это то, чем мы все занимаемся. Пришло время заняться хорошим программированием. Все мы знаем, что даже плохой код работает. Но чтобы сделать программу хорошей, нужны время и ресурсы. Но заняться своим кодом никогда не поздно.
Книга Роберта Мартина “Чистый код” дала мне много знаний о лучших практиках и о том, как на самом деле писать код. Теперь мне стыдно за свои навыки программирования. Хотя я всегда старался улучшить свой код, эта книга научила меня гораздо большему.
Вы читаете эту статью по двум причинам. Во-первых, вы программист. Во-вторых, вы хотите стать лучшим программистом.
Что такое чистый код
Недостаточно быстро закончить разработку, если другие не смогут понять ваш код, потому что это станет еще одним техническим долгом.
Ваш код «чистый», если его легко понять всем в команде. Чистый код может быть прочитан и улучшен другим разработчиком. С понятностью приходит удобочитаемость, изменяемость, расширяемость и поддерживаемость.
Причина, по которой вы должны заботиться о своем коде, заключается в том, что он описывает ваш мыслительный процесс другим. Вот почему вы должны начать думать о том, чтобы сделать свой код более элегантным, простым и читаемым.
Характеристики чистого года
- Он должен быть элегантным — чистый код должно быть приятно читать. Его чтение должно вызвать у вас улыбку, как это сделала бы хорошо сделанная музыкальная шкатулка или хорошо спроектированный автомобиль.
- Чистый код сфокусирован — каждая функция, каждый класс, каждый модуль демонстрируют целеустремленность, которая никогда не размывается и не загрязняется окружающими подробностями.
- Чистый код это забота. Кто-то нашел время, чтобы сделать это простым и упорядоченным. Люди уделили должное внимание деталям. Они позаботились.
- Он проходит все тесты.
- В нем нет дубликатов.
- Сведено к минимуму количество сущностей, таких как классы, методы, функции и т.п.
Одно из различий между умным программистом и профессиональным программистом состоит в том, что профессионал понимает, что ясность — главное. Профессионалы используют свои способности во благо и пишут код, понятный другим. — Роберт С. Мартин
Как писать чистый код?
Осмысленные имена
Выбор хороших имен требует времени, но экономит больше, чем на это тратится. Имя переменной, функции или класса должно ответить на все важные вопросы. Оно должно рассказать вам, почему существует объект, для чего он нужен и как он используется. Если имя требует комментария, то оно не раскрывает его намерений.
Вот пример:
— Имена классов
Классы и объекты должны иметь имена существительных или фразы, такие как Customer, WikiPage, Account и AddressParser. Избегайте таких слов, как «Менеджер», «Процессор», «Данные» или «Информация» в названии класса. Имя класса не должно быть глаголом.
— Имена методов
Методы должны иметь глагольные имена или глагольные фразы, такие как postPayment, deletePage или save. Аксессоры, мутаторы и предикаты должны называться в соответствии с их значением и иметь префикс get, set и соответствовать стандарту.
— Используйте доменные имена в случае проблемы
Когда для того, что вы делаете, нет «определения», используйте имя из проблемной области. По крайней мере, программист, обслуживающий ваш код, может спросить эксперта в предметной области, что это означает.
Написание кода с использованием принципов S.O.L.I.D.
Эти принципы изобретены Робертом К. Мартином (дядя Боб), SOLID — это термин, описывающий набор принципов для хорошего кода.
Принцип единой ответственности — SRP
Это означает, что у каждого класса должна быть одна цель. У класса никогда не должно быть более одной причины для изменения. То, что вы можете добавить в свой класс все, что хотите, не означает, что вы должны это делать. Разделите большие классы на более мелкие и избегайте классов Бога.
Возьмем пример. У нас есть RecyclerView.Adapter с бизнес-логикой внутри onBindViewHolder.
У RecyclerView.Adapter нет единой ответственности, потому что у него есть бизнес-логика внутри onBindViewHolder. Хотя этот метод отвечает только за данные в своей реализации биндинга представления.
Принцип открыт-закрыт — OCP
Программные объекты должны быть открыты для расширения, но закрыты для модификации. Это означает, что если вы напишете класс A, а затем ваши товарищи по команде захотят внести изменения в функцию внутри класса A, они могут легко сделать это, расширив класс A, вместо того, чтобы вносить изменения внутри класса A.
Простым примером может служить класс RecyclerView.Adapter. Вы можете легко расширить этот класс и создать собственный настраиваемый адаптер с настраиваемым поведением, не изменяя существующий класс RecyclerView.Adapter.
Принцип замен Лискова — LSP
Дочерние классы никогда не должны нарушать определения типов родительского класса.
Это означает, что подкласс должен переопределять методы родительского класса так, чтобы не нарушать функциональность родительского класса. Например, вы создаете класс интерфейса с прослушивателем onClick(), а затем применяете прослушиватель в MyActivity и передаете ему всплывающее тост при вызове onClick().
interface ClickListener { fun onClick() } class MyActivity: AppCompatActivity(), ClickListener { //........ override fun onClick() { // Do the magic here toast("OK button clicked") } }
Принцип разделения интерфейса — ISP
Принцип разделения интерфейса (ISP) гласит, что ни один клиент не должен зависеть от методов, которые он не использует.
Это означает, что если вы хотите создать класс A и реализовать его в другом классе (класс B), он не должен переопределять все методы класса A внутри класса B. Чтобы сделать его ясным и легким для понимания, давайте рассмотрим пример: внутри вашего активити вам нужно реализовать SearchView.OnQueryTextListener () и нужен только метод onQuerySubmit ().
Как этого добиться? Просто вы просто создаете callback и класс, который расширяется до SearchView.OnQueryTextListener ().
И вот как теперь реализовать View:
val listener = SearchViewQueryTextListener( object : SearchViewQueryTextCallback { override fun onQueryTextSubmit(query: String?) { // Do the magic here } } ) mSearchView.setOnQueryTextListener(listener)
Или, если вы используете Kotlin, можно использовать Extension Function:
И наконец, вот как реализовать в View:
val listener = object : SearchViewQueryTextCallback { override fun onQueryTextSubmit(query: String?) { // Do the magic here } } mSearchView.setupQueryTextSubmit(listener)
Принцип инверсии зависимостей — DIP
Положитесь на абстракции. Не полагайтесь на конкреции.
Определение принципа инверсии зависимостей, данное дядей Бобом, состоит из двух пунктов:
- Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба должны зависеть от абстракций.
- Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Модули высокого уровня, которые обеспечивают сложную логику, должны легко использоваться повторно и не подвергаться изменениям в модулях низкого уровня, которые предоставляют служебные функции. Чтобы добиться этого, вам необходимо ввести абстракцию, которая отделяет модули высокого и низкого уровня друг от друга.
Простой пример — шаблон MVP. У вас есть объект интерфейса, который помогает взаимодействовать с конкретными классами. Это означает, что классам пользовательского интерфейса (Activity/Fragment) не нужно знать фактическую реализацию методов в Presenter. Таким образом, если у вас есть какие-либо изменения внутри Presenter, классам пользовательского интерфейса не нужно знать об изменениях или заботиться об этих изменениях.
Давайте посмотрим на это в этом примере кода:
Теперь посмотрим на это в UserActivity:
Что мы делаем — создаем интерфейс, который абстрагирует реализацию презентатора, а наш класс представления сохраняет ссылку на PresenterInterface.
Чистый код: вывод
Зрелые программисты знают, что представление о том, что все является объектом, является мифом. Иногда вам действительно нужны простые структуры данных с процедурами, оперирующими с ними. С этого момента вы должны начать думать о том, что реализовать, и о будущем, в котором чистый код можно будет легко обновить.
Я знаю, что вы раньше создавали приложения с бессмысленным именованием, классами Бога, спагетти-кодом — поверьте мне, я делал то же самое. Вот почему я делюсь с вами своими знаниями о Чистом коде от дяди Боба. И это также является напоминанием и для меня. Надеюсь, что смог помочь вам понять принципы.
Чистый код: что еще почитать
- Чистый код — красивый код
- У каждого кода запах особый: 8 причин, почему ваш код плохо пахнет
- Делаем свой код чище
- Идеальный код — это иллюзия
- Чистый код для ведущих разработчиков 🚀
- Чистый код в реальной жизни
- Выразительный Чистый Код