суббота, 6 ноября 2010 г.

Проектирование: построение функциональной модели

Прежде чем проектировать структуры данных, разработчик должен построить функциональную модель проектируемой системы.

В умных книжках по OOA&D рекомендуют поступать наоборот: сначала выявлять классы и объекты и лишь затем – находить операции для этих классов и объектов. Автор данного блога рекомендует не верить умным книжкам и начинать проектирование с выявления функций.

У автора есть веские основания для такой рекомендации: любая техническая система создаётся для выполнения каких-то полезных функций. Если она их не выполняет, то такая система не нужна. Согласитесь, мало кому в быту будет полезен стул со сломанными ножками. Просто потому что на нём невозможно сидеть. В программной индустрии точно также. Если программа не делает нечто полезное, её можно удалить с компьютера, чтобы она не занимала место.

Направление проектирования должно быть задано однозначно: от функций к структурам данных, а не наоборот.


Функциональная модель проектируемой системы напрямую вытекает из функциональных требований, которые, в свою очередь, могут быть описаны в виде прецедентов. Существует несколько разных шаблонов оформления прецедентов (например, здесь и здесь). Но, на мой взгляд, главное – не оформление, а – суть. Прецедент должен описывать технологию создания чего-либо полезного при помощи проектируемой системы.

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

А) Первым шагом документируем функциональные требования к модулю редактирования. Для этого возьмём пример создания пригласительной открытки в программе CorelDraw и опишем его в виде набора прецедентов.

Ниже я намеренно привожу описания всех прецедентов, чтобы заинтересованный читатель мог при желании разобраться в примере.

Описание начинается с прецедента высокого уровня, который обращается к прецедентам более низкого уровня, а те, в свою очередь, обращаются к прецедентам ещё более низкого уровня и т.д. Каждый абстрактный прецедент детализируется конкретными прецедентами. Это позволяет сократить размер прецедента и сделать его более понятным для восприятия.

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

Прецедент 1. Создать приглашение

  1. Создать дома.
  2. Создать ночной фон.
  3. Создать облака и месяц.
  4. Создать надписи.
  5. Создать отрывной корешок.

Прецедент 2. Создать дома

  1. Создать дом.
  2. Создать копию дома.
  3. Переместить копию дома на расстояние.
  4. Создать зеркальное отражение копии дома.
  5. Уменьшить размеры второго дома.
  6. Изогнуть первый дом.
  7. Изогнуть второй дом.
  8. Переместить второй дом в сторону первого дома (чтобы частично перекрывал).
  9. Переместить второй дом по Z за первый дом.

Прецедент 3. Создать дом

  1. Создать контур здания.
  2. Создать контуры окон.
  3. Залить контур здания красным цветом.
  4. Залить контуры окон жёлтым цветом.
  5. Создать антенну.
  6. Выделить все детали дома.
  7. Объединить выделенное в группу.
  8. Уменьшить размеры дома.

Прецедент 4. Создать контур здания

  1. Создать прямоугольник.
  2. ???????????????????????

Прецедент 5. Создать контуры окон

  1. Создать ряд окон.
  2. Создать дубликат ряда окон.
  3. Переместить дубликат на заданное расстояние.
  4. Создать дубликат ряда окон.
  5. Переместить дубликат на заданное расстояние.
  6. Выделить все ряды окон.
  7. Объединить ряды окон в группу.

Прецедент 6. Создать ряд окон

  1. Создать окно.
  2. Создать дубликат окна.
  3. Переместить дубликат на заданное расстояние.
  4. Создать дубликат окна.
  5. Переместить дубликат на заданное расстояние.
  6. Выделить три окна.
  7. Объединить окна в группу.

Прецедент 7. Создать окно

  1. Создать маленький прямоугольник.
  2. Создать линию, отделяющую одну треть окна от остальной части.
  3. Выделить прямоугольник и линию.
  4. Объединить выделенное в группу.

Прецедент 8. Создать антенну

  1. Создать первую (вертикальную!) линию.
  2. Создать вторую линию.
  3. Создать третью линию.
  4. Создать четвёртую линию.
  5. Создать пятую линию.
  6. Выделить все 5 линий.
  7. Объединить выделенное в группу.

