WCF e DIP, farneticazioni post-corso

Sono reduce da un corso su .NET 3.0 tenuto come al solito in modo impeccabile dai ragazzi di DevLeap. Le 2 ore di viaggio di ritorno verso casa sono state un momento di riflessione sui contenuti del corso, soprattutto su WCF (spiegato magistralmente da Paolo ) e sulle sue implicazioni, a mente "calda" e quindi probabilmente con un po' di confusione in testa. Lentamente, ho iniziato a farneticare...

DIP, Dependency Inversion Principle: Abstractions should not depend upon details. Details should depend upon abstractions. (cit. Robert C. Martin)

Supponiamo di seguire questo principio. Siamo in un contesto object oriented, e disegneremo per esempio un servizio di gestione ordini. Siccome vogliamo applicare il suddetto principio, definiamo interfacce opportune, per esempio:

public interface IOrder
{
    
string Id { get; }
    
string CustomerId { get; } 
    
//...
}

public interface IOrderService
{
    IOrder GetOrder(
string id);
    
//...
}

Ora potremo creare le opportune implementazioni delle due interfacce. Potremo con semplicità avere differenti implementazioni del servizio, differenti non solo dal punto di vista funzionale ma soprattutto infrastrutturale, avendo magari opportuni adapter dietro la stessa interfaccia che ci consentano di avere il servizio reale in process, piuttosto che remoto via remoting, o ancora sotto COM+...  e anche in WCF, no?

Forse no, almeno non in modo "naturale"... Il problema nasce da lontano, credo, ed è simile al più discusso problema di "impedenza" tra il mondo object-oriented e quello entity-relationship ben conosciuto da chi dibatte intorno agli ORM. WCF == SOA, e SOA != OO. Ma anche, WCF == .NET, e .NET == OO. Per proprietà transitiva otteniamo un bel WCF != WCF . Bel problema...

In WCF il codice precedente potrebbe diventare così (chiedo scusa per eventuali imprecisioni, vado a memoria... )

public class Order
{
    
public string Id;
    
public string 
CustomerId;
    
//...
}

[ServiceContract]
public interface IOrderService
{
    [OperationContract]
    Order GetOrder(
string id);
    
//...
}

Supponendo un modello di servizio WCF di tipo RPC (col modello "data contract" dal punto di vista che cerco di illustrare forse è anche peggio...), ecco che abbiamo 2 particolarità:

  1. non possiamo più avere un interfaccia (IOrder) come valore di ritorno, ma dobbiamo avere qualcosa di serializzabile (Order), quindi una classe concreta: il DIP va un po' a farsi benedire, faccio dipendere un'astrazione da una classe concreta, per di più di dominio e quindi potenzialmente instabile (= soggetta a cambiamenti), a meno che io non la crei ad hoc per quest'unico scopo, quindi come puro contenitore di campi senza logiche applicative, fattibile ma magari non bellissimo; e comunque la cosa mi costringerebbe probabilmente ad istanziare oggetti ad hoc al solo scopo di trasferire dati, quando magari io i miei dati potrei già averli in una forma adatta ad essere "nascosta" dietro un'interfaccia
  2. abbiamo gli attributi ServiceContract ed OperationContract sulla definizione dell'interfaccia del servizio: se quest'interfaccia dovesse essere la stessa dietro cui implemento anche versioni "non WCF" del servizio, essa sarebbe "sporcata" da dettagli concreti, non astratti, dipendenti dal framework applicativo in uso (WCF); di nuovo, un'astrazione che dipende da dettagli concreti, per mantenere la situazione pulita ed allo stesso tempo usare WCF dovrei avere due set paralleli di interfacce di servizio, e di nuovo adattatori in mezzo...

Come dicevo prima, in realtà tutto credo nasca dal fatto che ragionare SOA non è ragionare OO, ma che usiamo OO per implementare SOA. Un'interfaccia OO non è un contratto SOA, ma la facciamo lavorare come se lo fosse.

Nulla di nuovo, va bene tutto, in fondo basta saperlo e gestirlo, no? Ma allora il dubbio è: quando Microsoft dice che WCF unifica ASMX, WSE, COM+ e Remoting, in realtà ci sta un po' sviando... io con Remoting posso avere il servizio remoto usando il primo modello di interfacce, quello "ideale", con WCF no, quindi WCF rimpiazza Remoting ma con i costi visti sopra, che non è detto che siano sempre accettabili. Se poi l'esigenza non è interoperare, bensì remotizzare servizi (.NET su .NET) rimanendo su una metafora d'uso che renda "trasparente" la posizione reale del servizio, allora in definitiva WCF, che ha un milione di cose che vorrei poter usare, non riesco ad usarlo se non attraverso "accrocchi", come due set di interfacce ed un ulteriore livello di indirezione e quindi di serializzazione da creare per ogni singolo servizio. Una situazione con application server fatto con IIS e servizi ospitati via Remoting, è ovviamente realizzabile anche con WCF, ma a mio avviso non ha la stessa "pulizia" se il cardine del problema è la trasparenza della posizione del servizio rispetto al client.

Insomma, a questo punto, viva WCF ma...  lunga vita anche a Remoting!   Perchè Remoting vivrà ancora a lungo, vero?? ...vero????? 

powered by IMHO 1.3