Potenziale abuso del modello di osservatore

1

Ho un oggetto MeetingRoom che contiene un elenco di Dipendenti, c'è una funzione su ogni dipendente chiamata SetMeetingDate, questo metodo deve prendere in considerazione lo stato di tutti gli altri dipendenti nella Sala riunioni, in particolare la proprietà IsReadyForMeeting.

Un singolo dipendente, ad esempio, può chiamare con successo SetMeetingDate (Date date) solo quando ogni dipendente nella ChatRoom ha impostato IsReadyForMeeting su true.

Ho pensato a un paio di modi per implementare questa funzionalità, posso fare qualcosa in cui il dipendente controlla lo stato degli altri dipendenti andando attraverso l'oggetto MeetingRoom come questo:

    public void SetMeetingDate(DateTime date)
    {
        if (!MeetingRoom.AllEmployeesAreReady)
        {
            throw new ApplicationException("all employees are not ready");
        }

        MeetingDate = date;
    }

che mi sembra avere la responsabilità nel posto sbagliato.

Un secondo approccio che posso usare è impostare un osservatore in modo che la classe Employee informi l'oggetto MeetingRoom che ha impostato una data di riunione e che la classe MeetingRoom solleverà l'eccezione se MeetingRoom.AllEmployeesAreReady è falso responsabilità per l'oggetto MeetingRoom e il codice per il dipendente sarebbe simile a questo:

    public void SetMeetingDate(DateTime date)
    {
        MeetingDate = date;

        Observer.MeetingDateAdded();
    }

E la Sala riunioni avrebbe quindi un metodo come questo:

    public void MeetingDateAdded()
    {
        if (!AllEmployeesAreReady)
        {
            throw new ApplicationException("all employees are not ready");
        }
    }

Questo uso dell'osservatore ha incontrato l'opposizione di altri sviluppatori nel mio team e posso capire perché, ma non riesco a pensare a un modo migliore per implementare il requisito, esiste un approccio facile / diverso che può essere utilizzato in questa situazione?

    
posta nickbw 03.02.2015 - 05:28
fonte

3 risposte

3

Questo non sembra un posto ragionevole in cui applicare il Pattern di Osservatore.

Quello che noto è che tutti i tuoi esempi fanno riferimento allo stato locale, quindi presumo che facciano parte di una specie di oggetto Meeting. Di conseguenza, il codice

public void SetMeetingDate(DateTime date)
{
    if (!MeetingRoom.AllEmployeesAreReady)
    {
        throw new ApplicationException("all employees are not ready");
    }

    MeetingDate = date;
}

è perfettamente valido, poiché MeetingRoom e MeetingDate sono chiaramente proprietà locali della classe "Meeting".

Se preferisci qualcosa di un po 'più indipendente, fai qualcosa del genere:

public static MeetingDate SetMeetingDate(MeetingRoom room, DateTime date)
{
    if (!room.AllEmployeesAreReady)
        throw new InvalidOperationException("All employees are not ready");

    return new MeetingDate(date, room.Employees);
}

o somesuch.

    
risposta data 03.02.2015 - 06:59
fonte
3

Dovresti andare con la tua prima soluzione.

La tua prima soluzione è migliore perché è più semplice (ma forse mostra all'utente un messaggio anziché lanciare un'eccezione se sembra più appropriata).

Head First Design Patterns lo dice meglio:

First of all, when you design, solve things in the simplest way possible. Your goal should be simplicity, not "how can I apply a pattern to this problem." Don't feel like you aren't a sophisticated developer if you don't use a pattern to solve a problem. Other developers will appreciate and admire the simplicity of your design. That said, sometimes the best way to keep your design simple and flexible is to use a pattern.

Di solito è meglio usare schemi di progettazione solo quando le tue alternative sembrano tutte troppo complicate. Lascia che KISS e YAGNI siano le tue guide quando si tratta di decidere se utilizzare un modello di design.

    
risposta data 03.02.2015 - 19:50
fonte
0

Prenderò un approccio diverso, si spera che sia più chiaro.

// This is a filter function, needlessly wordy in Java.
List<Employee> getUnreadyParticipants(DateTime meetingMoment) {
  ArrayList<Employee> unreadyParticipants = new ArrayList<>();
  for (Employee e : this.getMeetingParticipants()) {
    if (!e.readyForMeeting(meetingTime)) unreadyParticipants.add(e);
  }
  return unreadyParticipants;
}

public void setMeetingDate(DateTime meetingMoment) {
  ArrayList<Employee> unreadyParticipants = getUnreadyParticipants(meetingMoment);
  if (unreadyParticipants.size() > 0) {
    throw new InvalidOperationException(
      "Participants not ready: " + printListNicely(unreadyParticipants)
    );
  }
  // whatever else is the logic
}

I motivi:

  • Il controllo della compatibilità del tempo è preoccupazione di MeetingRoom , non Employee .
  • L'elenco dei partecipanti non ancora disponibili è disponibile per la diagnostica.
  • Non ci sono flag e altri pezzi di stato che denotano disponibilità (come .AreAllEmployeesReady ) che potrebbe non essere sincronizzata con l'elenco dei partecipanti.
risposta data 03.02.2015 - 20:32
fonte

Leggi altre domande sui tag