Posts by category: Patterns And Principles

Domain Driven Design e CQRS

Domain Driven Design e CQRS

Scrivere applicazioni che funzionano spesso non è un fattore sufficiente a garantirne il successo. Dobbiamo innanzitutto capire e soddisfare i requisiti del cliente, mantenere un elevato grado di manutenibilità e ovviamente avere usabilità e performance. In tutto questo il Domain Driven Design ci fornisce una serie di principi che ci aiutano a non fallire nella progettazione e nello sviluppo di un software e il CQRS è il modo migliore di applicare questi principi.

Queste slide sono tratte dall’evento live, se siete interessati è disponibile anche la registrazione.

/ Read Article /
by in / C# / Patterns And Principles
No peoples think this is good

Non commentare il codice, rendilo più leggibile con le Fluent Interface

Ad ognuno di noi sarà capitato almeno una volta di leggere una porzione di codice e di non riuscire a capirne la logica. Tra le cause oltre al cattivo design c’è quasi sempre la mancanza di commenti o di documentazione. Ma quanti di noi commentano il codice che scrivono? Intendiamoci è una buona regola commentare il codice, ma è un’attività talmente noiosa che diventa inutile se poi non manteniamo il commento aggiornato.
Vediamo allora come applicando le “Fluent Interface” possiamo scrivere del codice che si commenta da solo!

Una interfaccia è “fluente” quando ci consente di rendere il codice implementativo leggibile come le righe di un romanzo oppure come le strofe di una poesia. Tale caratteristica non è soggettiva, ma si può ottenere facilmente partendo dalla tecnica del method chaining.

Il method chaining, ovvero la possibilità di concatenare le chiamate ai metodi di una interfaccia, si ottiene definendo come valore di ritorno l’istanza corrente della classe a cui appartiene il metodo.

Con un po’ di codice tutto sarà più chiaro. Vediamo quindi un esempio di interfaccia non “fluente” che riguarda la prenotazione di un biglietto ferroviario. Partiamo con la classe Train:

Nel codice cliente andiamo poi a prenotare il biglietto per un particolare treno:

Come possiamo notare il codice non è per niente leggibile, dobbiamo infatti ricorrere alla definizione del costruttore della classe per capire il significato dei parametri passati.

Grazie agli object initializer introdotti con la versione 3.0 di C# il codice si fa più chiaro, ma rimane ancora pesante da leggere:

Vediamo quindi come una interfaccia “fluente” può rendere questo codice più leggibile:

Vediamo come cambia il nostro codice cliente per quanto riguarda la prenotazione di un biglietto ferroviario:

Possiamo migliorare ancora trasformando il metodo Nr in una “static factory”, ovvero implementando al suo interno la creazione di una istanza della classe Train, così:

La differenza rispetto al codice di prima è minima, ma evidente:

In conclusione ci sono molti modi per aiutare noi stessi e altri programmatori a capire che cosa fa il nostro codice, il più importante di tutti rimane sempre il commento, ma le fluent interface sono un valido alleato per combattere le lunghe sedute davanti al reflector!

/ Read Article /
by in / C# / Eventi / Patterns And Principles
No peoples think this is good

AntiPatterns, i vizi del programmatore: slide e codice

Ho pubblicato su slideshare le slide dell’evento 1nn0va di venerdì sera. Per chi fosse interessato sono disponibili per il download i progetti di esempio, trovate il link qui sotto dopo la presentazione.

 

Codice di esempio pronto per il download >>
Download
/ Read Article /
by in / C# / Patterns And Principles
No peoples think this is good

Refactoring: sostituire lo switch con il polimorfismo

Lo switch viene spesso utilizzato assieme ad un enumerativo per specificare porzioni di codice da eseguire in base al valore di una determinata variabile. L’utilizzo di tale costrutto rende però il nostro codice rigido e poco mantenibile perché all’aggiunta di un nuovo valore siamo costretti ad aggiornare sia l’enumerativo che lo switch.
Vediamo allora come con un refactoring object-oriented possiamo sostituire lo switch per rendere il nostro codice più flessibile, mantenibile e pulito.

