Так как я изучаю испанский в данный момент, я делаю очень простое приложение Flashcard.
Приложение имеет две концепции:
- Сами карты. Две струны, одна спереди, другая сзади. Кроме того, каждая карта помечена тегами 0-m. Например. теги для данной карты могут быть
["spanish" "verb"]
. - Профили. В профиле хранятся две вещи: какие карты включаются путем определения тегов и «оценка знаний» для каждой карты.
Приложение работает, просто выбрав профиль для практики, выдает лицевую сторону карты с наименьшим баллом знаний. Когда пользователь готов, он показывает обратную сторону. Затем пользователь вводит, запомнил ли он эту карту, что изменяет оценку знания этой карты.
Для тех, кто раньше использовал какое-либо приложение Flashcard, это очень тривиальная вещь.
Мой вопрос: как мне идиоматически смоделировать это в Clojure? Проблема, с которой я столкнулся, — это отношение «многие ко многим» между профилями и карточками.
Я мог бы создать карту состояния следующим образом:
{:card-universe [
{:front "Correr" :back "To run" :tags ["spanish" "verb"]}
{:front "Querer" :back "To want" :tags ["spanish" "verb"]}
{:front "La mesa" :back "The table" :tags ["spanish" "noun"]}]
:profiles [
{
:name "Spanish verbs"
:tags ["spanish" "verb"]
:cards [{:front "Correr" :back "To want" :score 7}
{:front "Querer" :back "To want" :score 10}]
}
{
:name "Spanish"
:tags ["spanish"]
:cards [{:front "Correr" :back "To run" :score 8}
{:front "Querer" :back "To want" :score 3}
{:front "La mesa" :back "The table" :score 2}]
}
]
}
Это мне кажется глупым. Допустим, я редактирую карту, потому что ошибся, тогда мне придется пройтись по всем профилям и обновить их. Я мог бы исправить это (несколько), создав удостоверения для всех карт и просто используя это вместо ссылки на карту:
{:card-universe [
{:id "c1" :front "Correr" :back "To run" :tags ["spanish" "verb"]}
{:id "c2" :front "Querer" :back "To want" :tags ["spanish" "verb"]}
{:id "c3" :front "Mesa" :back "Table" :tags ["spanish" "noun"]}]
:profiles [
{
:name "Spanish verbs"
:tags ["spanish" "verb"]
:cards [{:id "c1" :score 7}
{:id "c2" :score 10}]
}
{
:name "Spanish words"
:tags ["spanish"]
:cards [{:id "c1" :score 8}
{:id "c2" :score 3}
{:id "c3" :score 2}]
}
]
}
Это может быть немного лучше, но это все равно будет означать, что если я добавлю больше карт в данный тег, мне придется получить все карты. По сути, внешнее соединение между моей :card-universe и :cards в профиле.
Следующий вопрос, который возникает, — сохранение состояния. Я мог бы, конечно, просто сохранить это состояние прямо в файле, но если бы я расширил это до многопользовательского режима, создав веб-приложение, я бы выбрал базу данных SQL. На мой взгляд, я должен иметь возможность закодировать все это и сохранить в файл в начале, а позже иметь возможность поменять способ хранения данных, не касаясь структуры данных, которую приложение использует для работы.
Будем признательны за любые советы и опыт!
У меня такое ощущение, что приложение слишком простое, чтобы получить какие-либо преимущества Clojure. Особенно при введении базы данных, что в основном просто сделало бы это приложение CRUD.