Я пишу MUD-сервер в Haskell (MUD = Multi User Dungeon: в основном, многопользовательская текстовая приключенческая/ролевая игра). Данные/состояние игрового мира представлены примерно в 15 различных IntMap
s. Модный блок трансформатора выглядит следующим образом: ReaderT MudData IO
, где тип MudData
- это тип записи, содержащий IntMap
s, каждый в своем собственном TVar
(я использую STM для concurrency):
data MudData = MudData { _armorTblTVar :: TVar (IntMap Armor)
, _clothingTblTVar :: TVar (IntMap Clothing)
, _coinsTblTVar :: TVar (IntMap Coins)
... и так далее. (Я использую объективы, поэтому подчеркивания.)
Некоторые функции нуждаются в определенных IntMap
s, тогда как другим функциям нужны другие. Таким образом, наличие каждого IntMap
в своем собственном TVar
обеспечивает детализацию.
Однако в моем коде появился шаблон. В функциях, которые обрабатывают команды игроков, мне нужно читать (а иногда и позже писать) на мой TVar
в монаде STM. Таким образом, эти функции заканчиваются наличием помощника STM, определенного в их блоках where
. У этих помощников STM часто есть несколько операций readTVar
, поскольку большинству команд необходимо получить доступ к нескольким IntMap
s. Кроме того, функция для данной команды может вызывать несколько чистых вспомогательных функций, которые также нуждаются в некоторых или всех IntMap
s. Эти чистые вспомогательные функции, таким образом, иногда приводят к множеству аргументов (иногда более 10).
Итак, мой код стал "замусорен" множеством выражений и функций readTVar
, которые принимают большое количество аргументов. Вот мои вопросы: это запах кода? Не хватает ли какой-либо абстракции, которая сделает мой код более элегантным? Есть ли более идеальный способ структурирования моих данных/кода?
Спасибо!