@PerseforeComplete

Какая нужна модель для описания каждой конкретной монеты на счету?

Есть аккаунты пользователей. У каждого пользователя есть его целочисленный счёт монет (для простоты). Я разрабатываю сервис для работы с этими монетами и столкнулся с трудностью. Дело в том, что недостаточно просто сделать что-то по типу
var user1 = new User { Money = 100 };
var user2 = new User { Money = 200 };

Монет то у каждого пользователя пишется суммарно, но каждая монета уникальна. У сервиса должен быть функционал - уметь находить историю передачи каждой конкретной монеты от пользователя к пользователю. Стало быть, представлять монеты в виде int поля не достаточно и надо выделять сущность монеты. Достаточно ли будет такой модели?
class Coin
{
    public int Id {get; set;}
    public User Sender {get; set;}
    public User Receiver {get; set;}
}
  • Вопрос задан
  • 85 просмотров
Пригласить эксперта
Ответы на вопрос 3
mayton2019
@mayton2019
Bigdata Engineer
Проще всего вести лог транзакций монет по всем пользователям. В сущности User можно оставить только баланс.
А если кто-то захочет посмотреть какие есть монеты - то можно проверить лог по пользователю и собрать отчет.

Вобщем надо исходить из предположения что такой запрос будет не очень частым.
Ответ написан
trapwalker
@trapwalker
Программист, энтузиаст
Вы смутили народ соей странной постановкой задачи.
В реальном мире смысл монеты ка краз в ее неуникальности и взаимной заменяемости с другими такими же. А у вас это не монеты, а, своего рода, токены. И если формулировать так, то станет гораздо понятнее.

У вас определённо должна быть таблица токенов и, если каждй токен кому-то принадлежит, то токен должен ссылаться на текущего владельца.
Вообще тут можно всё сделать очень по-разному в зависимости от того, какие операции и какие отчеты вам нужны чаще, а какие реже, какие агрегации надо делать.
К примеру, можно хранить у каждого токена ссылку на его текущего владельца, а в отдельном журнале историю движения токена в том виде в каком вы предложили.
Фактически это журнал транзакций передачи токенов между пользователями.

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

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

Эти три изменения должны быть в рамках атомарной транзакции. Если что-то пошло не так, то все три действия должны отмениться.

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

Да, возможны более сложные ситуации, когда вам нужно быстро получать не только баланс пользователя на текущий момент, но и баланс пользователя на любой конкретный момент времени в прошлом.
Очевидно, что вм для этого пришлось бы сделать снимок текущего состояния балансов пользователя, а потом пройтись в обратном порядке по всем его транзакциям в которых он был источником и приемником токенов и обратить все операции над копией его баланса.
Чтобы делать это быстро, то балансы пользователей на момент транзакции можно размещать в жарнале. Это избыточность, но она позволит мгновенно получать баланс любого польщователя на любой момент времени. Для этого нажно лишь найти саму старую транзакцию этого пользователя не позднее заданного времени и там будет нужное число. Этот поиск делается с логарифмической сложность.
Ответ написан
@rPman
У криптовалют типа bitcoin (не etherum) именно так и реализовано - баланс на аккаунте пользователя это сумма не потраченных выходов, т.е. буквально каждый входящий перевод (сдачи от исходящих)

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

Кстати, в этой модели способов сформировать один и тот же по сумме перевод может быть несколько (можно брать разные входящие переводы), и можно (судя по всему твоя задача именно такая?) можно формировать лишние выходы, например по каждому входу от разных пользователей создавать точно такое же количество (или объединять по пользователю) выходов.
------------------

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

Войдите, чтобы написать ответ

Похожие вопросы