Nell’esempio seguente abbiamo creato una classe MSOfficeLicence con un metodo Price che tramite uno switch ritorna il prezzo di una licenza Office in base al tipo (Home o Business):

Proviamo ad applicare il polimorfismo e quindi rendiamo la classe MSOfficeLicence e il metodo Price astratti e creiamo una classe derivata per ogni tipo di licenza:

Ecco che tolto lo switch possiamo aggiungere nuovi tipi di licenza semplicemente creando una nuova derivata che esegue l’override del metodo Price. La logica del codice client deciderà quindi quale licenza istanziare magari tramite una factory o semplicemente tramite dependency injection:

Nota: I prezzi sono solo a titolo di esempio 🙂

/ Read Article /
by in / Patterns And Principles
No peoples think this is good

Il programmatore con solidi principi

Programmare per alcuni è un’arte, un esercizio di creatività che non può essere limitato da regole e schemi, una definizione però che non tiene conto degli obiettivi che un programmatore deve perseguire nello scrivere “buon codice”, ovvero mantenibilità, estendibilità, scalabilità, stabilità, etc. Per raggiungere questi obiettivi e non perdere la bussola dobbiamo avere dei solidi principi:

  • S – Single Responsibility Principle
  • O – Open/Closed Principle
  • L – Liskov Substitution Principle
  • I – Interface Segregation Principle
  • D – Dependency Inversion Principle

Ecco i principi che aiutano il programmatore ad ottenere una “buona” programmazione ad oggetti:

Single Responsibility Principle (SRP)

Ogni classe deve essere disegnata per svolgere bene un solo compito, avere una sola responsabilità, in pratica una classe deve avere un solo motivo per cambiare. Seguire questo principio porta automaticamente ad avere un basso accoppiamento.

Open/Closed Principle (OCP)

Una classe deve essere aperta alle estensioni, ma chiusa alle modifiche. Dobbiamo quindi essere in grado di estendere il comportamento di una classe senza modificarne l’implementazione (aka codice sorgente). Come? Facendo uso di classi astratte o interfacce, ovvero sfruttando il polimorfismo.

Liskov Substitution Principle (LSP)

Una funzione che utilizza un riferimento ad una classe base deve poter utilizzare al suo posto una qualsiasi delle classi derivate senza conoscerne l’implementazione. In pratica non dobbiamo modificare in alcun modo il comportamento di una classe base in una derivata. Una via potrebbe essere preferire dove possibile la composizione all’ereditarietà, ponendosi ogni volta la fatidica domanda IS A or HAS A?

Interface Segregation Principle (ISP)

Una classe non deve implementare una interfaccia che non usa o che usa parzialmente. Molte volte si deve preferire più interfacce con una sola funzionalità ad un’unica interfaccia che fa tutto. Il motivo? Una classe è influenzata dal cambiamento di una interfaccia anche se non la usa.  

Dependency Inversion Principle (DIP)

Si basa sul concetto che una classe di un alto livello non deve dipendere dall’implementazione di classi o entità di un livello inferiore. In pratica per raggiungere tale scopo devo progettare le classi pensando alle interfacce e non alle implementazioni. Questo porta ad avere non solo un basso accoppiamento tra i livelli della mia architettura, ma automaticamente a poter sostituire l’implementazione di un livello inferiore senza pregiudicare il funzionamento di quelli superiori.

 

In conclusione questi principi aiutano il programmatore, laddove non arriva l’esperienza, ad ottenere un codice di qualità che mantenga una forte coesione ed un basso accoppiamento tra le entità del sistema. Non devono però diventare un dogma, ma uno strumento da conoscere e da utilizzare a seconda degli obiettivi e dei requisiti applicativi.

Link utili

/ Read Article /