Ho lavorato per qualche settimana a un nuovo progetto web e sto realizzando che tutto ciò che sto facendo è fondamentalmente calcoli e trasformazioni sui dati, e che la maggior parte delle mie classi non contiene nessuno stato e potrebbe essere perfettamente trasformata in classi statiche con metodi statici. Quindi penso che questa potrebbe essere una buona opportunità per architettare l'applicazione seguendo il paradigma della programmazione funzionale. Ho prima fatto alcune ricerche su Internet per leggere le esperienze di altre persone che hanno provato qualcosa di simile e ho trovato un bel post di blog con alcune idee interessanti.
Tuttavia, mi chiedo come dovrei affrontare la situazione in cui si hanno più livelli di chiamate di funzioni annidate. Proverò a dare un semplice esempio per mostrare cosa intendo, prima in OOP e poi in FP.
In OOP di solito cerco di creare classi semplici che costruiscono funzionalità su livelli usando la composizione. Qualcosa del genere:
public class ClassLevel1
{
private readonly IClassLevel2 _objLevel2;
public ClassLevel1(IClassLevel2 objLevel2)
{
_objLevel2 = objLevel2;
}
public int FuncLevel1(int param1, int param2)
{
// Some operations here
var res = _objLevel2.FuncLevel2(param1) + param2;
// Some more operations here with the 'res'
return result;
}
}
public class ClassLevel2
{
private readonly IClassLevel3 _objLevel3;
public ClassLevel2(IClassLevel3 objLevel3)
{
_objLevel3 = objLevel3;
}
public int FuncLevel2(int param1)
{
// Some operations here
var res = _objLevel3.FuncLevel3(param1);
// Some more operations here with the 'res'
return result;
}
}
Quindi posso contare sull'integrazione delle dipendenze per creare le istanze e posso trarre vantaggio da qualsiasi framework di simulazione per testare facilmente ciascuna classe.
Ora immaginiamo che mi piacerebbe passare a FP e diciamo che abbiamo una funzione FuncLevel1
che internamente chiama FuncLevel2
, che internamente utilizza una terza funzione FuncLevel3
. Uno dei miei obiettivi principali sarebbe quello di strutturare il codice in modo tale che possa facilmente prendere in giro ogni funzione nei miei test di unità. Ad esempio, il codice vorrebbe questo:
public static int FuncLevel1(
Func<Func<int, int>, int, int> FuncLevel2,
Func<int, int> FuncLevel3,
int param1,
int param2)
{
// Some operations here
var res = FuncLevel2(FuncLevel3, param1) + param2;
// Some more operations here with 'res'
return result;
}
public static int FuncLevel2(
Func<int, int> FuncLevel3,
int param1)
{
// Some operations here
var res = FuncLevel3(param1);
// Some more operations here with 'res'
return result;
}
Quindi la funzione FuncLevel1
è chiamata come:
var res = FuncLevel1(FuncLevel2, FuncLevel3, 5, 10);
Il vantaggio di questa struttura è che posso prendere in giro le funzioni FuncLevel2
e FuncLevel3
se voglio unità test FuncLevel1
e FuncLevel2
rispettivamente.
In un semplice scenario mi rendo conto che potresti scrivere il codice come:
var res3 = FuncLevel3(5);
var res2 = FuncLevel2(res3) + 10;
var res1 = FuncLevel1(res2);
Ma è facile immaginare che ci possano essere altre (più complesse) situazioni in cui non è possibile risolvere il problema in questo modo.
Nel caso in cui tu abbia chiamate di funzioni profondamente annidate, passare tutte le funzioni richieste ai livelli più bassi dall'inizio alla fine può produrre un codice ingombrante. Pertanto sono molto interessato a leggere le alternative per gestire meglio uno scenario come questo.