Об идее

2015-05-25

Давайте немного посмотрим, как работают мозги системного архитектора. Например, на примере меня и одной моей идеи, которая копошится в мозге и требует быть выраженной в виде красивых диаграмм и понятного текста.

Как я уже писал, мой предыдущий подход к GTD завершился созданием своей собственной программки. Чем мне не нравились другие GTDшные программки, некоторые даже весьма неплохие? Своей жесткостью, и проистекающих из этой жесткости ограниченностью и сложностью. Все понимают GTD буквально. И в результате у нас есть задачи, задачи расположены в нескольких корзинках, у задач есть набор свойств. Количество свойств жестко задано. И все эти контексты, приоритеты, персоны и т.д. — это лишь списки, пусть и кастомизируемые. И каждой задаче можно назначить лишь один элемент из списка, включить лишь в один контекст.

Но ведь GTD, да и любая правильная система организации личных дел, должна быть гибкой. Системы бывают разными. Например, дорофеевская джедайская техника — это четыре корзинки: сегодня, на неделе, потом, плюс инбокс. Ну и, собственно, все. Правда, рекомендуемая им Micromiles еще добавляет цели (Goals), контексты и категории. А также даты, периодичность, возможность скрывать задачу до определенной даты. Причем цели сами по себе — какие-то комплексные сущности, с которыми еще надо разобраться. А у каждой задачки еще имеется справочная информация в виде текстовых заметок, чеклистов и/или вложений.

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

В общем, попытка с одной стороны упростить, уменьшить число сущностей, а с другой стороны, добавить гибкости, привела к созданию вот такой модели в этой самой моей программке.

Action-Folder Data Model

У нас есть лишь две сущности: папки и действия. Папки организованы в обычную древесную иерархию. Папки представляют собой любые измерения для группировки действий, какие вы захотите и сколько захотите. У папок есть типы, которые могут иметь специальное значение. Действия располагаются в папках как файлы. Причем одно и то же действие может одновременно находится в нескольких папках, как жесткие ссылки в файловой системе. В результате, например, завершенность действия означает всего лишь нахождение его в папке с типом "Сделано", пусть в UI это и делается простановкой галочки. Или можно, например, составить списки покупок для разных магазинов, где вы бываете. Но если вы купили колбасу в одном магазине, она будет помечена как купленная и в другом списке. Порядок действий в папке задается явно, ибо я считаю это важным.

А в Micromiles можно задавать у действий и чеклисты и просто текстовые примечания. А что, если еще уменьшить количество сущностей? Объединить папки и действия? Пусть будет лишь один Item. Вот такой.

Item

Item содержит и текстовое примечание, и упорядоченный список других айтемов — чеклист. И сам входит в дочерние списки родительских айтемов. Собственно, получается граф. Можно добавить аттачменты. А еще стоит добавить теги, вместо типов папок, чтобы различать, что у нас сделано, что инбокс, а что еще что, чтобы понятнее выражать операции над айтемами.

Item

Раз это граф, можно и мыслесхемы так выражать ;)

Item hierarchy

Как хранить эту модель? Ну можно в реляционной базе, благо в Android у нас уже есть SQLite. А можно и в документной, например, в Couchbase Lite. А проще всего, пожалуй, в графовой БД. Выделяем вопрос хранения в отдельный архитектурный слой, и принимаем архитектурное решение выбрать конкретную реализацию этого слоя позднее. В конце концов, нам нужно еще другие, более важные вопросы решить, которые можно обкатать и тупо на объектах в памяти.

Storage Layer

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

Но кроме этих базовых нужен еще набор более высокоуровневых операций. Которые будут соответствовать нажатию на одну кнопку в интерфейсе. Например, установка чекбокса на айтеме должна делать следующее: найти айтемы, помеченные тегом "сделано", скопировать данный айтем в дочерние списки всех "сделанных" айтемов. Нужно еще действие на перенос в другой список: скопировать в дочерний список другого айтема и удалить из дочернего списка текущего айтема. Это пригодится для переноса задач из одной коробки в другую. Много еще каких действий можно придумать. Собственно, набор действий, и соответствующих им кнопочек интерфейса, и даст нам конкретную реализацию, будь то классический GTD или джедайская техника, которую можно выстроить поверх этой модели. Появляется слой операций.

Operations Layer

Самое главное, чего не хватает в существущей моей программке, и что жизненно необходимо для подобной утилиты, — это синхронизация. Причем нужна не только синхронизация между различными устройствами одного пользователя, чтобы везде был один и тот же список задач, но и синхронизация между пользователями, чтобы можно было вести совместные списки. Тут нужен журнал изменений. Все действия над локальными айтемами записываются в журнал. Этот журнал передается на другое устройство. Полностью, для синхронизации между устройствами одного пользователя. Или частично, для поддерева айтемов, для синхронизации этого поддерева с другим пользователем. Как в том же Дропбоксе, расшариваем папку. На другой стороне журнал должен проигрываться и применяться к локальным айтемам. Будут конфликты. Хорошо, что в нашем случае конфликты можно легко разрешить — если с одной стороны сказали "А", а с другой сказали "Б", то пусть в списке будет и "А", и "Б".

Operation Log

Понятно, что при передаче журнала операций на некий удаленный адрес, его нужно фильтровать. Передавать только те операции, которые относятся к нужному поддереву айтемов, не передавать операции, инициированные самим этим адресом. Важно, что ведение журнала и применение входящих изменений легко могут быть отделены от собственно передачи журнала. Передавать можно как угодно, хоть через XMPP, хоть через Bluetooth. В общем, не важно. Принимаем еще одно архитектурное решение: реализуем и отрабатываем синхронизацию данных через журнал операций, откладывая решение о механизме передачи журнала на потом. Появляются еще слои.

OpLog/Sync Layers

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

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

All Layers

Гибко? Красиво? Хотите написать это на Котлине?