Definizione delle responsabilità: help!

rated by 0 users
This post has 10 Replies | 1 Follower

Top 10 Partecipanti
Maschio
Post 268
Punteggio 4.907
petrux Posted: 08-24-2010 17.37
Ciao a tutti,

innanzitutto bentornati dalle ferie (per chi ci è andato)!
Appena tornato da un fantastico viaggio nei Paesi Bassi, ho avuto il
seguento "problema di coscienza".
*Scenario*: un sistema di prenotazione appuntamenti ho una entità
Appointment:

class Appointment
{
DateTime Start { get; }
DateTime End { get; }
bool Confirmed { get; set; }
}

il mio sistema dovrebbe mandare una serie di notifiche via e-mail quando
l'appuntamento viene creato con Confirmed == 'True', quando viene
confermato, quando viene spostato/eliminato. Ora, avevo "cablato" la
generazione/invio di questi messaggi all'interno dei metodi del business
layer:

class AppointmentService : IAppointmentService
{
public void Add(Appointment a)
{
//rendi persistente 'a';
if (a.Confirmed)
; //crea il messaggio e-mail e mandalo a chi di dovere ;
}
}

Ora, il problema si pone nell'Update che può avvenire sia perché un
appuntamento viene "spostato", oppure se viene confermato. In questo
modo, il servizio dovrebbe:
- caricare dal db lo stato "persistente" dell'entità;
- confrontarla con quella "fresca";
- scegliere che tipo di e-mail inviare e poi recapitarle a chi di dovere.
Ora, mi chiedo: a questo punto non è meglio *delegare* a chi consuma il
business layer questo servizio?

Ciao e grazie in anticipo,
petrux - De Vliegende Hollander

--
  • | Punteggio Post: 35
Top 25 Partecipanti
Maschio
Post 30
Punteggio 678

Ciao Giulio,

personalmente modellerei l'AppointmentService rendendo esplicite le funzionalità di cui ho bisogno, piuttosto che esporre i metodi Add ed Update che "mi suonano" più da repository che da service. Con un'interfaccia del genere:

public interface IAppointmentService
{
    void Create(Appointment a);
    void Move(Appointment a, DateTime newDate);
    void Confirm(Appoinment a);
}

rendi esplicite le funzionalità implementate, il cliente sa esattamente cosa può fare con l'appuntamento, e tu puoi gestire tranquillamente l'invio delle notifiche via mail senza alcun problema. Come dicevo prima, i metodi Add e Update conviene infilarli nel repository..., oppure se hai bisogno di gestire una qualche validazione dei dati a livello di BusinessLogic, puoi metterli come metodi private nella classe AppointmentService, e richiamarli in modo opportuno dall'interno dei metodi Create, Move e Confirm.

Che ne pensi?

Ciao,
neronotte 

  • | Punteggio Post: 35
Top 10 Partecipanti
Post 143
Punteggio 2.560
Ciao petrux,

You wrote on 24/08/2010 :
> Ora, il problema si pone nell'Update che può avvenire sia perché un
> appuntamento viene "spostato", oppure se viene confermato. In questo
> modo, il servizio dovrebbe:
> - caricare dal db lo stato "persistente" dell'entit� ;
> - confrontarla con quella "fresca";
> - scegliere che tipo di e-mail inviare e poi recapitarle a chi di dovere.
> Ora, mi chiedo: a questo punto non è meglio *delegare* a chi consuma il
> business layer questo servizio?

cosa usi per la persistenza?

..m

--
Mauro Servienti
{C67C0157-5D98-4733-A75E-93CAEE4BADC8}
Microsoft MVP - Visual C# / MCTS
http://mvp.support.microsoft.com
blog @ http://milestone.topics.it
whynot [ at ] topics [ dot ] it
  • | Punteggio Post: 20
Top 10 Partecipanti
Post 143
Punteggio 2.560
Ciao neronotte,

You wrote on 25/08/2010 :
> Che ne pensi?

+1, anche io modellerei diversamente il "Service"

..m

--
Mauro Servienti
{C67C0157-5D98-4733-A75E-93CAEE4BADC8}
Microsoft MVP - Visual C# / MCTS
http://mvp.support.microsoft.com
blog @ http://milestone.topics.it
whynot [ at ] topics [ dot ] it
  • | Punteggio Post: 5
Top 10 Partecipanti
Maschio
Post 268
Punteggio 4.907
Buongiorno Mauro,

mauroservienti wrote:
> cosa usi per la persistenza?

