Contattaci

FluentResult

Fluentresult
  • Data: 16 Novembre 2021
  • Autore: Federico Barsotti
  • Categorie

  • Giuneco Tech

    Il nostro settore richiede uno studio continuo e una forte attenzione all’innovazione. Incentiviamo quindi dei programmi formativi annuali per tutti i componenti del team, con ore dedicate (durante l’orario di lavoro) e serate formative sia online che in presenza. Sponsorizziamo eventi, sia come partner che semplicemente come partecipanti, e scriviamo articoli su quello che abbiamo imparato per essere, a nostra volta, dei divulgatori.

    Vai alla sezione Team
  • Lo scopo di questo articolo è far conoscere FluentResult, un piccolo, ma non di meno utile, pacchetto nuget che aiuta gli sviluppatori a rendere più espressivo il codice, migliorando in particolar modo il ritorno da funzioni che normalmente prevedono come tipo di output “void” o i generici “Task”; non vogliamo entrare volutamente nel dettaglio di come si utilizza o raccontarvi tutti i possibili scenari (per questo c’è il repository pubblico di github, con la sua esauriente guida), il nostro scopo è quello di presentarlo e di stuzzicare la fantasia di architetti software 😉

    Nella homepage del progetto github troviamo questa descrizione sintetica del progetto:

    “FluentResults is a lightweight .NET library developed to solve a common problem. It returns an object indicating success or failure of an operation instead of throwing/using exceptions”.

    Lo scopo del pacchetto nuget è abbastanza chiaro: aiutare lo sviluppatore ad ottenere, da metodi e funzioni, oggetti “parlanti” che possano comunicare al chiamante il risultato dell’operazione, evitando ad esempio metodi “void” e semplicando la programmazione asincrona con Async/Await.

    Il tool che vi proponiamo in questo articolo non fa niente di miracoloso, il codice su GitHub è abbastanza comprensibile ai più: deve essere semplicemente “usato” correttamente nella nostra code-base.

    Il nostro primo “Result”

    Il nostro oggetto “Result” può essere costruito con diversi overloading: sempre seguendo la guida sul repo di GitHub, riportiamo i più intuitivi:

    // create a result which indicates success
    Result successResult1 = Result.Ok();
    // create a result which indicates failure
    Result errorResult1 = Result.Fail("My error message");
    Result errorResult2 = Result.Fail(new Error("My error message"));
    Result errorResult3 = Result.Fail(new StartDateIsAfterEndDateError(startDate, endDate));
    

    E come specificato sopra, result può essere utilizzato al posto dei “void”:

    public Result DoTask()
    {
        if (this.State == TaskState.Done)
            return Result.Fail("Task is in the wrong state.");
        // rest of the logic
        return Result.Ok();
    }
    
    

    Trovo molto utile metadatare il risultato di una operazione con informazioni aggiuntive, ad esempio con informazioni di logging e/o di tracing, nel caso in cui volessimo dumpare in qualche luogo più verboso le performances dell’operazione, delegando all’infrastruttura della solution il come utilizzare questi ulteriori metadati:

    var result1 = Result.Fail(new Error("Error 1").WithMetadata("metadata name", "metadata value"));
    var result2 = Result.Ok()
                        .WithSuccess(new Success("Success 1")
                        .WithMetadata("metadata name", "metadata value"));
    public class DomainError : Error
    {
        public DomainError(string message) : base(message)
        { 
            WithMetadata("ErrorCode", "12");
        }
    }
    

    Il tool ci viene in aiuto anche per migliorare la gestione delle eccezioni: in rete possiamo trovare molte strategie di “Error handling”

    // check if the Result object contains an error from a specific type
    result.HasError();
    // check if the Result object contains an error from a specific type and with a specific condition
    result.HasError(myCustomError => myCustomError.MyField == 2);
    // check if the Result object contains an error with a specific metadata key
    result.HasError(error => error.HasMetadataKey("MyKey"));
    // check if the Result object contains an error with a specific metadata
    result.HasError(error => error.HasMetadata("MyKey", metadataValue => (string)metadataValue == "MyValue"));
    

    In Giuneco utilizziamo da qualche tempo questo pacchetto nuget con ottimi risutati; i nostri architetti trovano molto utili le potenzialità di questo strumento per disegnare soluzioni con metodi più espressivi e rendere il codice più “Fluent” 😉

    Pacchetti Nuget suggeriti

    Altri pacchetti nuget che vi consigliamo e che magari approfondiremo in altri articoli sono:

     

    Nuget