Comments 63
— Сложность уникальную — когда мы делаем что-то сильно новое и большая часть наших решений уникальна.
— Сложность стандартизованную — когда мы используем сложные инструменты и технологии, но эти технологии отлажены уже многократным использованием в других проектах.
Вот со стандартизованной сложностью все не так страшно. Да, используемая библиотека может быть мега-сложной внутри, но если она уже была оттестирована и отлажена на сотнях проектов, то проблем от нее обычно мало.
А с уникальной сложностью по-возможности надо бороться, либо переводя ее в стандартизованную (используя готовые блоки), либо максимально упрощая архитектуру проекта, чтобы он был четкий и понятный.
Да, кто-то должен заниматься поддержкой и на самом глубоком уровне, но:
— таких людей нужно значительно меньше, по сравнению с теми кто просто использует инструмент
— такие люди имеют более узкую специализацию, каждый в своей сфере
Примеры такой стандартизованной сложности:
— JQuery для новичка будет очень сложен, если лезть в его внутренности, но в этом новичку нет необходимости, он может им пользоваться через простые методы.
— Точно также и автомобиль, например, внутри устроен очень сложно, но для того чтобы просто ездить, знать его внутренности досконально нет необходимости, достаточно освоить достаточно простые органы управления и знать ограниченя (углы поворота, тормозной путь и т.п.).
А вот если решение на года/на много раз — тот тут я сложности боюсь. Из головы это вылетит, и потом будет сложно дорабатывать/поддерживать/эксплуатировать. Тут лучше иметь простое решение. Каждый раз городить огород дорого.
Из этой же оперы — готовые решения (код, алгоритмы, формулы, методики — это может быть любая инженерная сущность), которые можно применять, не понимая, как они работают внутри.
Какое-то странное у вас понимание борьбы со сложностью. Получается что технологии, созданные для борьбы со сложностью, вдруг начали делать решение сложнее — а технологии, которые сложность "принимают", делают все проще… Какая-то борьба в минус получается.
Правильная борьба со сложностью — это когда решение становится проще для реализации и для понимания, а не сложнее.
«Старый» путь тотального огораживания и формализации до определённого момента выгоднее, но по мере роста количества сущностей и связей между ними, издержки на него начинают превышать выгоду.
Тут уже себя проявлет «новый» подход, экономя ресурсы за счёт гибкости.
Напротив, формализация и огораживание начинают работать после некоторого момента — когда спецификация и документация перестает помещаться в голове у разработчика. В этот момент они либо где-то записываются — либо безвозвратно теряются, и с этого момента код начинают называть ругательным словом legacy.
1. Начинают работать сразу, поскольку небольшую предметную бласть всегда можно формализировать у огородить.
2. Чем больше предметная область, тем сложнее её формализировать.
3. В какой-то момент форамлизация становится слишком дорогой.
В этот момент мы либо продолжаем попытки формализировать и сложность начинает увеличиваться из-за ошибок в формализации либо отказываемся от полной формализации. Формально, это значит что мы просто не пытаемся предусмотреть всё и заранее закладываем необходимость изменений и доработок в системе по мере их обнаружения. Иными словаим, принимаем, что система не совершенна и всегда будет требовать доработок.
Проблемы с поддержкой старого кода как раз возникают (сильнее чем в других) в системах, которые пытались формализовать больше необходимого, что привело к потере гибкости и проблемам с изменением. Если же система заранее готовилась под эволюционное развитие, то проблем остаются те же, а внесение изменений упрощается (как и затраты на первоначальную разработку, поскольку формализаци дорого обходится). Правда, в этом случае страдает чувство прекрасного, поскольку неформализованная система никогда не будет восприниматься законченной или идеальной (по крайней мере, в духе «старой» философии).
Правильная борьба со сложностью — это когда решение становится проще для реализации и для понимания, а не сложнее.
Все зависит от точки отсчета.
Смотрите, допустим есть математическая задача.
Для ее решения можно написать уникальное решение, допустим в 100 строк кода.
А можно взять математический пакет в котором 100 000 строк кода, но лично нам для решения задачи надо написать 1 строку.
Вот если оценивать общую сложность системы — решение с математическим пакетом на порядки сложней, а в практической реализации оно на порядке проще, так как решение в нем уже фактически есть, его надо просто вызывать.
Нельзя говорить, что XML — "жесткий" формат, а JSON — "гибкий". На самом деле все совсем наоборот. Возьмем для примера вот такие фрагменты:
<products>
<product ... />
<product ... />
<product ... />
</products>
{ products: [ ..., ..., ... ] }
И там, и там — сериализованный массив из трех элементов. Теперь попробуем добавить немного метаданных:
<products m:foo="foo">
<product ... />
<product ... m:bar="bar" />
<m:baz />
<product ... />
</products>
{
products: {
foo: 'foo' ,
items: [ {
type: 'product',
data: ...
}, {
type: 'product',
bar: 'bar',
data: ...
}, {
type: 'baz'
}, {
type: 'product',
data: ...
}
]
}
}
В случае XML удалось добавить метаданные, сохранив исходную структуру. Если скормить такое документ старому коду — тот может вовсе не заметить лишних метаданных! В случае JSON пришлось радикально менять схему данных, потому что мета-информация туды уже не влазила.
Именно XML является гибким форматом, который из-за своей гибкости бывает довольно сложен. А JSON — это простой жесткий формат, в котором, во-первых, нет ничего лишнего — а во-вторых, он хорошо укладывается именно в задачи сериализации простых структур данных, за что он и получил распространение.
Переход от XML к JSON — это именно продолжение борьбы со сложностью, а не ее принятие.
Это разные гибкости. В приведённом Вами коде XML действительно более гибкий, если рассматривать изменение минимального примера.
В то же время, описание минимального примера на XML дольше и сложнее, чем на JSON.
Поэтому сравнивать минимальный JSON и XML некорректно. Надо сравнивать структуры одинаковой сложности. В этом случае первый пример с JSON будет выглядить следующим образом:
{
products: {
items: [ {
type: 'product',
data: ...
}, {
type: 'product',
data: ...
}, {
type: 'product',
data: ...
}
]
}
}
Добавление параметров в этом пример не сложнее, чем в XML. В то же время JSON позволяет не писать лишнего, если оно не надо.
Это как раз то, про что я говорю: XML заставляет разработчика сразу огородиться формализмами от внешей среды и от всевозможных проявлений сложности, а JSON позволяет сделать это же, но не заставлет. Таким образом, разработчик получае выигрыш во времени разработки и её сложности, поскольку огораживает только то, что потребуется и так как потребуется.
Я сравнивал два фрагмента, которые требуют от разработчика одинакового времени на придумывание и реализацию. В то же время как раз явное добавление type: 'product'
требует от разработчика лишний усилий и съедает его время.
Фактически же,
type: 'product'
является аналогом <product/>
, который писать не обязательно, а если необходимо, то можно записать несколькими разными способами, в зависимости от потребностей.Раньше во главу угла вставала гибкость при сопровожении. Теперь же, важнее быстро и эффективно реализовать исходное задание, на то, чтобы обеспечить гибкость изменения каждой части реализации надо затратить слишком много ресурсов. И далеко не везде эта гибкость потребуется.
Поэтому, выгоднее не волноваться по поводу гибкости поддержки везде где можно, а закладывать её явно только в местах, где она потребуется с наибольшей вероятность.
Поддержка других мест (без заложенной гибкости) выглядит дороже если сравнивать со стоимостью добавления гибкости при разработке для конкретной сущности. Но фактически будет дешевле, поскольку нельзя предугодать где эта гибкость потребуется. Выгоднее упростить реализацию (условно) 100 сущностей предполагая, что в паре из них будут проблемы с гибкостью и потратить часть секономленных ресурсов на решение конкретных проблем.
Выходит, чистый код, SOLID, и т.п. — это «старая школа борьбы со сложностью», а "$%-як, $%-як и в продакшен" — новая школа.
Надо знать меру и делать просто, но так, чтобы можно было впихнуть что-нибудь посложнее.
В контексте данного примера. Вместо того, чтобы сразу делать получение видов продуктов из БД, интерфейсы для их редактирования и прочее, можно реализовать функцию get_products, а в ней их захардкодить или загружать из конфигов.
Потому как не ясно что с ними будет. Может потом вообще исчезнет понятие вида продукта, или будет несколько разных наборов видов, может через год потребуется добавить 1 вид и этим всё ограничится.
И по XP именно так — вначале прибиваем гвоздями два вида. Появился ещё один вид — делаем рефакторинг. Поскольку у нас уже есть все тесты, при рефакторинге мы не теряем качество.
Разумеется, XP не универсален. Но к каким-то задачам он подходит.
Совершенно согласен. Более того, в случае например XML чрезмерно сложным иногда является вовсе не сам формат (именно гибкий, а не жесткий), а скорее попытки его описать, а именно XSD. Но при этом существует например RelaxNG, где все вовсе не так сложно.
XSD — на самом деле тоже довольно простая вещь. Сложным является сам XML когда библиотека для работы с ним не абстрагирует программиста от низкоуровневых тонкостей формата.
Например, популярной ошибкой тех, кто работает с XML, является завязывание на конкретные имена префиксов вместо пространств имен. Откуда рождаются веселости вроде "наш сервис работает с любой версией SOAP, главное чтобы корневой элемент имел префикс soap:
". А если бы библиотека вообще не показывала префиксы у элементов, а показывала только локальные имена и пространства имен — такой ошибке было бы неоткуда взяться.
XSD — она простая, но тупая, если не сказать больше. Попробуйте описать тривиальную в общем-то вещь — когда свойство элемента может быть как дочерним элементом, так и атрибутом. Вряд ли у вас такое выйдет. При этом само по себе это элементарно же описывается в том же RelaxNG.
Ну и валидность в итоге очень часто в XSD не укладывается, потому и применяется для этого же широко XSLT, которая в общем-то не для валидации — но просто более гибкая, и поэтому можно научить и таким трюкам. Потому и понаписаны такие вещи, как схематрон и т.п.
языки с динамической типизацией
Но почему-то по мере взросления Python обзавелся type hiting,
появился TypeScript и т.п.
На мой взгляд, заигрыванание со статической типизацией без чёткого плана (а его нет) — самая большая проблема Python.
Аналогично из жизни — УАЗик проезжает там, где ЛендКрузер вязнет. Сложное удобно, а простое надежно.
Взято из рекомендованной вами книги — «Путешествие по системному ландшафту»
Т.е. со сложностью можно бороться чисто психологически.
Еще известен такой феномен как возрастной кризис, ускорение субъективного времени и страх потери производительности.
Это все складывается и тогда возникают теории катастрофического разрыва Йадерлунда (взято из той же книги)
Я в это не верю. Тот же ИИ как раз и не допустит разрыва.
Всегда были люди, которые копипастили с условного SO, и оно работает — «магия». А были люди, которым непременно надо разобраться на 3 слоя глубже, чем используемый уровень абстракции.
Автор, возможно, переходит из 1-й категории во 2-ю, т.к. не успевает за всем следить.
Другая мысль, насчёт типизации, гибкости и прочего NoSQL у меня вызвала ассоциации с недавним случаем. Для pet-проекта я придумал классный алгоритм, структуры данных и сел это всё кодить. Всё как положено, надёжно, на века, с микро-оптимизациями. А когда я закончил и удовлетворённо запустил это, оказалось, что на реальных данных ну вообще всё не так, и надо в корне концепцию менять.
То есть, надо было убить в себе перфекциониста и сделать какашку из скотча и синей изоленты, чтобы сразу понять, что идея неверная. А не тратить несколько вечеров.
Плюс, молодые да зеленые не понимают зачем вообще нужны фреймворки, либы и языки. Они думают это чтобы было круто и весело, «зацените какой я странный способ запилил», для того чтобы придерживаться какой-то идеологии «ООП/ФРП это круто, все это поток, все живое» и т.п. Они тупо не понимают истории — это все было сделано для того чтобы бороться со сложностью.
Многие сложности, такие как нехватка памяти или скорость были решены на железном уровне, многие методологии потеряли актуальность, и вместо решения проблемы сложности они наоборот усложняют. Взять ООП. Когда-то это был прорыв, он помогал как-то решить проблему пользовательского интерфейса в условиях ограниченной памяти. Теперь памяти достаточно, а идея расшаренных изменяемых объектов стоит поперек дороги к многозадачности. В то же время у нас до сих пор есть идеологи ООП, которые строчат книги и курсы о том как это здорово когда к переменной можно присобачить функции и анимировать ее, каким умным можно выглядеть произнося «это паттерн „стратегия“».
Теперь не так важно бороться со сложностью, всегда можно купить в десять раз больше серверов и нанять в десять раз больше программистов.
Но в стартапах и ИТ-компаниях спрос на упрощение все еще теплится, взять тот же стековерфлоу, когда я узнал сколько у них серверов, то хохотал до слез. Компании вроде убера — это по сути не ИТ компании. Это обычные бизнесмены которые научились получать прибыть используя ИТ как канал. Их продуктом не является софт.
— сложность построения;
— сложность системы как таковой.
Может быть сложность построения снижается за счет возрастающей стандартизации, универсальности. Которая в свою очередь является следствием возросшей сложности систем как таковых.
Это в свою очередь позволяет строить (мириться со сложностью) все более сложных систем. И так далее.
Мир (в лице заказчиков, бизнеса) ставит сложные задачи, сложность решения его (их) мало интересует, их интересует эффективность этого решения (ROI). А вот для повышения эффективности наша, разработчиков, подзадача управлять сложностью.
Этой статьёй я хотел сверить свои мысли с людьми, чтобы понять не туплю ли. Вообще, думал куда меньше людей со мной согласится и готовился к сливу кармы :-D
Если появится идея во что полезное эти мысли можно развить, постараюсь это сделать.
«такие гиганты, как гугл и фейсбук разработали %FrameworkName% или %PseudoLibName% и используют это у себя, значит и у нас с коллективом в сто раз меньше человек это тоже подойдёт». А решения, зарекомендованные временем клеймят «устаревшими». Живой пример — веб фронтенд. Грустно.
Причём тут страхи? Ничего лично, только бизнес. Разработка своих инструментов управления сложностью требует ресурсов, которые могут быть потрачены на решения бизнес, а не технических задач.
откровенно говоря во фронте сейчас хорошо как никогда. Да и в целом мир javascript и ноды сейчас неплохо держится. То о чем вы говорите — это скорее результаты использования js там где его не использовали ранее. А во фронте — перенос приложений с десктопов в облака и всякие SPA. Тут да, есть немного, но это не следствие желания быть модными — это всего лишь поиск путей. А вот «решения, зарекомендованные временем» никто не будет списывать только во возрасту — бизнес умеет считать деньги а программисты — время и нервы. Если решение дает результат — оно в обойме, если нет — ничего личного )
Изменение восприятия сложности