Challenge design Elevator [chiuso]

1

Ho bisogno di rafforzare le mie abilità OOP e quindi ho pensato di implementare un simulatore di Elevator. Inizialmente quello che sembra essere un design semplice è diventato un disastro completo e mi ha lasciato confuso sulla mia conoscenza di OOP . Di seguito sono riportate le classi di implementazione.

/**
 * 1. User enter the elevator.
 * 2. Elevator checks the maximum capacity.
 * 3. User enters the floor number.
 * 4. Elevator registers the request.
 * 5. Elevator checks the next request and stops at that floor.
 * 6. When elevator is in the halt state the door opens.
 */

enum State {
  UP,
  DOWN,
  HALT
}

enum Command {
  ALARM,
  OPEN,
  CLOSE,
  GROUND,
  FIRST,
  SECOND
}

enum Floor {
  GROUND,
  FIRST,
  SECOND
}

interface Engine {
  public void moveTO(Floor floor);
}

interface Alarm {
  public void ring();
}

interface Sensor {
  public int getWeight();
  public int shouldCloseDoor();
}

final class Panel {
  private final Command[] commands;
  private final Elevator elevator;

  Panel(Command[] commands, Elevator elevator) {
    this.commands = commands;
    this.elevator = elevator;
  }

  public void onKeyPress(Command command) {
    if (command == Command.OPEN) {
      elevator.stop();
    } else if (command == Command.CLOSE) {
      elevator.move();
    } else if (command == Command.GROUND) {
      elevator.gotoFloor(Floor.GROUND);
    } else if (command == Command.FIRST) {
      elevator.gotoFloor(Floor.FIRST);
    } else if (command == Command.SECOND) {
      elevator.gotoFloor(Floor.SECOND);
    }
  }
}

final class Door {
  private boolean final open;

  Door() {
    open = false;
  }

  public void open() {
    if (open) return;
    try {
      Thread.sleep(1000); //1000 milliseconds is one second.
      open = true;
    } catch(InterruptedException ex) {
      Thread.currentThread().interrupt();
      close();
    }
  }

  public void close() {
    open = false;
  }
}

// Handle elevator logic. Here the assumption is that the elevator has to come
// back to ground floor if there are not any pending requests. There are two
// queues which handles the floor requests, the elevator keeps moving in the
// direction of the queue until that queue is not empty. If the elevator reaches 
// the top floor and there is no pending request then the elevator comes down to
// ground floor and comes to the halting state.
class Elevator {
  public static final int MAX_WEIGHT_ALLOWED = 1600;

  private final State state;
  private final Door door;
  private final Floor floor;
  private final Queue<Floor> queueUp;
  private final Queue<Floor> queueDOwn;
  private final Engine engine;
  private final Sensor sensor;
  private final Alaram alarm;

  Elevator(Door door, Engine engine, Sensor sensor, Alaram alarm) {
    this.door  = door;
    this.queueUp   = new Queue<Floor>();
    this.queueDown = new Queue<Floor>();
    this.state  = State.HALT
    this.floor  = Floor.ZERO;
    this.engine = engine;
    this.sensor = sensor;
    this.alarm  = alarm;
  }

  public void stop() {
    door.open();
    state = State.HALT;
    engine.stop();
    System.out.println("Elevator is in stopped state.");
  }

  private void moveUp() {
    while(!queueUp.isEmpty()) {
      floor = queueUp.dequeue();
      engine.moveTO(floor);
    }
    // All up requests are served.
    state = state.DOWN;
    gotoFloor(Floor.ZERO);
  }

  private void moveDown() {
    while(!queueDown.isEmpty()) {
      floor = queueUp.dequeue();
      engine.moveTO(floor);
    }
    // All down requests served.
    state = State.UP;
  }

  public void move() {
    if (sensor.getWeight() > Elevator.MAX_WEIGHT_ALLOWED) {
      alarm.ring();
      stop();
      return;
    }
    if (!sensor.shouldCloseDoor()) {
      alarm.ring();
      stop();
      return;
    }
    door.close();
    if (state == State.UP) {
      moveUp();
    } else if (state == State.DOWN) {
      moveDOwn();
    }
    // Both the queues are empty
    state = State.HALT;
    System.out.println("Elevator is moving to floor: " + );
  }

  public void gotoFloor(Floor nextFloor) {
    if (floor < nextFloor)
      queueDown.enqueue(floor);
    else
      queueUp.enqueue(floor);
    move();
  }
}


public class ElevatorSimulator {
  public static void main(String[] args) {
    Elevator elevator = new Elevator(
      new Door(), new Engine(), new Sensor(), new Alarm());
    Panel panel = new Panel(Command.values(), elevator);

    panel.onKeyPress(Command.OPEN);
    panel.onKeyPress(Command.CLOSE);
    panel.onKeyPress(Command.FIRST);
  }
}

