L'applicazione da progettare gestisce le visite mediche di un reparto ospedaliero: pazienti, medici, visite e reparti. Di tutte le persone, quindi sia pazienti che medici, interessano nome, cognome e anno di nascita. Dei medici interessa la specializzazione (una stringa). I pazienti possono prenotare una visita presso un reparto. In seguito, la visita può venire assegnata a un medico. Ogni visita ha un codice (una stringa). Ogni paziente può prenotare quante visite vuole, ma ogni visita viene prenotata da un solo paziente. La visita è sempre e soltanto in un reparto. A un medico possono venire assegnate al massimo ottanta visite, ma non c'è un minimo. Quando la visita viene prenotata non è assegnata a nessun medico, e nel seguito può venire assegnata a un singolo medico, ma non di più. Può succedere di dover disassegnare tutte le visite di un medico dato. Un medico afferisce a uno e un solo reparto, ma non è detto che effettui visite solo per quel reparto.
Uno degli aspetti dell'applicazione è l'evoluzione delle visite. Inizialmente, una visita è Prenotata. Un evento Assegna la porta nello stato Assegnata; inoltre, questo evento assegna alla visita un medico, che è specificato nell'evento stesso. In condizioni normali, la visita diventa poi Effettuata a seguito di un evento Effettua. In caso di problemi, la visita può venire Sospesa da un evento Sospendi. Questo cancella l'assegnamento del medico alla visita. Una visita sospesa torna nello stato Assegnata a seguito di un evento Riassegna, che porta anche il nuovo medico; questo medico può o meno essere lo stesso medico a cui era inizialmente stata assegnata la visita; se è diverso, al medico a cui inizialmente era stata assegnata la visita viene inviato un messaggio di Notifica che include la visita. Una visita assegnata o sospesa può diventare Annullata se riceve un evento Annulla.
L'attività principale riceve come parametri un insieme di pazienti. Per prima cosa, crea l'insieme delle visite che questi hanno prenotato ma che sono ancora solo prenotate e non assegnate oppure sono sospese. Se non ce ne sono, si attende un certo tempo e si ripete la ricerca. Se invece ci sono, partono attività parallele. Nella prima, viene inviato un messaggio a tutti i pazienti di queste visite per informarli che la loro visita è ancora in questo stato. Nella seconda, viene inviato un messaggio al reparto di tutte queste visite per sollecitare un nuovo assegnamento. Quando la seconda sottoattività termina, si stampa una stringa che lo notifica. Questo conclude l'attività principale.
| assegnato | medico MR | visita MO |
| afferisce | medico M | reparto |
| in | visita MO | reparto |
| prenota | paziente O | visita M |
Le transizioni degli eventi Assegna e Riassegna cambiano il medico assegnato a una visita. Questo richiede la responsabilità della visita sulla sua associazione con il medico.
La prima sottoattività atomica trova un sottoinsieme delle visite di un insieme di pazienti. Deve quindi conoscere le visite prenotate dai pazienti, e qundi i pazienti devono avere responsabilità sulle visite che hanno prenotato.
La seconda attività lanciata in parallelo sollicita i reparti delle visite. Quindi la visite hanno responsabilità sulla loro associazione con i reparti di afferenza.
InizioSpecificaStatiVisita
Stato: {Prenotata, Assegnata, Sospesa, Annullata, Effettuata};
Variabili di stato ausiliarie:
iniziale: Medico
Stato iniziale:
statoCorrente = Prenotata
medico = --
FineSpecifica
InizioSpecificaTransizioni Visita
Transizione: Prenotata → Assegnata
Evento:
Assegna(medico:Medico)
Condizione:
nessuna
Azione:
pre: nessuna
post: this.medico = medico &&
iniziale = medico
Transizione: Sospesa → Assegnata
Evento:
Riassegna(medico:Medico)
Condizione:
nessuna
Azione:
pre: iniziale != null
post: this.medico = medico &&
(medico == iniziale || nuovoevento = Notifica{mitt: this, dest:iniziale})
FineSpecifica
Condizione e pre sono entrambe condizioni booleane. Quando sono false:
In questo caso, l'evento di riassegnamento non va inviato a una visita che non ha mai ricevuto un evento di assegnamento, che rende la variabile ausiliare non vuota. La precondizione iniziale != null viene resa vera dal precedente evento di assegnamento.
Nonostante quello che sembra, anche la postcondizione è una condizione booleana: indica una condizione che sarà vera dopo che l'azione è stata eseguita. Non è un comando (“fai questo”) ma una affermazione (“alla fine della transizione, questo sarà vero”). Si può immaginare di usarlo in un programma che verifica i comportamenti inviando l'evento e verificando che la postcondizione sia falsa; se lo è, segnala l'errore.
L'unica variabile ausiliaria è il medico a cui era stata inizialmente assegnata la visita, essendo l'unico dato che:
Deve essere mantenuto perché serve per inviare il messaggio di notifica dopo una sospensione e un riassegnamento, e non è sempre memorizzato nelle classi dati visto che viene cancellato dall'evento di sospensione.
Principale(Set<Paziente>): Attesa(Set<Paziente>) : Set<Visita> Informa(Set<Paziente>): Sollecita(Set<Visita>): Fine():
L'attività prende un insieme di pazienti e trova le loro visite che non sono ancora o non sono più assegnate. Quindi ha come parametro di ingresso un insieme di pazienti e di uscita un insieme di visite.
Per le attività Informa e Sollecita non è richiesta l'implementazione, ma la segnatura sì. I requisiti dicono quali sono i loro dati di input e output:
InizioSpecificaAttivitaAtomica NonAssegnate NonAssegnate(pazienti: Set) : (visite: Set ) pre: nessuna post: visite = {visita | (visita.stato == Prenotata || visita.stato == Sospesa) and ∃ paziente . (paziente.visita == visita and paziente ∈ pazienti)} FineSpecifica
Come per le transizioni, anche le precondizioni e postcondizioni della attività sono condizioni booleane. Questa sottoattività atomica non ha precondizioni, mentre la postcondizione è che il risultato visite sia l'insieme delle visite prenotate o sospese dei pazienti dell'insieme. Quindi ogni sua visita:
L'associazione prenota collega ogni visita con il paziente che l'ha prenotata. Una visita ha un solo paziente, ma un paziente può prenotare più visite. È una associazione con molteplicità arbitraria dal lato dei pazienti e singola dal lato delle visite. Per questo i metodi hanno nomi diversi: Visita.setPrenota() e Paziente.aggiungiPrenota(). Essendo anche una associazione a responsabilità doppia, questi metodi chiamano entrambi lo stesso metodo di aggiunta ManagerPrenota.aggiungiPrenota() del manager.
La stessa cosa vale per le cancellazioni.
Ogni evento ricevuto da Visita causa la creazione di un nuovo oggetto VisitaFired. L'oggetto è quindi diverso per ogni evento, non è sempre lo stesso. I dati che vanno mantenuti da una transizione all'altra non si possono quindi memorizzare né nella classe VisitaFired né nel suo metodo esegui. Vanno memorizzati nella classe Visita. Questo vale in generale per tutte le variabili ausiliarie, che sono per definizione i dati da mantenere fra una transizione e l'altra e che non sono sempre memorizzati nelle classi dati.
Vengono fornite solo per permettere la compilazione delle altre. È un errore scriverle nel compito da consegnare in quanto non richiesto dalle specifiche.