De backend van de toekomst: Minimal API, .NET Hexagonal Architecture en meer
Tags: programming, dotnet
Published: 2023-03-20 15:39:51

## Inleiding
Enkele weken geleden kregen wij, Maxim, Jonas en Arne als developers voor Neobyte BV de opdracht voorgeschoteld om een CMS, ofwel Content Management System te maken. Dit is een applicatie die het voor mensen zonder kennis van programmeren een website kunnen opzetten en beheren. Hieronder lichten wij onze keuzes en beslissingen toe in het uitwerken van de backend van deze applicatie. We nemen eerst een kijk op de hexagonale architectuur waarin onze backend geschreven is en vergelijken deze met de gelaagde architectuur. Voor de API (Application Programming Interface) moesten we beslissen tussen de implementatie van Minimal API of de traditionele Controller API. Ten slotte wordt het remote hosting gedeelte van het project toegelicht.

## .NET Architectuur
Een van de voorwaarden van het project was dat de Backend een .NET systeem moest zijn. In de rest van de aanpak werden we vrij gelaten. De architectuur die we kozen om onze backend op te bouwen is de Hexagonal Architecture. De hexagonale architectuur scheidt de domeinlogica van randapparatuur zoals de database, de API en andere services. Het systeem wordt opgedeeld in 3 lagen, namelijk: de domeinlaag, de applicatielaag en de infrastructuurlaag. Dit biedt voordelen zoals modulaire en flexibele code, onafhankelijke ontwikkeling en testen van elke laag en de mogelijkheid om de infrastructuurlaag te vervangen zonder de domeinlogica te wijzigen.

Een alternatieve architectuur is de gelaagde architectuur, waarbij elke laag afhankelijk is van de laag eronder. Hoewel deze architectuur vaak goed werkt, kan het nadeel zijn dat het minder flexibel en moeilijker te onderhouden kan zijn bij complexe systemen. We kozen daarom voor de Hexagonal Architecture omdat deze meer flexibiliteit en onderhoudbaarheid geeft dan de gelaagde architectuur. Ons systeem maakt gebruik van verschillende randapperatuur zoals het remote hosting systeem die onafhankelijk vervangen moet kunnen worden. 

Zie hieronder hoe wij de hexagonale architectuur toegepast hebben in ons project.
![Neobyte CMS Hexagonal Architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/28wt1e6ql14285va8dff.png)

## Minimal API
Voor onze API kozen we voor een van de nieuwere benaderingen die afwijkt van het traditionele, namelijk Minimal API.

Bij Minimal API ligt de nadruk op het minimaliseren van de overhead en het vereenvoudigen van de syntax. Minimal API biedt een vereenvoudigde manier om API's te schrijven, waarbij minder code nodig is om dezelfde functionaliteit te bereiken als met traditionele Controller API's. Dit komt doordat de Minimal API's zijn gebaseerd op endpoint routing, waarbij één endpoint kan worden gedefinieerd en meerdere HTTP-methoden.

Het gebruik van Minimal API biedt voordelen zoals minder code, minder overhead en minder configuratie dan Controller API's. Hierdoor kunnen API's sneller worden ontwikkeld en zijn ze gemakkelijker te begrijpen en te onderhouden. Aan de andere kant bieden Controller API's voordelen zoals een hoger abstractieniveau, waardoor complexe logica beter gestructureerd kan worden. Onze API is relatief klein. Minimal API leek voor ons dus de logische keuze.

Ten slotte speelde ook snelheid een rol bij het maken van onze keuze. Na onderzoek werd duidelijk dat Minimal API sneller is dan de traditionele Controller API. 

Hieronder is een kleine test te zien door ons uitgevoerd. We hebben 50 virtuele gebruikers 5 minuten lang 2 dezelfde endpoints laten aanspreken. Het ene endpoint was geschreven met Minimal API, de andere met Controller API.
![Minimal API vs Controller API requests/s](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/li9zk3coumsly240aa22.png)

## Hosting connectie
Een van de belangrijkste delen van de backend was het hosting connectie gedeelte. Er wordt via credentials connectie gemaakt naar de plaats waar de website gehost is. We implementeerden verschillende protocols, namelijk: FTP, SFTP en Amazon S3. De applicatie is zodanig opgebouwd dat deze lijst makkelijk verder uit te breiden is.

