Núcleo funcional para projeto de sistema de elevador

5

Como a arquitetura "Functional Core / Imperative Shell" de Gary Bernhardt pode ser usada para projetar software para um sistema de elevador ?

Especificamente, digamos que há alguns elevadores, cada um com botões de chamada (um por andar). Cada elevador possui sensores que informam status de velocidade, posição e botão, e um controlador que aceita instruções como subir, descer e parar. Além disso, cada andar possui sensores que informam o status dos botões para cima e para baixo.

Escolha o que for mais fácil para o pedido de veiculação, como mensagens confiáveis ou qualquer outra. E escolha o que for melhor em termos de simultaneidade (multiprocessamento, multithreading ou apenas código assíncrono).

Um avançado sistema de elevadores baseia suas decisões em mais do que apenas a posição atual, a velocidade de cada elevador e o estado dos botões de solicitação nos andares e dentro do elevador. Em particular, para fornecer instruções aos elevadores, seria necessário saber há quanto tempo vários eventos ocorreram (para melhorar a equidade) e talvez até mesmo o que a história recente foi (isso ajudaria a prever pedidos futuros).

Mas fornecer tanta informação como uma entrada para uma função pura parece muito confuso.

Estou pensando errado ou esse problema não é adequado para essa arquitetura?

Edit: como @ThomasKilian apontou, a palestra que estou me referindo pode não ser tão conhecida quanto eu pensava. Então, deixe-me expandir a questão: estou interessado em qualquer abordagem em que toda a lógica de negócios não trivial seja principalmente codificada usando o estilo de programação funcional.

    
por max 18.11.2016 / 21:28
fonte

1 resposta

2

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?

    
por 19.11.2016 / 01:33
fonte