Всем привет!
Давно хотел написать про паттерны/шаблоны программирования. Основной вопрос, возникающий при разговоре про паттерны - какая от них польза? Ведь главное - умеет человек кодить или нет.
С одной стороны паттерны - это лишь часть арсенала программиста. Можно заучить все паттерны, но не научиться кодить.
И тут возникает второй вопрос - о каких паттернах мы говорим?
1) самые известные - паттерны проектирования из книги «банды четырёх» https://refactoring.guru/ru/design-patterns/catalog
Это синглтон, фабричный метод, билдер и все все все
2) паттерны Enterprise архитектуры от Фаулера https://martinfowler.com/eaaCatalog/
3) паттерны рефакторинга https://refactoring.com/catalog/ Про них также говорится в книге Идеальная работа Мартина
4) паттерны модульных тестов http://xunitpatterns.com/ и снова в книге Идеальная работа
5) паттерны интеграции корпоративных приложений https://www.enterpriseintegrationpatterns.com/patterns/messaging/toc.html многие из которых можно встретить в стандарте JMS
6) паттерны микросервисных приложений https://microservices.io/patterns/index.html
7) даже у Kubernates есть паттерны https://www.redhat.com/cms/managed-files/cm-oreilly-kubernetes-patterns-ebook-f19824-201910-en.pdf
8) не говоря уже про антипаттерны https://javarush.ru/groups/posts/2622-chto-takoe-antipatternih-razbiraem-primerih-chastjh-1
9) 10) ...
Из этого списка можно сделать вывод, что паттерны могут быть везде. А из этого второй вывод: паттерны - это удобный способ описания какой-то области разработки. Собственно это и есть их ценность. Шаблоны помогают изучить новую технологию, читать статьи, книги и главное читать код и тесты. Ну и проектировать систему, обсуждать ее архитектуру с коллегами. По сути паттерны - это язык проектирования. А идеальный способ их использования - когда они уже реализованы в неком фреймворке: Singleton и MVC в Spring, Builder в Lombok, Sidecar в k8s, или в языке как Singleton и Decorator в Kotlin.
#patterns #refactoring #unittests
Давно хотел написать про паттерны/шаблоны программирования. Основной вопрос, возникающий при разговоре про паттерны - какая от них польза? Ведь главное - умеет человек кодить или нет.
С одной стороны паттерны - это лишь часть арсенала программиста. Можно заучить все паттерны, но не научиться кодить.
И тут возникает второй вопрос - о каких паттернах мы говорим?
1) самые известные - паттерны проектирования из книги «банды четырёх» https://refactoring.guru/ru/design-patterns/catalog
Это синглтон, фабричный метод, билдер и все все все
2) паттерны Enterprise архитектуры от Фаулера https://martinfowler.com/eaaCatalog/
3) паттерны рефакторинга https://refactoring.com/catalog/ Про них также говорится в книге Идеальная работа Мартина
4) паттерны модульных тестов http://xunitpatterns.com/ и снова в книге Идеальная работа
5) паттерны интеграции корпоративных приложений https://www.enterpriseintegrationpatterns.com/patterns/messaging/toc.html многие из которых можно встретить в стандарте JMS
6) паттерны микросервисных приложений https://microservices.io/patterns/index.html
7) даже у Kubernates есть паттерны https://www.redhat.com/cms/managed-files/cm-oreilly-kubernetes-patterns-ebook-f19824-201910-en.pdf
8) не говоря уже про антипаттерны https://javarush.ru/groups/posts/2622-chto-takoe-antipatternih-razbiraem-primerih-chastjh-1
9) 10) ...
Из этого списка можно сделать вывод, что паттерны могут быть везде. А из этого второй вывод: паттерны - это удобный способ описания какой-то области разработки. Собственно это и есть их ценность. Шаблоны помогают изучить новую технологию, читать статьи, книги и главное читать код и тесты. Ну и проектировать систему, обсуждать ее архитектуру с коллегами. По сути паттерны - это язык проектирования. А идеальный способ их использования - когда они уже реализованы в неком фреймворке: Singleton и MVC в Spring, Builder в Lombok, Sidecar в k8s, или в языке как Singleton и Decorator в Kotlin.
#patterns #refactoring #unittests
refactoring.guru
Каталог паттернов проектирования
Список паттернов проектирования, сгруппированый по предназанчению, сложности и популярности паттернов. В каталог включены объектно ориентированные паттерны, а также некоторые архитектурные паттерны.
Всем привет!
Иногда проект нужно мигрировать - перейти на новую версию платформы, фреймворк, новый формат конфигов. Для преобразований XML есть XSLT. Для JSON - целый зоопарк тулов - https://stackoverflow.com/questions/1618038/xslt-equivalent-for-json
А если нужно преобразовать Java? Есть библиотеки для семанитического анализа кода - вот неплохой список https://stackoverflow.com/questions/2261947/are-there-alternatives-to-cglib
Но анализ - это лишь часть миграции, да и как известно всегда можно добавить новый уровень абстракции)
Сегодня хочу рассказать про OpenRewrite - библиотеку, созданную специально для миграции или масштабного рефаторинга кода.
Введение: https://docs.openrewrite.org/running-recipes/getting-started
Пример кода миграции для произвольного Java класса: https://docs.openrewrite.org/authoring-recipes/writing-a-java-refactoring-recipe
В результате разбора кода строятся Lossless Semantic Trees (LSTs) - ациклические деревья с вложенными элементами, например: CompilationUnit -> Class -> Block of code. Код мигратора напоминает по принципу работы SAX парсер - если кто еще помнит такой)
Не обязательно самому писать код миграции, вот список готовых "рецептов":
https://docs.openrewrite.org/reference/recipes Там есть и преобразование json, xml, yml, maven pom, замена System.out на логгер, миграция с JUnit 4 на JUnit 5, миграция на проверок в модульных тестах с JUnit asserts на AssertJ. И даже миграция на Spring Boot https://www.infoq.com/news/2022/09/spring-boot-migrator
Важно - фреймворк содержит проверки корректности синтаксиса у получаемого кода, но не гарантирует, что код после миграции скомпилируется и будет работать как нужно.
Еще важно - для миграций можно и нужно писать модульные тесты.
#java #migration #refactoring
Иногда проект нужно мигрировать - перейти на новую версию платформы, фреймворк, новый формат конфигов. Для преобразований XML есть XSLT. Для JSON - целый зоопарк тулов - https://stackoverflow.com/questions/1618038/xslt-equivalent-for-json
А если нужно преобразовать Java? Есть библиотеки для семанитического анализа кода - вот неплохой список https://stackoverflow.com/questions/2261947/are-there-alternatives-to-cglib
Но анализ - это лишь часть миграции, да и как известно всегда можно добавить новый уровень абстракции)
Сегодня хочу рассказать про OpenRewrite - библиотеку, созданную специально для миграции или масштабного рефаторинга кода.
Введение: https://docs.openrewrite.org/running-recipes/getting-started
Пример кода миграции для произвольного Java класса: https://docs.openrewrite.org/authoring-recipes/writing-a-java-refactoring-recipe
В результате разбора кода строятся Lossless Semantic Trees (LSTs) - ациклические деревья с вложенными элементами, например: CompilationUnit -> Class -> Block of code. Код мигратора напоминает по принципу работы SAX парсер - если кто еще помнит такой)
Не обязательно самому писать код миграции, вот список готовых "рецептов":
https://docs.openrewrite.org/reference/recipes Там есть и преобразование json, xml, yml, maven pom, замена System.out на логгер, миграция с JUnit 4 на JUnit 5, миграция на проверок в модульных тестах с JUnit asserts на AssertJ. И даже миграция на Spring Boot https://www.infoq.com/news/2022/09/spring-boot-migrator
Важно - фреймворк содержит проверки корректности синтаксиса у получаемого кода, но не гарантирует, что код после миграции скомпилируется и будет работать как нужно.
Еще важно - для миграций можно и нужно писать модульные тесты.
#java #migration #refactoring
Stack Overflow
XSLT equivalent for JSON
Is there an XSLT equivalent for JSON? Something to allow me to do transformations on JSON like XSLT does to XML.
Всем привет!
Есть такой принцип - "безобразно, но единообразно". Если верить интернету, он появился в армии. Но может ли он быть применим к исходному коду и архитектуре?
Ответ - да.
Начну издалека - любой код и архитектура устаревает.
Но это не так страшно если выполняются три условия:
1) хорошо спроектированная гибкая архитектура. Я здесь про архитектуру уровня сервиса\АС. Маленькая ремарка - по отношению к коду термин архитектура плох тем, что в здании архитектуру изменить очень сложно. А в коде - можно.
2) высокое покрытие тестами. Тут все очевидно: много тестов - можно спокойно рефакторить
3) наличие времени для рефакторинга, т.е. другими словами - отсутствие вечного "это надо было сделать еще вчера"
В этом случае сервис можно отрефакторить для адаптации архитектуры к новым требованиям.
И делать это лучше сразу для всего приложения. Чтобы было "единообразно".
Почему так - я уже много об этом писал: изучать код - сложная задача. Один из способов облегчить ее - единообразие архитектуры, в т.ч. наименований, практики применения паттернов, разделения на уровни и модули.
Особенно сильно тяжесть изучения кода бьет по новичкам, но и для "старичков" спустя полгода-год код можно забыть.
В этом плане переделывать выглядящий "безобразно" код в отдельном методе или классе в рамках реализации текущей фичи - плохая идея, т.к. это ухудшит читаемость кода приложения в целом.
Лучше поговорить с бизнесом о рисках, зафиксировать техдолг, выделить на него отдельный технический релиз, согласовать время и все отрефакторить за раз.
Если вам кажется этот вариант фантастическим - понимаю, да, увы, такое бывает.
В этом случае предлагаю рефакторить максимально крупные куски кода вместе с бизнес-фичами. Ну например - модуль в терминах Maven или Gradle. Или набор модулей, относящийся к одному бизнес-процессу, если вы построили маленький монолитик. Или большой)
С монолитами, кстати, хуже всего - именно из-за устаревшей архитектуры, поменять которую разом невозможно, они зачастую и умирают.
При этом неплохо бы где-то рядом с кодом зафиксировать все архитектурные проблемы и план рефакторинга. В файлике типа todo.md в корне проекта. Точно не в wiki или в тикете, т.к. большинство разработчиков в wiki не пойдут.
Также подойдет JavaDoc. Часто он бывает тривиален и не несет ценности. Здесь же ситуация обратная.
Ну и конечно при ползучем рефакторинге поможет расстановка @Deprecated. На них ругается IDEA, SonarQube, они будут мозолить глаза. Это не гарантия того, что код будет поправлен, но уже что-то.
А лучший вариант - технический релиз. И не поосторожнее с монолитами)
P.S. Кстати, сложность рефакторинга является одним из возможных сигналов для разделения монолита на части
#arch #техдолг #refactoring #unittests
Есть такой принцип - "безобразно, но единообразно". Если верить интернету, он появился в армии. Но может ли он быть применим к исходному коду и архитектуре?
Ответ - да.
Начну издалека - любой код и архитектура устаревает.
Но это не так страшно если выполняются три условия:
1) хорошо спроектированная гибкая архитектура. Я здесь про архитектуру уровня сервиса\АС. Маленькая ремарка - по отношению к коду термин архитектура плох тем, что в здании архитектуру изменить очень сложно. А в коде - можно.
2) высокое покрытие тестами. Тут все очевидно: много тестов - можно спокойно рефакторить
3) наличие времени для рефакторинга, т.е. другими словами - отсутствие вечного "это надо было сделать еще вчера"
В этом случае сервис можно отрефакторить для адаптации архитектуры к новым требованиям.
И делать это лучше сразу для всего приложения. Чтобы было "единообразно".
Почему так - я уже много об этом писал: изучать код - сложная задача. Один из способов облегчить ее - единообразие архитектуры, в т.ч. наименований, практики применения паттернов, разделения на уровни и модули.
Особенно сильно тяжесть изучения кода бьет по новичкам, но и для "старичков" спустя полгода-год код можно забыть.
В этом плане переделывать выглядящий "безобразно" код в отдельном методе или классе в рамках реализации текущей фичи - плохая идея, т.к. это ухудшит читаемость кода приложения в целом.
Лучше поговорить с бизнесом о рисках, зафиксировать техдолг, выделить на него отдельный технический релиз, согласовать время и все отрефакторить за раз.
Если вам кажется этот вариант фантастическим - понимаю, да, увы, такое бывает.
В этом случае предлагаю рефакторить максимально крупные куски кода вместе с бизнес-фичами. Ну например - модуль в терминах Maven или Gradle. Или набор модулей, относящийся к одному бизнес-процессу, если вы построили маленький монолитик. Или большой)
С монолитами, кстати, хуже всего - именно из-за устаревшей архитектуры, поменять которую разом невозможно, они зачастую и умирают.
При этом неплохо бы где-то рядом с кодом зафиксировать все архитектурные проблемы и план рефакторинга. В файлике типа todo.md в корне проекта. Точно не в wiki или в тикете, т.к. большинство разработчиков в wiki не пойдут.
Также подойдет JavaDoc. Часто он бывает тривиален и не несет ценности. Здесь же ситуация обратная.
Ну и конечно при ползучем рефакторинге поможет расстановка @Deprecated. На них ругается IDEA, SonarQube, они будут мозолить глаза. Это не гарантия того, что код будет поправлен, но уже что-то.
А лучший вариант - технический релиз. И не поосторожнее с монолитами)
P.S. Кстати, сложность рефакторинга является одним из возможных сигналов для разделения монолита на части
#arch #техдолг #refactoring #unittests
Всем привет!
Продолжая тему рефакторинга. Основное предусловие для начала рефакторинга - это наличие хорошего тестового покрытия. Т.к. мы не меняем бизнес функционал, а улучшаем код либо для повышения производительности, либо для его упрощения. Но при этом нужно гарантировать, что бизнес функционал не сломался, т.е. не появились регрессионные баги. Ведь рефакторинг, в отличие от новой фичи, может затронуть все приложение. Соответственно, баги могут появиться в любом месте, и без тестового покрытия - это большие риски.
Можно рассмотреть похожий кейс. У нас есть монолит, мы хотим распилить его на микросервисы. Это тоже своего рода рефакторинг, только на уровне архитектурном уровне. И тоже аналогичное условие для его начала - наличие достаточного набора тестов. В данном случае повышается важность интеграционных тестов.
Важный момент: в процессе подготовки к разбиению монолита или серьёзному рефакторингу может возникнуть вопрос-предложение - а давайте все выкинем и напишем заново. Так вот - одним из базовых критериев для ответа на этот вопрос также является покрытие тестами. Очевидно, не единственным, но важным. Другие критерии - объем техдолга, соответствие текущей архитектуры и целевой.
Еще кейс - разработчик «боится» рефакторить код, т.к. он слишком сложный или затрагивает слишком много зависимостей. С тестами решиться на рефакторинг намного проще.
Вывод простой - пишите тесты, это страховка при рефакторинге)
#refactoring #unittests #microservices
Продолжая тему рефакторинга. Основное предусловие для начала рефакторинга - это наличие хорошего тестового покрытия. Т.к. мы не меняем бизнес функционал, а улучшаем код либо для повышения производительности, либо для его упрощения. Но при этом нужно гарантировать, что бизнес функционал не сломался, т.е. не появились регрессионные баги. Ведь рефакторинг, в отличие от новой фичи, может затронуть все приложение. Соответственно, баги могут появиться в любом месте, и без тестового покрытия - это большие риски.
Можно рассмотреть похожий кейс. У нас есть монолит, мы хотим распилить его на микросервисы. Это тоже своего рода рефакторинг, только на уровне архитектурном уровне. И тоже аналогичное условие для его начала - наличие достаточного набора тестов. В данном случае повышается важность интеграционных тестов.
Важный момент: в процессе подготовки к разбиению монолита или серьёзному рефакторингу может возникнуть вопрос-предложение - а давайте все выкинем и напишем заново. Так вот - одним из базовых критериев для ответа на этот вопрос также является покрытие тестами. Очевидно, не единственным, но важным. Другие критерии - объем техдолга, соответствие текущей архитектуры и целевой.
Еще кейс - разработчик «боится» рефакторить код, т.к. он слишком сложный или затрагивает слишком много зависимостей. С тестами решиться на рефакторинг намного проще.
Вывод простой - пишите тесты, это страховка при рефакторинге)
#refactoring #unittests #microservices
Всем привет!
Прочитал книгу Лемер "Масштабируемый рефакторинг". В целом понравилась, с важным дисклеймером.
С одной стороны основные мысли в книге вполне себе "капитанские". С другой - о них очень легко забыть)))
Еще важный момент - большинство правил из книжки применимо для скажем так большого рефакторинга: затрагивающего платформенный сервис, от которого зависят множество команд, ядро монолита, схему БД или что-то подобное. Если нужно отрефакторить метод или класс - данные рекомендации скорее всего будут излишними.
Тезисы:
1) т.к. рефакторинг займет длительное время - нужен план. План позволит:
а) видеть весь объем работ и правильно оценить: хватит ли выделенного бизнесом времени
б) найти забытые задачи либо самостоятельно - анализируя план - либо с помощью смежных команд, опубликовав его
2) рефакторинг нужно делать для кода в вашей области ответственности. Если за код отвечает другая - не надо его трогать без согласования
3) нужно понять - не является ли код deprecated или неиспользуемым. Часто код забывают удалять, все его использование ограничивается модульными тестами
4) нужно изучить - почему код стал таким. Зачем?
а) возможно выяснится, что "это не баг, а фича"
б) когда станет понятно, на почему возникли те или иные компромиссы в коде - это изменит отношение к коду. Все же приятнее улучшать сложный legacy код, а не "переписывать этот го..код"
5) нужно ответить себе на вопрос - почему код нужно рефакторить именно сейчас. А возможные ответы на этот вопрос приводят к необходимости метрик для бизнеса, о которых я уже писал https://t.me/javaKotlinDevOps/197
6) важно собрать команду с двумя типами участников: full time разработчики и эксперты. Для этого нужно договориться с руководителями о их полном или частичном подключении к задаче рефакторинга. Искать стоит людей, либо заинтересованных в результате рефакторинга, либо тех, кому надоела рутина и хочется, что-то поменять
7) нужен канал или страничка, где регулярно будут публиковаться прогресс рефакторинга. В случае, если прогресс будет - это может мотивировать на подключение к рефакторингу новых участников. Прогресс нужно сопоставлять с планом, при необходимости вносить корректировки. Также нужен митап или чат, где заинтересованные лица смогут задать вопросы.
8) прогресс нужно контролировать еще потому, что ближе к концу, когда основные изменения уже сделаны, есть риск снижения темпов. Из-за выгорания или расслабления - ведь основные изменения уже сделаны. Что тут можно сделать:
а) собираться командой в неформальной обстановке
б) рассказывать о своих достижениях для вливания "новой крови"
9) после окончания рефакторинга важно проконтролировать, что все потребители знают об изменениях и либо уже используют их, либо запланировали обновление. Речь может идти о переходе на новое API, новый фреймворк, новый DevOps, новую версию библиотеки. Для ускорения процесса перехода нужны:
а) рассылка
б) демонстрация
в) инструкция
г) чат, куда можно задать вопросы
д) возможно регулярный митап для ответов на сложные вопросы
#books #refactoring #book_review
Прочитал книгу Лемер "Масштабируемый рефакторинг". В целом понравилась, с важным дисклеймером.
С одной стороны основные мысли в книге вполне себе "капитанские". С другой - о них очень легко забыть)))
Еще важный момент - большинство правил из книжки применимо для скажем так большого рефакторинга: затрагивающего платформенный сервис, от которого зависят множество команд, ядро монолита, схему БД или что-то подобное. Если нужно отрефакторить метод или класс - данные рекомендации скорее всего будут излишними.
Тезисы:
1) т.к. рефакторинг займет длительное время - нужен план. План позволит:
а) видеть весь объем работ и правильно оценить: хватит ли выделенного бизнесом времени
б) найти забытые задачи либо самостоятельно - анализируя план - либо с помощью смежных команд, опубликовав его
2) рефакторинг нужно делать для кода в вашей области ответственности. Если за код отвечает другая - не надо его трогать без согласования
3) нужно понять - не является ли код deprecated или неиспользуемым. Часто код забывают удалять, все его использование ограничивается модульными тестами
4) нужно изучить - почему код стал таким. Зачем?
а) возможно выяснится, что "это не баг, а фича"
б) когда станет понятно, на почему возникли те или иные компромиссы в коде - это изменит отношение к коду. Все же приятнее улучшать сложный legacy код, а не "переписывать этот го..код"
5) нужно ответить себе на вопрос - почему код нужно рефакторить именно сейчас. А возможные ответы на этот вопрос приводят к необходимости метрик для бизнеса, о которых я уже писал https://t.me/javaKotlinDevOps/197
6) важно собрать команду с двумя типами участников: full time разработчики и эксперты. Для этого нужно договориться с руководителями о их полном или частичном подключении к задаче рефакторинга. Искать стоит людей, либо заинтересованных в результате рефакторинга, либо тех, кому надоела рутина и хочется, что-то поменять
7) нужен канал или страничка, где регулярно будут публиковаться прогресс рефакторинга. В случае, если прогресс будет - это может мотивировать на подключение к рефакторингу новых участников. Прогресс нужно сопоставлять с планом, при необходимости вносить корректировки. Также нужен митап или чат, где заинтересованные лица смогут задать вопросы.
8) прогресс нужно контролировать еще потому, что ближе к концу, когда основные изменения уже сделаны, есть риск снижения темпов. Из-за выгорания или расслабления - ведь основные изменения уже сделаны. Что тут можно сделать:
а) собираться командой в неформальной обстановке
б) рассказывать о своих достижениях для вливания "новой крови"
9) после окончания рефакторинга важно проконтролировать, что все потребители знают об изменениях и либо уже используют их, либо запланировали обновление. Речь может идти о переходе на новое API, новый фреймворк, новый DevOps, новую версию библиотеки. Для ускорения процесса перехода нужны:
а) рассылка
б) демонстрация
в) инструкция
г) чат, куда можно задать вопросы
д) возможно регулярный митап для ответов на сложные вопросы
#books #refactoring #book_review
Telegram
(java || kotlin) && devOps
Всем привет!
Я уже писал о важности рефакторинга.
Но как оценить, что рефакторинг достиг своих целей?
Можно экспертно. Но не всегда этот вариант годится для обоснования времени на рефакторинг у бизнеса.
Можно ли как-то подтвердить эффект цифрами?
Самый простой…
Я уже писал о важности рефакторинга.
Но как оценить, что рефакторинг достиг своих целей?
Можно экспертно. Но не всегда этот вариант годится для обоснования времени на рефакторинг у бизнеса.
Можно ли как-то подтвердить эффект цифрами?
Самый простой…
Всем привет!
Хочу рассказать про наверное самый способ улучшить читаемость. Например, у вас есть сложное условие из нескольких уровней, каждый из которых состоит из ряда проверок. Или длинный метод с кучей условий, который сложно понять и на который справедливо ругается SonarQube.
Решение такое - выделяем атомарные блоки кода или условия в отдельные private методы.
К слову, данный способ является одним из базовых рефакторингов под названием "extract method" из известной книжки Фаулера "Рефакторинг".
Может возникнуть вопрос - а если метод вызывается один раз?
Ответ - без разницы.
У нас есть умный компилятор, он должен такие методы заинлайнить. Сразу скажу, спецификации, подтверждающей этот факт я предоставить не могу)
Окей, но даже если вам не повезет, и ваш компилятор этого не сделает - нужно иметь RPS (request per second) сильно больше 1, чтобы лишние вызовы метода сыграли свою роль. Причем даже в таком случае длинная цепочка вызовов методов должна быть в основном сценарии. Кажется, что под эти три условия попадает не так много кода. И в любом случае у нас есть НТ.
Еще может возникнуть вопрос с unit tests - их число тоже нужно увеличивать? Ответ - не обязательно, нет жесткой связки 1 к 1 теста и метода. Тест можно написать на группу взаимосвязанных методов, главное закрыть все возможные пути выполнения кода. Да и не нужно тестировать private методы.
И еще важный момент - extract method позволяет решить еще один часто встречающийся кейс. Предположим у вас есть дублирующийся код, отличающийся только одним небольшим блоком. Решение навскидку (на Kotlin):
fun doSomething(booleanParam: Boolean): SomeResult {
if (booleanParam) {
doAnotherThing()
}
// some code
}
Но приходится вводить Boolean параметр, а это хоть и не общепризнанный антипаттерн, по этому вопросу идут hollywars, но приближается к этому статусу)
Поэтому можно сделать так:
fun doSomething(): SomeResult {
// some code
}
fun doSomethingExtended(): SomeResult {
doAnotherThing()
return doSomething()
}
Итог: не нужно боятся выделять новые методы.
#refactoring #readability #antipatterns
Хочу рассказать про наверное самый способ улучшить читаемость. Например, у вас есть сложное условие из нескольких уровней, каждый из которых состоит из ряда проверок. Или длинный метод с кучей условий, который сложно понять и на который справедливо ругается SonarQube.
Решение такое - выделяем атомарные блоки кода или условия в отдельные private методы.
К слову, данный способ является одним из базовых рефакторингов под названием "extract method" из известной книжки Фаулера "Рефакторинг".
Может возникнуть вопрос - а если метод вызывается один раз?
Ответ - без разницы.
У нас есть умный компилятор, он должен такие методы заинлайнить. Сразу скажу, спецификации, подтверждающей этот факт я предоставить не могу)
Окей, но даже если вам не повезет, и ваш компилятор этого не сделает - нужно иметь RPS (request per second) сильно больше 1, чтобы лишние вызовы метода сыграли свою роль. Причем даже в таком случае длинная цепочка вызовов методов должна быть в основном сценарии. Кажется, что под эти три условия попадает не так много кода. И в любом случае у нас есть НТ.
Еще может возникнуть вопрос с unit tests - их число тоже нужно увеличивать? Ответ - не обязательно, нет жесткой связки 1 к 1 теста и метода. Тест можно написать на группу взаимосвязанных методов, главное закрыть все возможные пути выполнения кода. Да и не нужно тестировать private методы.
И еще важный момент - extract method позволяет решить еще один часто встречающийся кейс. Предположим у вас есть дублирующийся код, отличающийся только одним небольшим блоком. Решение навскидку (на Kotlin):
fun doSomething(booleanParam: Boolean): SomeResult {
if (booleanParam) {
doAnotherThing()
}
// some code
}
Но приходится вводить Boolean параметр, а это хоть и не общепризнанный антипаттерн, по этому вопросу идут hollywars, но приближается к этому статусу)
Поэтому можно сделать так:
fun doSomething(): SomeResult {
// some code
}
fun doSomethingExtended(): SomeResult {
doAnotherThing()
return doSomething()
}
Итог: не нужно боятся выделять новые методы.
#refactoring #readability #antipatterns