### FTP
Het eerste protocol dat we toevoegden aan ons systeem is FTP. Het implementeren hiervan ging niet zonder problemen. Eerst maakten we gebruik van `System.Net.WebRequest`. Deze first party klasse van Microsoft bleek verouderd te zijn. De vervanger van deze klasse is `System.Net.Http.HttpClient`. Deze ondersteunde helaas geen FTP. Daarom zijn we op het advies van Microsoft op zoek gegaan naar een third party alternatief. Hiervoor kwamen we uit op `FluentFTP` en 
`FTP.dll`. 

|Eigenschap|First party|FluentFTP|FTP.dll|
|---|---|---|---|
|Snelheid|snel|zeer snel|gemiddeld|
|Async/await support|ja|ja|nee|
|open/closed source|Visible|Open|Closed|
|gebruiksvriendelijkheid|goede documentatie, makkelijk op te zetten|Veel voorbeelden, degelijke documentatie|Beperkte documentatie, desondanks makkelijk om op te zetten|
|support|April 2022|Heden|Mei 2022|

Na de verschillende opties te vergelijken bleek `FluentFTP` voor ons de geschikte library te zijn omwille van de goede support en gebruiksvriendelijkheid. Ook het gebrek aan async/await ondersteuning bij `FTP.dll` was een grote tegenvaller. 

### SFTP
Naast FTP wilden we ook ondersteuning bieden voor SFTP. Dit is een file transfer protocol gebaseerd op SSH (Secure Shell). 

Net zoals voor de FTP connectie, zijn er voor SFTP ook een paar opties. Wij hebben gebruikgemaakt van `SSHNET` voor de gebruiksvriendelijkheid en grote downloadcijfers. Deze Nuget package heeft ook de mogelijkheid om async te werken, maar hier moeten de Async Tasks nog wel zelf worden aangemaakt vanuit de Begin en End functies (`BeginFileDownload, EndFileDownload`).

### S3
Een derde hosting connectie de we geïmplementeerd hebben is S3 (Simple Storage Service). Dit is een cloudgebaseerde opslagservice die wordt aangeboden door Amazon Web Services (AWS). 

Een belangrijk verschil tussen S3 en andere hosting verbindingen zoals FTP is dat S3 geen traditionele bestandssysteem hiërarchie gebruikt, maar objecten. Dit betekent dat bestanden niet in mappen worden georganiseerd, maar in containers genaamd "buckets". Het biedt ook geavanceerde functies zoals het versiebeheer van objecten, levenscyclusbeheer en gegevensencryptie.

Voor S3 hebben we gekozen voor de library van AWS genaamd `AWSSDK.S3`. Deze SDK biedde al de functionaliteit die nodig was om S3 aan onze lijst met remote hosting connecties toe te voegen. 

Een grote hindernis was natuurlijk het feit dat de manier van data opslag bij S3 anders was dan de traditionele hiërarchie. AWS zegt wel zelf dat deze structuur makkelijk te mimieken is door in de sleutels van de bestanden forward slashes te gebruiken. Dit was in onze ogen ook de enige mogelijke oplossing. 

## Conclusie
Ondanks het uitwerken van deze backend niet zonder problemen ging, hebben we een mooi resultaat kunnen brengen. Het grondig onderzoeken van verschillende opties en telkens de beste uit te kiezen heeft van onze backend applicatie een mooi, schaalbaar en betrouwbaar project gemaakt.

## Bronnen
[.NET Hexagonal Architecture](https://paulovich.net/hexagonal-architecture-dot-net/)
[.NET Hexagonal Architecture](https://alistair.cockburn.us/hexagonal-architecture/)
[Hexagonal vs Layered](https://softwareengineering.stackexchange.com/questions/436194/i-cant-really-tell-the-difference-between-hexagonal-and-layered-architecture)
[Minimal API](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-7.0)
[System.Net.Webrequest](https://learn.microsoft.com/en-us/dotnet/api/system.net.ftpwebrequest?view=net-7.0)
[FluentFTP](https://github.com/robinrodricks/FluentFTP)
[Ftp.dll](https://www.limilabs.com/ftp)
[SSHNET](https://github.com/sshnet/SSH.NET)
[AWSSDK.S3](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/csharp_s3_code_examples.html)