Шрифт:
Огромная популярность методологий гибкой разработки привела многих к мысли, что приложения можно (и даже предпочтительно!) проектировать по ходу работы. Эпоха предварительного написания сложных, исчерпывающих технических спецификаций ушла навсегда! Новая школа призывает поставлять продукт рано и часто. Одна строка эксплуатируемого кода полезнее 10 строк у вас в голове. Звучит слишком хорошо, чтобы быть правдой… во всяком случае в том, что касается данных.
В то время как бизнес-логика и пользовательские интерфейсы эволюционируют довольно быстро, структурам данных и их отношениям это обычно не свойственно. Следовательно, очень важно с самого начала четко определить модель данных как на структурном, так и на аналитическом уровнях. Миграция данных из одной схемы в другую «на месте» в лучшем случае сложна, всегда занимает много времени и часто чревата ошибками. Если с ошибками уровня приложения еще можно какое-то время мириться, ошибки в базе данных могут привести к катастрофическим последствиям. Даже если вы нашли и исправили ошибку проектирования на уровне данных, это не восстановит поврежденную информацию.
Надежная модель данных — это такая модель, которая гарантирует безопасность сегодняшних данных и может расширяться для данных завтрашних. Гарантировать безопасность означает обеспечить неуязвимость для ошибок, которые все равно (сколько бы усилий вы ни приложили) проникнут в вечно изменяющийся прикладной уровень; поддерживать ссылочную целостность данных; задавать ограничения предметной области везде, где они известны; выбирать подходящие ключи, которые помогут обеспечить ссылочную целостность и соблюдение ограничений. Обеспечить расширяемость означает правильно нормализовать данные, чтобы модель данных можно было легко дополнить новыми архитектурными уровнями, не прибегая к использованию всевозможных лазеек и обходных путей.
База данных — последний страж, охраняющий ваши драгоценные данные. Прикладной уровень, эфемерный по своей природе, не может следить за собой сам. Для того чтобы база данных обеспечивала необходимую защиту, модель данных нужно спроектировать так, чтобы она отвергала неподходящие данные и не позволяла создавать отношения, не имеющие смысла. Ключи, отношения по внешнему ключу и ограничения предметной области, описанные в схеме, лаконичны, понятны, легко проверяются и в конечном итоге самодокументируемы. Правила предметной области, закодированные в модели данных, также имеют физический, долгосрочный характер; они не теряются при изменениях в логике приложения.
Чтобы извлечь из реляционной базы данных максимальную пользу, то есть сделать ее полноценной частью приложения, а не просто хранилищем данных приложения, необходимо с самого начала хорошо понимать, что же вы создаете. По мере развития вашего продукта будет совершенствоваться и уровень данных, но в каждой фазе развития он должен сохранять свой статус Крепости. И тогда вы сможете довериться ему и с уверенностью возложить на него ответственность за перехват ошибок с других уровней приложения — и он вас не разочарует.
Дэн Чак (Dan Chak) — директор по разработке ПО в CourseAdvisor Inc., компании Washington Post. Является автором книги «Enterprise Rails» (O'Reilly).
Руководствуйтесь неопределенностью
Кевлин Хенни
Столкнувшись с альтернативными вариантами, люди обычно полагают, что самое важное — сделать правильный выбор. В проектировании (программных продуктов или любом другом) это не так. Наличие альтернативы — признак того, что необходимо проанализировать неопределенность в дизайне системы. Используйте неопределенность как определяющий фактор для выявления тех мест, где можно отложить переход к деталям или применить разбиение и абстракцию, чтобы снизить важность проектировочных решений. Если вы жестко «прошьете» в системе первое же решение, которое пришло вам в голову, оно, скорее всего, в дальнейшем свяжет вам руки. В результате случайные решения начнут играть важную роль, а гибкость программного продукта снизится.
Одно из самых простых и конструктивных определений архитектуры дал Гради Буч (Grady Booch): «Любая архитектура является результатом проектирования, но не любое проектирование направлено на создание архитектуры. Архитектура служит представлением важных проектировочных решений, формирующих систему, причем важность здесь определяется стоимостью изменений». Отсюда следует, что эффективной является та архитектура, которая в общем случае снижает важность решений, принятых в ходе проектирования. Неэффективная архитектура эту важность увеличивает.
Если проектировочное решение может повести по одному из двух путей, архитектор должен отступить на шаг. Вместо того чтобы выбирать между вариантами А и Б, он должен подумать над другим вопросом: «Как спроектировать решение, чтобы снизить важность выбора между А и Б?». В этой ситуации интересен не выбор между А и Б, а сам факт существования этого выбора (а также то, что правильный выбор необязательно очевиден или неизменен).
Иногда архитектору приходится ходить кругами, прежде чем его озарит и он распознает возникшую дихотомию. Вы стоите у доски, обсуждая (весьма энергично) разные варианты с коллегой? Вы задумчиво бормочете «М-м-м» и «Э-э-э» над кодом, бесконечно перебирая возможные реализации? Когда новое требование или уточнение существующего требования ставит под сомнение разумность текущей реализации, перед вами неопределенность. Как реагировать на нее? Подумайте, как с помощью разделения или инкапсуляции изолировать принимаемое решение от кода, который в конечном итоге зависит от этого решения. Альтернативой этому часто становится невнятный код, который, словно нервничающий человек на собеседовании, бормочет что-то невразумительное и пытается компенсировать неуверенность множеством догадок и общих фраз. А если выбор делается с твердой, но необоснованной уверенностью, то проект на полной скорости и без оглядки сворачивает на неверный путь.
Часто возникает искушение принять «решение ради решения». В таких ситуациях вам поможет опционное мышление. [11] Если существует неопределенность относительно различных путей, по которым может пойти разработка системы, примите решение не принимать решение. Отложите конкретное решение до того момента, когда его можно будет принять более ответственно на основании реальных знаний, но не слишком надолго, чтобы не попасть в ситуацию, когда эти знания уже бесполезны.
11
Опционное мышление (options thinking) — подход к оценке эффективности проектов с точки зрения концепции реальных опционов (см., представляющий собой поиск дополнительных возможностей, не учитываемых при традиционном анализе. Опционное мышление применимо к широкому спектру проектов: слияния и поглощения, банковское кредитование, инновационные проекты и т. п. — Примеч. ред.