Прецедент 9. Создать ночной фон

  1. Создать большой прямоугольник для фона.
  2. Заполнить прямоугольник чёрным цветом.
  3. Выделить прямоугольник фона.
  4. Поменять местоположение прямоугольника по Z (отправить на задний план).

Прецедент 10. Создать облака и месяц

  1. Создать эллипс.
  2. Разместить эллипс над домом.
  3. Залить эллипс бордовым цветом.
  4. Создать второй эллипс.
  5. Разместить второй эллипс над домом, слегка закрыв первый эллипс.
  6. Залить второй эллипс коричневым цветом.
  7. Создать круг.
  8. Расположить его над домом рядом с первыми двумя эллипсами.
  9. Залить круг светлым цветом.
  10. Преоборазовать эллипс в сектор эллипса.
  11. Изменить угол дуги сектора эллипса до полумесяца.

Прецедент 11. Создать надписи

  1. Создать надпись "NIGHT".
  2. Изменить шрифт надписи.
  3. Окрасить надпись в жёлтый цвет.
  4. Повернуть надпись на 90 градусов.
  5. Переместить надпись на чёрный фон слева.
  6. Создать надпись "PARTY".
  7. Изменить шрифт надписи.
  8. Изменить размер надписи.
  9. Окрасить надпись в белый цвет.
  10. Переместить надпись на чёрный фон снизу.
  11. Создать надпись "WELCOME".
  12. Изменить шрифт надписи.
  13. Изменить размер надписи.
  14. Изменить цвет надписи.
  15. Изменить местоположение надписи.
  16. Создать надпись "23:00".
  17. Изменить шрифт надписи.
  18. Изменить размер надписи.
  19. Изменить цвет надписи.
  20. Изменить местоположение надписи.

Прецедент 12. Создать отрывной корешок

  1. Создать прямоугольник.
  2. Поместить прямоугольник правее остального изображения.
  3. Окрасить прямоугольник фрактальной заливкой.

Б) Вторым шагом – выпишим неделимые функции (которые не представлены в виде других прецедентов), сгруппируем их по темам и представим в виде таблицы.

Получится функциональная модель модуля редактирования:

Группа
Функция
1. Создание
F1.1. Создать прямоугольник.
F1.2. Создать эллипс.
F1.3. Создать окружность.
F1.4. Создать прямую.
F1.5. Создать текст.
2. Копирование
F2.1. Создать копию фигуры.
3. Группирование
F3.1. Объединить фигуры в группу.
F3.2. Разделить группу на отдельные фигуры.
4. Размещение
F4.1. Переместить фигуру в заданную точку.
F4.2. Переместить фигуру на заданное расстояние.
5. Масштабирование
F5.1. Изменить размеры фигуры по вертикали.
F5.2. Изменить размеры фигуры по горизонтали.
F5.3. Изменить размеры фигуры пропорционально.
6. Размещение по Z
F6.1. Поместить фигуру на задний план.
F6.2. Поместить фигуру на передний план.
7. Форма
F7.1. Создать зеркальное отражение фигуры относительно вертикальной оси.
F7.2. Создать зеркальное отражение фигуры относительно горизонтальной оси.
F7.3. Изогнуть фигуру.
F7.4. Преобразовать эллипс/окружность в сектор.
F7.5. Изменить угол сектора.
8. Форматирование
F8.1. Изменить шрифт текста.
F8.2. Изменить размер шрифта.
F8.3. Изменить цвет текста.
9. Заливка
F9.1. Залить фигуру заданным цветом.
F9.2. Залить фигуру фрактальным рисунком.
10. Вращение
F10.1. Повернуть фигуру на 90 градусов.
F10.2. Повернуть фигуру на 180 градусов.
F10.3. Повернуть фигуру на произвольный угол.

Данная функциональная модель не является полной, т.к. основана только на одном примере. Её можно и нужно дополнять, описывая и анализируя другие примеры создания поздравительных и пригласительных открыток.