Как стать автором
Обновить

Комментарии 13

Статья так и не отвечает на поставленный в заголовке вопрос «усложненность архитектуры».
Вместо этого уводит в сторону производственного конвейера, типа он «сложный», потому что у нас куча анализаторов кода, CI, всё покрыто тестами и код-ревью.
В моём понимании архитектура вообще не об инструментах и процессах. При абсолютно тех же производственных процессах и инструментах архитектура приложения может быть как простой, логичной и понятной, так и нет.
архитектура вторична, первичны результат и процесс разработки

Результат непосредственно зависит от архитектуры, а разработка по сути стандартна — там ничего «архитектурного» нету, это лишь набор процессов и инструментов.

P.S. Проект организации строительства монолитных зданий примерно одинаков как для безвкусной бетонной коробки, так и для памятника архитектуры.
Спасибо за комментарий.

Результат непосредственно зависит от архитектуры, а разработка по сути стандартна

В статье как раз говорится про разработчиков, которые в принципе не сталкивались с таким процессом разработки, в котором есть автоматизированный pipeline со статическими анализаторами, тестами, quality gates, и пр. На моей практике, я очень редко встречал android проекты, которые попали мне из других рук, и где был бы написан хотя бы один тест. И эти проекты, в принципе, не пригодны к автоматическим тестам. Если бы, в таких проектах было бы требование покрытия кода тестами, их архитектура однозначно бы изменилась в сторону усложнения.

Т.е. требования к процессу разработки — реально влияют на то, какой будет архитектура проекта.

Не понимаю, почему усложнения? Казалось бы наоборот, каждый класс, ну или функция отвечает за одну вещь. Это и тестируется проще и понимается тоже и архитектура не усложняется. Или в вашем понимании, простая архитектура, это когда чем меньше классов, тем проще? Но это ведь не так.
С моей точки зрения, простая, это когда понятнее.
Второй ваш пример, явно понятнее первого.

Я часто встречаю от новичков некоторое сопротивление, в плане того, что как раз много кода приходится писать. Для них чем меньше кода — тем проще.
НЛО прилетело и опубликовало эту надпись здесь
Для приведенного примера легко написать тесты изначально. Можно мокнуть restApi.loadSomething() с помощью Mockito не выделяя интерфейса

Представьте что SomeApifinal класс, такой метод уже замокать не получится. Ну и это считается дурным тоном — мокать конкретные реализации.

А вот это уже две последние «линии обороны» сложной архитектуры.
1. Представь ситуацию, когда <что-то с весьма незначительной вероятностью>
2. Так принято, это обычная практика, так пишут даже в Facebook/Яндекс/..., так не делать — дурной тон.
Дальше только «не спорь с тимлидом».
Представь ситуацию, когда <что-то с весьма незначительной вероятностью>

Я привел весьма распространенную ситуацию, и это действительно, считается антипатерном — мокать конкретные реализации. Конкретная реализация может быть не вашим кодом, а сторонней библиотекой, например, или это может быть код, за который ответственна другая команда в проекте. Что бы избежать этих проблем — лучше скрыть конкретную реализацию за интерфейсом и придерживаться контрактов в реализации этого интерфейса.

Можно не делать класс финальным, тогда и проблем с моком не будет. Для запрета наследования можно использовать линтер и статический анализатор. В результате компромисс — новичок доволен, потому что не нужно выделять абстракции в каждом модуле, а тимлид доволен, потому что код по-прежнему тестируемый и наследования в коде нет. Мокать внешние зависимости действительно не следует, но как я понял из статьи, вы предлагаете выделять интерфейсы для всех зависимостей, которые замедляют тесты и взаимодействуют с внешним миром.

Разработчики языка Kotlin, сделали классы по умолчанию — final. И это было сделано не просто так. На мой взгляд, лучше придерживаться агрегации, композиции при расширении функционала какого-то класса, нежели наследования. Поэтому, хорошей практикой является закрытие класса на расширение через final, а если нужно расширить — то можно прибегнуть к паттерну "декоратор", но этот паттерн уже подразумевает выделение интерфейса для класса.

Как я понял, в заметке под сложностью понимается и конструктивная сложность, и труднопреодолимость системы контроля качества кода, и проблематика познания уже созданного. Что касается первой, то да — простые решения чреваты путаницей в дальнейшем, а обобщенный опыт построения больших приложений содержит великое множество принятых соглашений и выбранных подходов (паттернов), но на длинной дистанции это усложнение себя оправдывает. Полоса препятствий для кода по пути в репозиторий — вещь также полезная, глупо спорить. Однако, на мой взгляд, новичок в проекте не спросит «почему так сложно?» до тех пор пока не разберется в задаче и не выносит в голове своё решение, возможно более простое, а порой на это уходят месяцы. Так часто бывает, когда приложение делается для бизнеса, существующего уже лет 20, да к тому же вечно приспосабливающегося к изменениям в окружающей среде, да еще если автоматизация выполняется после ухода носителей знаний, а может, и по причине этого. Так что новичку лучше пожелать попасть в проект с ясной архитектурой и хорошей атмосферой в коллективе. Помогут, обучат.
В принципе все написано правильно, единственное что мне режет глаз, так это то что новичку не дают шанса проявить себя. Кто знает, может все действительно сложно и есть путь проще, а у тимлида/архитектора «замылен глаз». Поэтому новичку нужно выставить формальные требования к исходному коду, и не просто ссылкой на solid в википедии, а типа: мы делаем "так" — потому "что".
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории