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

╔═════════╦══════════╦════════╦════════════════════════╦════════╗
║ Attr ID ║ Group ID ║ intval ║         strval         ║ dblval ║
╠═════════╬══════════╬════════╬════════════════════════╬════════╣
║       1 ║        1 ║ 22     ║ (null)                 ║ (null) ║
║       2 ║        1 ║ (null) ║ Jolly Ranchers, Cherry ║ (null) ║
║       3 ║        1 ║ (null) ║ (null)                 ║ 3400   ║
║       1 ║        2 ║ 17     ║ (null)                 ║ (null) ║
║       2 ║        2 ║ (null) ║ Atomic Fireballs       ║ (null) ║
║       3 ║        2 ║ (null) ║ (null)                 ║ 600    ║
║       4 ║        3 ║ (null) ║ Fuzzy                  ║ (null) ║
║       5 ║        3 ║ (null) ║ (null)                 ║ 4.0    ║
║       6 ║        4 ║ 28     ║ (null)                 ║ (null) ║
╚═════════╩══════════╩════════╩════════════════════════╩════════╝

Каждая «группа» строк (обозначенная Group ID) принадлежит друг другу в логической единице. Каждый атрибут (обозначенный Attr ID) указывает, какие данные хранятся в каждой строке, и ровно один из столбцов val содержит значение атрибута, в зависимости от того, какие это данные. В приведенной выше таблице Attr ID из 1 указывает на количество коробок в партии конфет. Attr ID 2 указывает тип конфет, а Attr ID 3 указывает примерное количество конфет в коробке. В приведенной выше таблице мы видим две партии конфет. Теперь здравомыслящий технолог может представить это в виде структуры, которая выглядит примерно так:

╔════╦═══════════╦════════════════════════╦══════════════╗
║ ID ║ box_count ║     description        ║ appx_candies ║
╠════╬═══════════╬════════════════════════╬══════════════╣
║  1 ║        22 ║ Jolly Ranchers, Cherry ║         3400 ║
║  2 ║        17 ║ Atomic Fireballs       ║          600 ║
╚════╩═══════════╩════════════════════════╩══════════════╝

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

Учитывая это, как бы вы ответили на вопрос типа «Каково среднее количество коробок для поставки конфет с разбивкой по типам?»

Для схемы sane вы можете написать код SQL, который выглядит следующим образом:

select avg(box_count) as avg_boxes, description
from candy_shipments
group by desc
order by desc

Что касается другого… Я не знаю, как работать с SQL. Но он «гибкий». Мы можем хранить любые данные, которые захотим. Однако удачи в получении данных.

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

╔═════════╦═════════════════╦═══════════╦══════════════════════════╗
║ Attr ID ║      Name       ║ data type ║           sql            ║
╠═════════╬═════════════════╬═══════════╬══════════════════════════╣
║       1 ║ Candy box count ║ int       ║ (null)                   ║
║       2 ║ Candy variety   ║ string    ║ select name from ...     ║
║     ... ║                 ║           ║                          ║
╚═════════╩═════════════════╩═══════════╩══════════════════════════╝

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

Внутренние платформы

База данных «yo dawg» также известна как структура базы данных EAV (сущность, атрибут, значение). Каждая строка в таблице идентифицирует объект и одно значение атрибута, относящееся к этому объекту. Он хорошо работает в нескольких очень специфических случаях, которых у нас просто не было, и плохо работает почти во всех других сценариях. Соблазн «гибкости» был настолько велик, что никто не задавался вопросом, стоит ли эта гибкость более медленной разработки, трудностей с сортировкой и исправлением ошибок, усталости и снижения морального духа.

