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

Я думаю, знающие согласятся, что их первый опыт программирования реального приложения (не Hello World) свелся с простому вопросу: с чего, собственно, начать? Как начать проектирование программы? Что писать-то?!

И, как правило, первый опыт — это куча кода, который потом либо забывался, либо переписывался полностью, в зависимости от нужности программы.

Я долгое время шарил по интернету в поисках рецепта проектирования, но везде все сводили к определенным моделям, которые как шаблоны, нужно было применить и на них натянуть свою программу. Для примера можно взять MVC — все знают, что это, но рекомендации, как реализовывать ее, разнятся кардинально.

И вот, однажды утром, мне пришла в голову простая мысль: а что, если программу проектировать по методу снежинки?

Что я сделал:

1. Нарисовал на листке бумаги, как выглядит программа (для консолей особой разницы нет, поймете по ходу повествования). Для примера, возьмем калькулятор.

2. Условно разделил лист бумаги на две части, в одной я начну описывать интерфейс, в другой — что собственно программа умеет делать, ее модель (бизнес-логика). Уже на этом этапе видно, что мы разделили программу на 2 части: представление и логику. При этом, если программа консольная, в представление у нас попадут команды, на которые реагирует программа и вывод, который она возвращает.
Контроллер же — это связь между частью интерфейса и моделью программы.

3. Для описания интерфейса первым делом перечисляются все однотипные элементы (например, кнопки, лейблы и прочее). Получается, уже на этом этапе мы описываем классы-родители. Например, калькулятор:

image

Красным я обвел одинаковые элементы, это меню, лейбл, текстовое поле, кнопки и радио.

Дальше я смотрю, можно ли разбить эти элементы на более конкретные? (Что, естественно, можно, так как у нас не одна кнопка). Соответственно, от кнопки я стараюсь образовать как можно меньше общих групп или, чтобы было понятнее, классов: это число-буквенные (не вычисляют, только вводят данные) и оперативные (нажатие на них может привести к вычислениям или иным операциям). Чем меньше мы образуем одновременных классов, тем больше уровень абстракции получаем, что весьма полезно может быть в будущем, я думаю все согласны с этим (удобнее будет дополнять функционал, всегда есть от чего наследовать).

Продолжая дальше разбивать на группы, мы придем к определению каждого окончательного класса, когда разбиение уже невозможно. А цепочка от него до нашей начальной программы будет цепочкой наследования. Если нас что то не устраивает, например, куда деть кнопку стирания последнего символа — мы всегда можем пройтись по дереву наследования и изменить ветвление или деление на классы. Описав интерфейс — мы получим шпаргалку для дальнейшего проектирования(мы же, в конце концов, не будем лепить пустые элементы на форму).

4. Аналогично поступаем с логикой, начиная от общего класса, все больше конкретизируя операции.
Если у нас есть какая-либо операция, уже известная, но не классифицированная, ее достаточно добавить, а потом уже вписать в выстраивающуюся модель.

Получится что-то вроде этого:

image

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

image

Если программа очень большая, сложная — всегда можно взять отдельный элемент и описать по вышеуказанному методу. Например, для многооконного приложения можно нарисовать снежинку для каждого окна. Для сложной логики — выделить глобальные операции, и поступить аналогично. К тому же, подобный метод работает не только от общего к частному, но и наоборот. Сперва мы набираем всё, что нам придет в голову, в виде кирпичиков или небольших деревьев. Если можем объединить во что то общее — мы получаем родительский класс. Если можем разбить на категории, мы получаем подклассы. И так, пока не останется кирпичиков без связей, не будет возможности разбить на подклассы и не получится снежинка.

Когда все будет сделано — можно начинать писать код. Но как его писать, это уже другая история… Впрочем, еще на этапе проектирования уже можно давать имена классам и кратко описывать их функционал.

P.S.


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

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

Комментарии (6)


  1. Scf
    07.12.2015 17:36
    +2

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


    1. keep
      08.12.2015 08:10

      Ага :) еще от пользовательского интерфейса плясать не всегда получается, ну и автора даже в диаграмме проскакивают «кнопки», «меню», «лейбл» :) так что дополнить снизу-вверх, сверху-вниз и методиками анализа предметной области и получится более общий подход… потом и про объекты вспомнить можно будет и про шаблоны)


    1. Daniro_San
      08.12.2015 09:36

      Так или иначе в большинстве случаев код приходится «подбивать» под GUI, иногда действительно разумно спроектировать интерфейс и потом написать под него код.


    1. foenicks
      11.12.2015 15:57

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


  1. DrLivesey
    07.12.2015 19:27

    Интересный метод, но как мне кажется он пригоден скорее для случаев когда функционал можно разделить на независимые части, что получается не всегда. В остальном же все очень наглядно. Спасибо за статью.


    1. foenicks
      11.12.2015 15:59

      А можно пример, когда деление невозможно? Для наглядности.