Всем привет! Я живу в Средней Азии и замечаю следующую картину - мои знакомые и друзья со временем переезжают заграницу. Большей частью в Российскую Федерацию. Кто-то в Америку, кто-то в Корею, Турцию, Европу и прочие благополучные страны. Их всех объединяет одно - они потратили кучу времени и энергии на процесс переезда, получение документов, разрешений и прочих трудностей. Собравшись с несколькими, самыми близкими друзьями, мы решили запилить сервис помощи переселенцам - HumanWay. В процессе обдумывания, голова просто кругом пошла - насколько сложная доменная область. Количество сущностей множилось с каждой новой мыслью и никакая бритва тут не помогала. Список необходимых действий зависит от страны исхода, от возраста заявителя, состава семьи, профессии, региона вселения и многих других параметров. Все эти данные нам надо собрать, обработать и выдать наиболее оптимальный путь.  Наша мысль пошла дальше, чтобы пользователь не запутался в таком сложном процессе, мы захотели ему помочь: дать подсказки, лайфхаки, придуманные такими же переселенцами до него, и информацию о необходимых документах кратко и в нужный момент. Чтобы реализовать задуманное нужно было какое-то особенное техническое решение. Традиционные подходы хранить свойства в колонках таблицы пользователя подходили плохо, т.к. для каждого пользователя набор атрибутов свой и количество их огромно и постоянно увеличивается по мере развития проекта. Кроме того, мало эти данные записать, нужно еще эти данные удобно проанализировать. Мне пришла идея - собирать факты. Факт - это объект реального мира - некая порция информации. Факт типизированный, т.е. если факт - "Возраст", тогда этот факт должен хранить объект типа AgeFact в котором может быть только неотрицательное целое число меньше 130 (не слышал, чтобы кто-то дожил до этого возраста, а если дожил, то решил бы в столь почтенные годы на переезд). Или например Область - RussiaRegion - справочный объект со счетным количеством объектов. Соответственно в факт "Область" невозможно записать ничего кроме области. Нраица! Так возникла идея базы данных фактов. Системы управления фактами. Нереляционной системы управления фактами. Имперской Гвардейской Штурмовой Нереляционная Системы Управления Фактами. Ух, куда занесло. Как хранить факты? Самое простое - свалим все в кучу, в простой массив. Сам тип факта является ключом. При необходимости можно добавить индекс, но пока массив небольшой, можно и прямым перебором. Сериализуем все в JSON и положим в колоночку с таким же типом в БД. Да - очень просто, но мы же только в начале пути. Как гласит один из принципов языка Python - "simple better than complex". Хорошо, информацию мы придумали как хранить, а что с этим всем делать? К хранению еще нужна система вывода выражений (в смысле вычисление ответа, а не печати на экране). Достать факт из базы, сделать вывод и произвести какое-нибудь действие. Для этого нужен свой DSL. Велосипед конечно мы строить не будем, а возьмем всеми любимый JavaScript. Запустим песочницу без состояния, будем ей кормить все собранные о пользователе данные и выражение, которое надо вычислить. Ответом будет булевый тип: да или нет. Для примера, пользователю надо напомнить взять трудовую книжку на подачу документов на программу переселения соотечественников. Но для детей подавать трудовую книжку не принято, поэтому введем ограничение по возрасту: AgeFact >= 16. Теперь встает вопрос, а как мы узнаем возраст пользователя? Со сбором фактов все довольно просто, заставим набор стандартных элементов (текстовое поле, чекбокс, поле выбора и прочие), принимать данные и записывать в соответствующий факт. Если факту не понравятся те данные, что пытаются ему скормить, он тут же ругнется. Не валидация - а красота то какая! Поля (коих может быть много типов, не только для ввода данных, но и банальное текстовое поле) объединяем в карточки, карточки объединяем в экраны, экраны объединяем в цепочки и мы получили конструктор для сбора практически любого сервиса с богатой доменной областью. Решая специфическую задачу, у нас получилось создать решение, которое позволяет быстро раскатывать интерактивные сайты. Мы сделали сайт помощи переселенцам в Россию, теперь мы задумываемся об Америке, Канаде, Корее и других странах. А вообще, мысль на переселении не кончается, любой сложный процесс со сбором справок, документов и прочих бумаг - это наш кандидат на освещение. Например, как организовать учебу за рубежом для своего ребенка? Как купить квартиру? Как устроить ребенка в детский сад? Наша основная задача - помощь людям в сложных, запутанных процессах, где есть множество тайных знаний. Поэтому мы себя и назвали - HumanWay - т.е. путь человека. Мы пытаемся осветить дорогу в сумерках бюрократии :) На все ушло каких-то полгода разработки такой веселой командой, как: Программисты 2 шт (Я и не я) Дизайнер (Чтобы было все красиво) Юрист (Для сбора информации, бланков, документов и пр.) И вот мы здесь. Сервис работает, а люди к нам не приходят...  Что мы для раскрутки? Раскидали по знакомым, чтобы те отправили знакомым и т.д. - я бы сильно не рассчитывал на этот канал раскрутки Добавились во все найденные группы переселения и даже! наш пост запинили в 3х группах! Итог: люди не особо читают запиненные сообщения. В прочих группах, админы хотят денег, что логично. Вначале нам казалось, что группы тг - это главный наш источник пользователей, но выяснилось, что у формата чата есть неприятная особенность - ваши сообщения уплывают вверх и их читает очень ограниченное количество людей. Было бы классно разработать бота, который бы мог отвечать пользователям на их вопросы - идет разработка решения, как только что-то будет (или не будет) - ждите статьи!. SEO оптимизировались, сделали статичную версию сайта, чтобы скормить поисковикам. Не опускаем руки! Мы искренне верим в сервис, что он будет полезен нашим пользователям. Просто они должны узнать о нас. Пожалуйста, пользователь, прийди. Мы все сделали, чтобы тебе было удобно. Чтобы ты смог узнать о многих подводных камнях такого сложного процесса, как переселение. Мы очень старались! Команда HumanWay