Это предпочтение максимальной гибкости любой ценой не уникально. Его часто называют эффектом внутренней платформы. Эффект внутренней платформы — это склонность разработчиков программного обеспечения создавать реплики, часто некачественные, существующей системы, чтобы вмещающая система оставалась гибкой. База данных yo dawg — это внутренняя платформа — плохо реализованная база данных внутри базы данных — созданная для того, чтобы сохранить гибкость хранилища данных содержащейся в ней системы. Точно так же идея механизма бизнес-правил часто выступает как внутренняя платформа и, как правило, является плохой реализацией языка программирования; опять же, созданный для того, чтобы бизнес-логика содержащейся системы оставалась гибкой. Алекс Пападимолус предлагает следующий совет о том, как позволить страху перед изменениями придать вашему программному обеспечению избыточную гибкость (также известную как сложность):

Это довольно глупый страх. Весь смысл программного обеспечения (отсюда и программное обеспечение) заключается в том, что оно можетизмениться[,], что оно будет изменить. Единственный способ оградить ваше программное обеспечение от изменений бизнес-правил — создать полностью универсальную программу, лишенную всех бизнес-правил, но способную реализовать любое правило. О, и они уже построили этот инструмент. Называется С++. И Ява. И С#. И Базовый. И, осмелюсь сказать, COBOL.
(источник)

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

Но что, если они просят о гибкости?

Запрос на «гибкость» от пользователя или заинтересованного лица обычно имеет доброжелательные намерения. Кто бы мог подумать, что негибкость или жесткость лучше гибкости? Это может усложнить взаимодействие с заинтересованными сторонами, когда отказ от излишней сложности может показаться бестолковым или обструкционистским. Вот несколько примеров того, как прислушиваться к «гибкости», о которой просят пользователи и заинтересованные стороны, и как помочь изменить точку зрения.

«Гибкость» означает, что я могу отложить принятие важных решений на потом; «гибкость» может выиграть мне немного времени».
Хорошие лидеры осознают ценность откладывания важных решений до последнего ответственного момента, и это может быть пользователь или заинтересованная сторона, которые просят отложить принятие решения, пока они ищут больше Информация. Если они просят вас повысить гибкость, чтобы выиграть время на принятие решений, это, вероятно, означает, что они не понимают пропорциональную взаимосвязь между гибкостью, сложностью и стоимостью. Гибкость стоит дорого. Если отложить выпуск функции невозможно, подумайте о том, можем ли мы сделать что-то простое сейчас и изменить это позже, когда у нас будет больше информации.

«Гибкость» позволяет мне вообще не принимать решения. Мы можем просто позволить пользователям самим устанавливать правила».
Абсолютная гибкость звучит как утопия; однако гораздо труднее защитить чистоту данных или обеспечить соблюдение бизнес-правил в чрезмерно «гибкой» системе. Работа в таких системах, как «база данных yo dawg», часто означает бесконечные усилия по осмыслению аморфных комков данных. Опять же, сложность обходится дорого, и здесь может быть полезен экономический аргумент. Есть еще одна метафора, которую я люблю использовать:

Jello можно использовать в любом направлении. Шарнир является гибким только в одном направлении и жестким во всех остальных направлениях. Я могу построить разводной мост с несколькими балками и несколькими петлями. Я не могу построить разводной мост с Джелло. Излишняя гибкость затрудняет создание более полезных структур.

Может быть полезно задавать наводящие вопросы.

  • «Какая вид гибкости вам нужна?»
  • «Есть ли вещи, которые вы никогда не хотели бы изменить в этом?»

Это также может помочь вести эти разговоры в контексте работающего программного обеспечения. Если вы создаете простое, «негибкое» решение, это может помочь вам сообщить о том, сколько (или как мало) гибкости требуется окончательному решению.

Сосредоточьтесь на ценности

Всякий раз, когда возникает тема «гибкости», должно быть преднамеренное решение о ценности гибкости и о том, стоит ли эта ценность дополнительных затрат на сложность, которая с ней связана. Гибкость сама по себе не более чем бесполезна — она крадет ценность. Постоянное усилие перенаправить разговор на ответ «почему это должно быть гибким?» может устранить избыточную сложность и сосредоточить внимание на рациональных, ценных решениях.