Ciao a tutti,
Mi si chiede di modellare una "casa intelligente": per ogni stanza possono esserci installati alcuni devices, ognuno in grado di compiere determinate operazioni, ad esempio:
Lampadina: On, Off, Blink
Termostato: AlzaTemperatura, AbbassaTemperatura, ImpostaTemperatura(int gradi)
La lampadina A installata nella stanza X e la lampadina B installata nella stanza Y possono però avere delle configurazioni differenti, ad esempio Lampadina_A: On, Off, Blink mentre per Lampadina_B la funzione Blink può essere disabilitata. La topologia della stanza e le varie configrazioni dei dispositivi devono essere memorizzate su un database.
La mia idea era di arrivare a qualcosa che fosse davvero object-oriented, e quindi avere una classe (ad esempio):
class Room { ... }
class LightBulb : IDevice
{
Romm Room { get; }
void On();
void Off();
void Blink();
}
Come faccio a mantenere la configurazione persistente?
Grazie in anticipo,
Giulio
--
Ciao Giulio,
mancano un po' di dettagli sul dominio/contesto, domande:
me ne verranno in mente altre :-)
.m
Ciao Mauro,
mancano un po' di dettagli sul dominio/contesto, domande: c'è un super-coso che usa/manipola i devices? il super-coso deve sapere qualcosa delle configurazione dei devices? il super-coso deve poter interrogare il divice sulle sue capability? ci sono relazioni tra i device, aka: un device prende decisioni sulla base dello stato di un altro device; la configurazione di un device cambia in base alla conf/stato di un altro; etc...;
Rispondo con ordine:
1. no, niente super-cosi. C'è un'interfaccia utente che permette di eseguire un qualche comando su un qualche device... quindi al limite possiamo considerare un service layer con delega a supercoso
2. stando al punto precedente, il super-coso delegato sa che i comandi sono abilitati o no
3. stando al punto precedente, la risposta è "sì"
4. no
Io ho elaborato una soluzione. Forse è un po' cervellotica ma a me piace. Ve la espongo e mi aspetto un giudizio impietoso. :-) L'esecuzione "fisica" dei comandi avviene mediante interazione con una centralina hardware che espone determinate API che, per quanto riguarda il funzionamento della mia applicazione, possono tranquillamente essere astratte in una interfaccia IApiCentralina che esporrà metodi come .AccendiLuce(idStanza, idLuce) e altra robaccia simile. Ho definito una interfaccia ICommand che espone un metodo .Execute() e una property .Enabled { get; set; }. A questo punto la mia classe diventa:
class LightBulb : Device { Room Room { get; } ICommand TurnOn { get; } ICommand TurnOff { get; } ICommand Blink { get; }}
e i comandi vengono consumati così:
LighBulb bulb = ...;bulb.TurnOn().Execute();
Ogni comando avrà poi una implementazione "a parte" (o giù di lì, sto anche meditando a una specie di composizione con delle Func/Action) che sa quale metodo dell'interfaccia delle API chiamare.
Per la configurazione persistente su database (sia chiaro: per me si poteva fare pure su un banalissimo XML ma ubi maior...) ho fatto così: ho mappato la classe astratta Device su una omonima tabella e poi ho seguito la strategia table-per-concrete-class (quindi una tabella LightBulb, una Termometer e così via). Ogni tabella ha una colonna per ogni comando abilitato di tipo Booleano e poi con un NHibernate.Properties.IPropertyAccessor mappo il valore ICommand.Enabled sulla colonna (anche se dovesse rivelarsi una scelta sbagliata, almeno ho avuto modo per un "deep dive" in NHibernate).
Ora stavo analizzando gli altri problemi (es: il fatto che alcuni comandi possano ricevere dei parametri di ingresso). Come modellereste la cosa?
Ciao,Giulio
p.s. il nome LightBulb è un omaggio a questi signori qua: http://grooveshark.com/s/Lightbulb+Sun/yV5m5?src=5 ;-)--