NHibernate 3. Sto usando la prima Alpha ma il Linq provider è a dir poco
buggatissimo, almeno per quanto riguarda il dialect SQL Server 2008. :-(

Ciao,
Giulio
--
  • | Punteggio Post: 20
Top 10 Partecipanti
Post 143
Punteggio 2.560
Ciao petrux,

You wrote on 25/08/2010 :
> Buongiorno Mauro,
>
> mauroservienti wrote:
>> cosa usi per la persistenza?
>
> NHibernate 3. Sto usando la prima Alpha ma il Linq provider è a dir poco
> buggatissimo, almeno per quanto riguarda il dialect SQL Server 2008. :-(

leggi qui:
http://www.primordialcode.com/blog/post/nhibernate-3-extending-linq-provider-fix-notsupportedexception

potresti pensare di usare gli eventi di NH per intercettare il
"salvataggio" e mandare le mail, ad esempio cos�:
http://milestone.topics.it/blog/post/nhibernate-ipreinserteventlistener

> Ciao,
> Giulio
> --

..m

--
Mauro Servienti
{C67C0157-5D98-4733-A75E-93CAEE4BADC8}
Microsoft MVP - Visual C# / MCTS
http://mvp.support.microsoft.com
blog @ http://milestone.topics.it
whynot [ at ] topics [ dot ] it
  • | Punteggio Post: 5
Top 10 Partecipanti
Maschio
Post 268
Punteggio 4.907
Ciao Neronotte,
(e ciao Mauro)

innanzitutto grazie della risposta.

neronotte wrote:
> Ciao Giulio,
>
> personalmente modellerei l'AppointmentService rendendo esplicite le
> funzionalità di cui ho bisogno,
[cut]
> public interface IAppointmentService
> {
> void Create(Appointment a);
> void Move(Appointment a, DateTime newDate);
> void Confirm(Appoinment a);
> }
[cut]
> Che ne pensi?

Mi piace. Ma c'è un altro problema (che forse è un "falso" problema ma
tant'è): penso che il codice del metodo 'Confirm' faccia quanto segue:

public void Confirm(Appointment a)
{
a.Confirmed = true;
//update dell'entità.
}

Ora, mi chiedo: perchè è meglio fare:

IAppointmentService appService = ...;
Appointment a = ...;
appService.Confirm(a);

quando posso modificare la property 'Confirmed' visto che è get/set?
E già che ci siamo: supponiamo che un client del servizio faccia quanto
segue:

IAppointmentService appService = ...;
Appointment a = ...;
a.Confirmed = true;
appService.Move(a, ... /*una nuova data*/);

l'update che avviene necessariamente all'interno del metodo 'Move'
registra anche il cambiamento di 'Confirmed'? Se si, perdo la notifica
via mail (e bypasso l'utilizzo del metodo 'Confirm'). Se no:
a) mi spiegate come si fa? ;-)
b) come faccio poi a "rimandare" l'appuntamento in giro per il mondo
*solo* con la data cambiata e con il vecchio valore di 'Confirmed'?

Grazie e buona giornata,
Giulio

--
  • | Punteggio Post: 20
Top 10 Partecipanti
Post 143
Punteggio 2.560
Ciao petrux,

You wrote on 25/08/2010 :
> l'update che avviene necessariamente all'interno del metodo 'Move'
> registra anche il cambiamento di 'Confirmed'? Se si, perdo la notifica
> via mail (e bypasso l'utilizzo del metodo 'Confirm'). Se no:
> a) mi spiegate come si fa? ;-)

qui con gli event listener di NH vivresti felice perch� in qualsiasi
modo la cosa venga modificata prima o poi deve passare da te :-)

> b) come faccio poi a "rimandare" l'appuntamento in giro per il mondo
> *solo* con la data cambiata e con il vecchio valore di 'Confirmed'?

Non ho capito.

..m

--
Mauro Servienti
{C67C0157-5D98-4733-A75E-93CAEE4BADC8}
Microsoft MVP - Visual C# / MCTS
http://mvp.support.microsoft.com
blog @ http://milestone.topics.it
whynot [ at ] topics [ dot ] it
  • | Punteggio Post: 20
Top 10 Partecipanti
Maschio
Post 268
Punteggio 4.907
Ciao Mauro,

mauroservienti wrote:
[cut]
> > b) come faccio poi a "rimandare" l'appuntamento in giro per il mondo
> > *solo* con la data cambiata e con il vecchio valore di 'Confirmed'?
>
> Non ho capito.

Forse - "suprise surprise!!!" (cit.) - l'ho capito io. :-)
Parti da questa situazione

public class Foo
{
public Foo()
{
X = "";
Y = "";
}

public virtual Int32 Id { get; private set; }
public virtual string X { get; set; }
public virtual string Y { get; set; }
}

public interface IFooService
{
void UpdateX(Foo item, string x);
}


nell'implementazione ho:

public void UpdateX(Foo foo, string x)
{
using (var tx = _session.BeginTransaction())
{
_session.Refresh(foo);
foo.X = x;
_session.Update(foo);
tx.Commit();
}
}

così:
1. *SOLO* la modifica alla property 'X' viene effettivamente resa
persistente;
2. l'istanza 'foo' che se ne va in giro per il mondo è coerente con la
sua persistenza;
in questo modo:

Foo foo = ...;
IFooService fs = ...;
fs.UpdateX(foo, "ciao");

a questo punto, ogni modifica fatta alla 'y' non viene fatta persistere
ed è ripristinato il valore persistente (che è quello che mi serve). Che
ne dici/dite?

Ciao,
Giulio
--
  • | Punteggio Post: 20
Top 10 Partecipanti
Post 143
Punteggio 2.560
Ciao petrux,

You wrote on 26/08/2010 :
> Forse - "suprise surprise!!!" (cit.) - l'ho capito io. :-)

"A chorus line"... ?

> Parti da questa situazione

[snip]

> a questo punto, ogni modifica fatta alla 'y' non viene fatta persistere
> ed è ripristinato il valore persistente (che è quello che mi serve). Che
> ne dici/dite?

ho capito l'esempio ma non lo scopo, ma direi che mi manca il contesto.

> Ciao,
> Giulio

..m

--
Mauro Servienti
{C67C0157-5D98-4733-A75E-93CAEE4BADC8}
Microsoft MVP - Visual C# / MCTS
http://mvp.support.microsoft.com
blog @ http://milestone.topics.it
whynot [ at ] topics [ dot ] it
  • | Punteggio Post: 20
Top 10 Partecipanti
Maschio
Post 268
Punteggio 4.907
Ciao Mauro

  • | Punteggio Post: 5
Pagina 1 di 1 (11 elementi) | RSS
Powered by Community Server (Commercial Edition), by Telligent Systems