Обновить

Почему разрабатывать ПО действительно сложно?

Время на прочтение5 мин
Охват и читатели6.3K
Всего голосов 16: ↑15 и ↓1+17
Комментарии11

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

Давайте начнем с тривиального, но неоспоримого факта: программное обеспечение постоянно развивается… Заметным исключением является наборная система TeX, разработанная Дональдом Э. Кнутом.

Что-то вы неправду пишете. TeX постоянно развивается, получая дополнительные функции. Буквально каждый пользователь развивает его своими функциями (командами), а число добавочных надстроек (пакетов) растёт с каждым годом.

TeX развивается, или LaTeX, XeLaTeX и тд?

Действительно, вы правы. MS Office 2003 достиг полного совершенства и больше не развивается.

Надстройки (LaTeX), инструменты - да. Но не сам TeX. Его смысл наоборот, в том чтобы быть стабильным. Это не случайность что версия TeX сходится к pi: 3.141592653 - текущая, если верить Википедии.

Пожалуй, надо ответить на это отдельной статьёй. Постараюсь сделать.

Ответ на заголовок статьи можно сформулировать одной фразой - потому что сложность разработки ПО не может быть меньше сложности решаемой им бизнес-задачи. С ростом сложности задач растет и сложность ПО.

Да, но. Это задача архитектуры (системной архитектуры, если быть точным) влиять на подход к решению бизнес задач. Если просто добавлять ещё и ещё - сложность будет неизбежно рост вплоть до момента стагнации, когда ничего полезного за разумные время/деньги в систему уже не добавить.

Разделение продукта на bounded contexts позволяет снизить сложность за счёт того что каждый такой домен ограничен. И это работает.

Однако, такой подход приводит к тому что не все становится возможным сделать "как хочется", что может вызывать критику и сопротивление. Также, это долгосрочная история, что усложняет дело ещё сильнее.

Я долго пытался бороться со сложностью, но на данный момент несколько опустил руки.

Если взглянуть на общую картину, то модульность и разделение приводят к созданию дополнительной сложности в виде связей и интерфейсов между модулями, и в долгосроке это иногда аукается внезапными багами. Нужно понимать, что ресурс внимания одного программиста ограничен, и модульность в контексте единственного программиста -- это такой костыль, помогающий программисту переключать контекст и как-то, с проблемами, работать с отдельными кусками. Так, мне теперь в одном из проектов на микросервисах приходится не просто понимать, что модули работают корректно, но ещё и вычитывать листинги протокола взаимодействия этих модулей (а их больше сотни, на минуточку), проверять корректность RPC.

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

Для проектов, где я являюсь единственным программистом, я использую другой подход: стараюсь, чтобы объёмная сложность кода перевешивала концептуальную. Т.е., если сложно написать какой-то универсальный компонент, который придётся отлаживать год, и он всё равно будет багать, лучше я обойдусь без него, даже если это приведёт к большему объёму кода. Пусть лучше будет три разных неуниверсальных компонента, но понятно, как работающих.

Хочется немного дополнить, к тому что вы говорите.

Мне кажется что следующая модель роста сложности и борьбы с ней может быть релевантной.

Первое: мы начинаем разрабатывать приложение, без модулей, (монолит да), и поначалу все идет хорошо, но где нибудь через год возникает ощущение что все как то связано сложным и странным образом.

Решение: а давайте организуем код по модулям и как то его упорядочим.

Второе: модульный монолит можно развивать еще какое то время, прежде чем возникнет вторая проблема, трудоемкость изменений (это тоже своего рода сложность, сложность тестирования). Если приложение -- достаточно крупный монолит, количество изменений в единицу времени будет только увеличиваться и также будет увеличиваться время необходимое на тестирование. В итоге процесс выпуска новых релизов начинает болезненно буксовать.

Решение: Микросервисы. То что раньше было (или могло быть) модулями теперь становятся отдельными приложениями (взаимодействующими через API, который нужно разрабатывать дополнительно, что overhead, но оправдано). Таким образом объем тестирования сокращается до отдельного сервиса и его связей (а не всего приложения целиком). Да, разрабатывать микросервисы немного более трудоемко чем модульным монолит (за счет API overhead), но это окупается на большой дистанции.

Третье: как я говорил в статье, модульность вообще (и микросервисы в частности) не снижают общую сложность приложения. Это способ лучше организовать связи и облегчить тестирование и раскатывание изменений. Однако, с ростом приложения общая сложность продолжает возрастать и в какой то момент его развитие стопорится потому что "все слишком сложно", и просто чтобы понять какие и где нужно сделать изменения нужно долго разбираться (иногда месяцами).

Решение: bounded contexts (собственно о чем в бОльшей степени статья). Нужно менять системную архитектуру приложения, вводить границы (ограничивающие сложность) и это уже не может быть сделано только на техническом (инженерном уровне), сам продукт нужно менять что бы такой подход к уменьшению сложности сработал. И добиться этого становится действительно тяжело :)

Когда я был молодым и глупым, то пытался в своих пет-проектах делать все по "большому", по тем же принципам, что использовал в рабочем процессе. Это в итоге приводило к переусложнению когда и большинство этих проектов так и не было доведено до конца.

Немного подумав я поменял подход. И теперь в пет-проектах стараюсь делать избыточность по минимуму. Только там где вижу пользу от этого на следующем шаге.

Даже позволяю дублирование кода. Правда когда код дублируется больше трех раз вывожу его отдельно.

И реализацию стал делать начиная с UI. Все API и данные мокаются в изолированном классе(-ах) на UI стороне. И когда становится понятно каким всё таки должен быть API и когда фронтом уже можно пользоваться почти как полноценным приложением - ввожу backend с БД и прочими прелестями.

Такой подход позволил мне делать пет-проекты быстрее и, что важнее, заканчивать их и получать с этого не только моральное удовольствие.

Кстати. Этот подход также использую и при старте написания новых компонент/микросервисов в обычном рабочем процессе. Правда сначала пришлось немного побуждать команду, что это даст пользу. Начальству не нравилось в этом:

  • рефакторинг здесь всё, а это по их мнению лишние траты (см.след.пункт)

  • ты же архитектор. а тут, по сути своей, никакой изначально архитектурой и не пахнет. значит не отрабатываешь свои деньги, халтуришь

Но после нескольких успешных релизов все подуспокоились.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Информация

Наименование
ООО «Райк Ру»
ИНН
7802810683
Сайт компании
www.wrike.com
На Хабре с
Дата регистрации
2006
Размер компании
1 001–5 000 человек
Место нахождения
США
Представитель
Wriketeam