Ho sentito che pensare e annotare il requisito aiuta molto e ho provato anche io, ma penso di aver fallito completamente anche in questo scenario.

Domanda

  1. Buona strategia per risolvere un insieme di requisiti.
  2. Evita il sovraccarico cognitivo e concentrati sulla progettazione di alto livello piuttosto che passare a dettagli di distrazione.
  3. Elenca e gestisci le dipendenze.
  4. In generale, come affrontare un buon progetto:)
posta CodeYogi 18.07.2016 - 05:19
fonte

1 risposta

3

Stai provando a creare un design a strati.

Nello strato superiore ci sono ingressi e amp; uscite che interagiscono con i cavalieri dell'elevatore: gli ingressi sono il pannello dei pulsanti nell'ascensore e il display di quale pavimento è acceso insieme all'indicatore su / giù e agli indicatori premuti dei pulsanti. Inoltre ci sono pulsanti di chiamata su / giù su ciascun piano (e una duplicazione dei display). Questa parte è piuttosto semplice, si ha un pannello di pulsanti nell'ascensore e un insieme variabile (per piano) di pulsanti di chiamata su / giù e un display (che viene duplicato). (A meno che, naturalmente, tu non abbia esperienza o fantasia potresti provare a migliorare la funzione dell'ascensore avendo pulsanti diversi da quelli standard ...)

Nel mezzo c'è un'astrazione che nasconde i dettagli dell'implementazione, ovvero l'algoritmo che sceglie l'equità e i piani e bilancia le richieste per piano rispetto alle altre richieste per piano e alle richieste in ascensore.

Nello strato più basso, ci sono i sensori da leggere e gli attuatori da controllare. Ecco dove mi sembra che tu abbia bisogno di più rigore. Gli elementi del design mi sembrano irregolari. The Door è rappresentato da una classe mentre il motore da un'interfaccia. C'è un'interfaccia a sensore singolo. Mi aspetterei di vedere più sensori di tipi specifici. L'interfaccia del sensore ha un metodo iffy should-door-close. Devi anche chiamare chiaramente gli attuatori.

Non dovresti progettare l'algoritmo o codificare le classi finché non comprendi pienamente questo livello più basso. Devi dare qualche pensiero serio o ricerca a queste capacità, e quanto sono intelligenti. Ad esempio, il motore consentirà l'attivazione per spostare l'ascensore indipendentemente dal fatto che la porta sia aperta? Se è così, allora l'algoritmo dell'ascensore dovrà evitare di muoversi mentre la porta è aperta. In caso contrario, l'algoritmo dell'ascensore sta condividendo parte dell'intelligence e della gestione della sicurezza con un altro controller semi-intelligente, il che significa che non si dovrebbe provare a duplicare, replicare (o necessariamente memorizzare) tali capacità all'interno dell'algoritmo dell'elevatore.

Esiste anche una configurazione dell'ascensore: il più grande dei quali è semplicemente il conteggio del numero effettivo di piani, poiché per ogni piano possiamo aspettarci un pannello a pavimento per pulsanti di richiesta su / giù, per non parlare che i pulsanti del pannello dell'ascensore riflettono il conteggio del piano.

Fondamentalmente, devi decidere cosa stai modellando con il tuo codice e perché. C'è un modo di dire che non si modella qualcosa senza uno scopo: il modello non è solo guardare internamente ed ammirare, ma fare qualcosa di molto specifico esternamente. La risposta a "perché modelliamo qualcosa" è perché è necessario esibire un comportamento di risposta agli input e, in particolare, che il comportamento si manifesti nel trigger (s) degli attuatori appropriati al momento giusto (s). Altrimenti, non modellare ciò di cui non hai bisogno. Non duplicare la modellazione di qualcosa che è già stato modellato da qualcos'altro. Ad esempio, se la porta sa se è aperta o meno, quindi utilizzare tale interfaccia anziché duplicare lo stato di apertura / chiusura della porta nell'algoritmo.

Quindi, si inizia dal livello superiore e si specificano le interfacce che forniscono i pulsanti e i display. Quindi identificare i sensori e le loro interfacce e gli attuatori che necessitano di controllo e le loro interfacce. Quindi individuiamo dove si trova l'intelligenza nel sistema (cosa manca e dove deve essere), il che dipende in gran parte dall'intelligenza dei dispositivi sensore / attuatore. Quindi puoi progettare un dispositivo smart & gestore di ascensore sicuro che si trova tra il livello superiore (utente) e il livello più basso (sensore / attuatore).

Essenzialmente, devi progettare dall'esterno in (in alto e in basso prima, poi in mezzo); altrimenti, non avrai idea di cosa stai modellando (nel mezzo) e perché.

    
risposta data 18.07.2016 - 17:30
fonte