То, что происходит внутри программы очень похоже на деятельность команды из нескольких человек. У каждого члена команды есть своя задача и, скорее всего, своё «рабочее место» к которому никто кроме него не должен прикасаться. Коллеги могут давать друг другу поручения и передавать какую-нибудь информацию о рабочем процессе. Они могут просить друг у друга помощи и могут оказывать её. Как и у любой команды у них есть начальник, в задачу которого входит взаимодействие с пользователем и координация действий внутри команды.
При таком взгляде на программу она оживает, и всё происходящее внутри неё начинает обретать какие-то образы. Распределив все рабочие процессы и задачи по различным «работникам» начинаешь понимать как всё должно работать.
Исходные коды плеера, на который я когда-то потратил кучу времени, уже давно пылятся на жестком диске. Я писал это приложение в течении года когда появлялось настроение. В конце концов у меня иссяк энтузиазм и плеер был забыт. И вот недавно мне в голову пришла идея архитектуры, которая, как оказалось, отлично к нему подходит — о ней далее и пойдет речь. Я выделю «работников» в приложении, и распределю роли так, чтобы у каждого работника была чёткая, максимально простая, и понятная задача.
Знакомство
Для начала, самый главный член команды — певец. Он горланит песни по нотам, которые ему подсовывают. Естественно, в программе никакие ноты не обрабатываются — это просто замена понятию «музыкальный трек». Певцу можно поручить спеть что-нибудь, попросить остановиться, и попросить петь чуть погромче или потише. Еще, можно положить певцу ноты следующей по списку композиции, чтобы он быстро перешел от одной песни к другой.
Пока певец орёт, кто-то должен вести список песен, которые будут спеты следующими. Тут в дело вступает сортировщик. В его задачу входит вести список играемых далее композиций в соответствии с режимом воспроизведения, угодном пользователю. Когда певец допевает песню он просит сортировщика дать ему ноты от следующей. А тот либо даёт их, либо разводит руками, сообщая что список закончился, и повтора не предусмотрено. Кроме того, в любой момент начальник может сообщить, что пользователь поменял порядок воспроизведения, и сортировщику придется составлять новый список.
Сортировщик лишь хранит порядок воспроизведения и ему надо знать какие песни вообще имеются в наличии. За хранение полного списка песен и манипуляции над ним отвечает аудиотекарь (кажется есть такое слово). Чаще всего к его услугам обращается именно сортировщик, при составлении своего списка. Аудиотекарь может дать список корневых папок, список содержимого каждой папки и информацию о любом треке в аудиотеке.
Есть еще одна задача. Когда пользователь добавляет новую папку с музыкой в аудиотеку, эту папку нужно просмотреть и внести информацию о всей найденой музыке в аудиотеку. Этим мог бы заниматься и аудиотекарь, но в этом случае было бы сложно обеспечить одновременное сканирование папок и правильное функционирование аудиотеки. Пускай этим занимается поисковик — он будет накапливать все изменения, которые нужно провести и одним махом передавать их аудиотекарю, чтобы свести задержки при работе с аудиотекой к минимуму.
И последний, самый ответственный персонаж — начальник. Он отвечает за начало работы своей команды и за взаимодействие с пользователем. Он управляет интерфейсом и даёт знать остальным если пользователь чего-то хочет. Нажата кнопка паузы — начальник просит певца остановиться. В очередь добавлена композиция — начальник сообщает об этом сортировщику, и так далее. В нашем случае это скорее всего не понадобится, но еще к начальнику могут обращаться подчиненные если им нужно подсобить в чем-то, с чем они сами справиться не могут. В этом случае начальник может показать кто в команде может помочь.
Кто все эти люди?
Я ни разу не слышал о такой архитектуре, но есть вероятность, что что-то подобное уже существует. Если вы о таком слышали — буду благодарен если напишите об этом в комментариях. Несмотря на то, что я возможно изобрел велосипед, останавливаться я не буду — вдруг получится маунтин-байк.
Вернемся к делу. Надо как-то назвать исполнителей. Я думал о работниках, личностях и минионах, но думаю самым подходящим словом будет «персонаж». Этот термин достаточно обезличен чтобы назвать им и кого угодно. И бездельника и нюню и главного злодея. Каким должен быть персонаж?
Во-первых, он должен обладать некоторой свободой. Такой-же, какой обладают люди в реальной жизни. Своего сотрудника нельзя заставлять делать что-то с помощью физической силы (я за гуманный труд). Поэтому нельзя непосредственно вызывать функции объекта персонажа — это было бы похоже на «кукловодничество», а не на добровольную работу. Вместо этого он должен получать сообщения и реагировать на них по мере возможности. Получается, должны быть предусмотрены методы передачи сообщений.
Во-вторых, на каждого участника процесса должен быть выделен свой поток. Это обеспечит их независимость друг от друга.
В-третьих, чтобы потоки не портили данные при одновременном доступе к ним, необходимо предусмотреть соответствующие средства. Это несколько похоже на взаимодействие процессов в системе и на существующие там проблемы.
О сообщениях
Персонаж последовательно обрабатывает приходящие к нему сообщения. Если сообщений нет, он может простаивать или выполнять какую-нибудь фоновую работу переодически проверяя очередь сообщений.
Какими должны быть сообщения? Можно сделать один единственный тип — универсальный, который можно использовать во всех случаях, задавая нужные параметры. Примерно так же как существует универсальное понятие функции. Но я стараюсь избегать подобных решений, так как универсальность зачастую усложняет выполнение простых действий. Я предпочту три простых способа покрывающих все возможные варианты выполнения некоторого действия, одному сложному универсальному. Это, конечно, несколько усложняет обучение выполнению этого действия, но в разы ускоряет его применение и улучшает наглядность выражений. Кроме то, если действия разбиты по типам, то это означает что машина с легкостью может их различать, а это, в свою очередь, расширяет возможности автоматизации и оптимизации.
Итак, навскидку я могу разбить сообщения на три группы:
1) Задачи/поручения — кто-то хочет чтобы персонаж выполнил некоторую работу. Пример: когда пользователь жмет «play» начальник просит певца начать исполнение песни.
2) Запросы — персонаж может попросить у своего коллеги передать ему некоторые материалы. Когда просимый (должно быть такое слово) будет готов к передаче, просящий получит от него сообщение с нужными материалами. Пример: когда певцу становится нужна новая композиция он просит её у сортировщика.
3) Уведомления о событиях — может статься так, что деятельность одного персонажа будет зависеть от действий другого. Командиру надо знать когда певец меняет песню, чтобы обновить интерфейс. Для этого командиру нужно попросить певца сообщать о смене песни. А певец, в свою очередь, разошлет уведомительные сообщения всем, кто об этом попросил.
Вместе с сообщениями можно передавать какие-нибудь материалы или параметры. Фактически, разница между посылкой сообщения и вызовом функции лишь в том, что сообщения посылаются персонажам и могут выполняться отложено в то время как функции срабатывают незамедлительно и относятся к объектам.
Тут я думал расписать все сообщения, которые понимает каждый персонаж плеера, но список получился довольно большой и я решил что это довольно бесполезно. Так что я начну заканчивать.
Заключение
Представленная архитектура позволяет довольно наглядно представить многопоточное приложение. Кроме этого разбиение всех составляющих программы на объекты и исполнители делает структуру программы нагляднее. При командной разработке становится понятнее как разделить обязанности — каждый программист может взять себе по персонажу.
Получается что программа — это всего-навсего комната с несколькими работниками и рабочими материалами. Сбылась мечта программиста. Я могу объяснить как работает программа. Я уверен в том, что если концепцию легко представить, то у неё есть шансы.
This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends:
- Massacres That Matter - Part 1 - 'Responsibility To Protect' In Egypt, Libya And Syria
- Massacres That Matter - Part 2 - The Media Response On Egypt, Libya And Syria
- National demonstration: No attack on Syria - Saturday 31 August, 12 noon, Temple Place, London, UK
Комментариев нет:
Отправить комментарий