Se você encapsular seus dados em objetos e decompor suas funções adequadamente, eu acho que você poderia facilmente usar a abordagem do núcleo funcional. Imagine um objeto Floor
para acompanhar os botões pressionados em cada andar, um objeto Elevator
que controla a velocidade e os botões dentro do elevador. Para manter o controle do histórico, você pode aproveitar a imutabilidade e empurrar estados para uma pilha em vez de substituí-los. A interação entre o shell e o core pode ser algo como:
List<Stack<Elevator>> elevators;
List<Stack<Floor>> floors;
while(true) {
orders = core(elevators, floors);
runOrders(orders);
foreach (elevator in elevators) {
elevator.push(getNewState(elevator.peek()));
}
foreach (floor in floors) {
floor.push(getNewState(floor.peek()));
}
}
O código imperativo passa as ordens para os elevadores da vida real, recupera seus novos estados e empurra esses estados para as pilhas. Dentro do núcleo, você não precisa de nada não funcional.
Sim, há muitos dados a serem transmitidos, mas isso é porque você precisa de muitos dados. Qualquer código para gerenciar posições, velocidades, botões, históricos etc. será complicado. Você tem alguma razão para pensar que uma implementação imperativa seria mais simples do que uma implementação funcional transparente?