I'm writing a quite simple application that deals with hotel rooms reservation. I've got a problem at one stage.I'm processing a queue of orders. For every order one of the receptionists should choose a room (one or none at all) for the client according to his strategy. That's why I decided to go with Java Optional. The problem is that if there are simply no free rooms at the desired date the order should be cancelled, but if there are some rooms available and none of them fit to the receptionist's strategy that order should be put back to the queue.Choosing rooms definitely should be receptionist's duty. What do you think is the best way to deal with that problem in a clean way? Should I throw an exception instead of returning empty Optional when there are no rooms at date? Unfortunately, exceptions aren't usually a good solution for controlling the code flow.Code fragment:    Optional<Room> selectedRoom = receptionist.chooseRoom(rooms,                                                           order.getQuestionnaire());    boolean decision = selectedRoom            .map(room -> receptionist.askClient(order.getClient(),                                                 room,                                                order.getQuestionnaire()))            .orElse(false);    if (shouldProcessAgain(order, selectedRoom.isPresent(), decision)) {        orders.add(order);    }
OOP design problem. Two kinds of empty Optional
java;object oriented;coding style
I think you could model it in two ways:Option 1: Using an wrapper + enum for the receptionist response:enum ReceptionistDecision {    BOOK_ROOM,    NO_ROOM,    RETURN_TO_QUEUE,}class ReceptionistResponse {    ReceptionistDecision Decision;    Optional<Room> Room;    ReceptionistResponse(Room room) {        ...    }    ReceptionistResponse(ReceptionistDecision decision) {        ...    }}Option 2: Or you could an interface class, and make each of the responses inherit from it. Something like:interface class ReceptionistResponse {}class ReturnToQueueReceptionistResponse implements ReceptionistResponse {}class NoRoomsBookedQueueReceptionistResponse implements ReceptionistResponse {}class RoomBookedReceptionistResponse implements ReceptionistResponse {    Room BookedRoom;}The chooseRoom method would be:ReceptionistResponse chooseRoom(List<Rooms> allRooms, Questionnaire questionnaire) {    if (/* all rooms are full */) {        // Option 1        return new ReceptionistResponse(ReceptionistDecision.RETURN_TO_QUEUE);        // Option 2        return new ReturnToQueueReceptionistResponse();    }    if (/* Choose no rooms */) {        // Option 1        return new ReceptionistResponse(ReceptionistDecision.NO_ROOM);        // Option 2        return new NoRoomsBookedQueueReceptionistResponse();    }    if (/* Choose some room */) {        // Option 1        return new ReceptionistResponse(choosenRoom);        // Option 2        return new RoomBookedReceptionistResponse(choosenRoom);    }}And the client code for option 1:ReceptionistResponse response = receptionist.chooseRoom(rooms, order.getQuestionnaire());// options 1if (response.Decision == ReceptionistDecision.RETURN_TO_QUEUE) {// option 2if (response instanceof(ReturnToQueueReceptionistResponse)) {    orders.add(order);}