emanuele delbono
ema.blog

Emanuele DelBono

  • Reactjs Redux pattern

    React and Redux

    ReactJs e’ diventato in breve tempo una delle più diffuse librerie per sviluppare applicazioni web. Ho usato il termine libreria per marcare la differenza che React ha con framework piu’ esaustivi quali ad esempio AngularJS. Proprio per il fatto che ReactJs e’ una libreria, il suo scope e’ legato esclusivamente alla generazione delle View di un ipotetico framework MV*. Questo ha un duplice vantaggio: ci permettere di scegliere quale altra libreria affiancare a ReactJs per l’implementazione delle nostre applicazioni (chiamata alle api, servizi, utilities, ecc…) e lascia liberta’ di disegnare l’architettura più adatta all’applicazione che si sta sviluppando. Quindi non siamo vincolati ad usare architetture complesse per semplici applicazioni, ma possiamo usare React e poco altro per piccole applicazioni e usare Flux e Redux per applicazioni più complesse. Redux e’ oggi lo standard di fatto anche se talvolta può essere troppo complesso, prolisso o “pesante” per applicazioni di medie dimensioni. Redux resta comunque una ottima implementazione basata su pochi chiari principi che rendono l’applicazione semplice, testabile e manutenibile. In questo breve articolo mi piacerebbe mostrarvi un’implementazione di redux che usiamo in CodicePlastico che e’ completamente aderente ai principi di Redux ma che rimane più semplice e meno prolissa.

    I principi di redux sono:

    • Esiste un unico stato: i componenti di react non usano this.state ma lo stato viene memorizzato esternamente al componente e gli viene passato dall’esterno sotto forma di proprietà.
    • Lo stato e’ read-only: l’unico modo di cambiare lo stato e’ quello di inviare un’azione e far si che chi riceva l’azione crei il nuovo stato
    • La trasformazione dello stato e’ fatto da funzioni pure

    Come potete vedere i principi sono molto semplici e Redux di fatto non fa altro che fornire alcuni moduli che semplificano la loro applicazione.

    Un po’ di codice

    Partiamo da un esempio implementato con l’uso dello stato internamente al componente per poi rifattorizzarlo verso un’architettura in puro stile redux. Il componente e’ questo:

    class MyCounter extends React.Component {
      constructor() {
    	  super()
        this.state = { counter: 0 }
      }
      plusOne() {
        this.setState({counter: this.state.counter + 1})         
      }
      render() {
        return (
         <div>
          <div>Click count: {this.state.counter}</div>
          <button onClick={this.plusOne.bind(this)}>Add 1</button>
        </div>)
      }
    }
    

    Questo componente mostra un bottone che se cliccato incrementa il valore del contatore visualizzato sopra il bottone stesso. L’implementazione e’ quella classica con l’uso dello stato per memorizzare il valore del contatore. Pur non essendoci nulla di male in questa implementazione (specialmente per il caso in questione) in casi più complessi la gestione dello stato non si limita ad una sola chiamata a setState ma a diverse chiamate in tempi diversi e con logiche (e molti if).

    Il primo principio di redux sottintende che lo stato sia tenuto fuori dal componente e che venga passato al componente MyCounter attraverso l’uso delle props. Possiamo quindi introdurre un componente esterno che “wrappa” il nostro counter:

    class WithState extends React.Component { 
      constructor() {
    	  super()
        this.state = { counter: 0 }
      }
      plusOne() {
        this.setState({counter: this.state.counter + 1})         
      }
      render() {
        return (
          <MyCounter value={this.state.counter} onPlusOne={this.plusOne.bind(this)} />
         )
      }
    }
    
    class MyCounter extends React.Component {
      render() {
        return (
         <div>
          <div>Click count: {this.props.value}</div>
          <button onClick={this.props.onPlusOne}>Add 1</button>
        </div>)
      }
    }
    

    In questo modo il componente MyCounter non fa più uso dello stato e potrebbe essere scritto sotto forma di funzione semplificando ulteriormente la sua implementazione:

    function MyCounter({value, onPlusOne}) {
       return (
         <div>
          <div>Click count: {value}</div>
          <button onClick={onPlusOne}>Add 1</button>
        </div>)
    }
    

    Ma abbiamo un problema. Il componente WithState non e’ riutilizzabile per altri componenti avendo al suo interno conoscenza di alcune cose:

    • Il componente che sta “wrappando”
    • La forma dello stato
    • La funzione che modifica lo stato (plusOne)

    Vediamo come risolvere questi tre problemi. Partiamo dal terzo punto: dobbiamo rimuovere la logica di modifica dello stato dal componente WithState Nei principi di redux si dice che per modificare lo stato bisogna scatenare un’azione che verra’ gestita da funzioni chiamate reducer. L’idea di inviare azioni proviene dall’architettura unidirezionale di Flux che ha gettato le basi anche per redux. L’idea e’ quella di introdurre un dispatcher che si occupa di inoltrare le richieste di azioni a tutti coloro che sono interessati. Una semplicissima (e semplificata) implementazione di un dispatcher può essere questa:

    const dispatcher = {
      subscribers: [],
      register(subscriber) {
        this.subscribers.push(subscriber)
      },
      dispatch(action) {
        this.subscribers.forEach(s => s(action))
      }
    }
    

    Il suo ruolo e’ quello di ricevere una richiesta di dispatch da parte di un componente e inoltrare la richiesta a tutte le funzioni interessate all’azione. Il reducer prenderà’ l’azione (e lo stato corrente) e ritornerà il nuovo stato. Una prima idea potrebbe essere quella di lasciare al componente WithState l’applicazione del reducer:

    function counterReducer(state, action) {
      return {counter: state.counter + action.value}  
    }
    
    class WithState extends React.Component { 
      constructor() {
    	  super()
        this.state = { counter: 0 }
      }
      componentWillMount() {
        dispatcher.register(action => {
          const nextState = counterReducer(this.state, action)
          this.setState(nextState)
        })
      }
      render() {
        return (
          <MyCounter value={this.state.counter}  />
         )
      }
    }
    
    function MyCounter({value, onPlusOne}) {
       return (
         <div>
          <div>Click count: {value}</div>
          <button onClick={() => dispatcher.dispatch({value: 1})}>Add 1</button>
        </div>)
    }
    

    In questo modo abbiamo portato all’esterno la logica di modifica dello stato. Ora non ci resta che generalizzare portando fuori la definizione dello stato iniziale, il componente wrappato e il riferimento alla funzione reducer (che ora e’ cablata in WithState). Per estrapolare quelle informazioni possiamo scrivere una funzione che prende i 3 parametri (nome del componente, stato iniziale, la funzione che modifica lo stato) e ritorna il nuovo componente WithState opportunamente configurato.

    function counterReducer(state, action) {
      return {counter: state.counter + action.value}
    }
    
    function createWithState(WrappedComponent, reducer, INITIAL_STATE) {
      return class WithState extends React.Component { 
        constructor() {
    	    super()
          this.state = INITIAL_STATE
        }
        componentWillMount() {
          dispatcher.register(action => {
            const nextState = reducer(this.state, action)
            this.setState(nextState)
          })
        }
        render() {
          return (
            <WrappedComponent {...this.state}  />
          )
        }
      }
    }
    
    function MyCounter({counter}) {
       return (
         <div>
          <div>Click count: {counter}</div>
          <button onClick={() => dispatcher.dispatch({value: 1})}>Add 1</button>
        </div>)
    }
         
    const MyComponent = createWithState(MyCounter, counterReducer, {counter: 0})
    

    Con questo ultimo giro di refactoring il componente WithState e’ completamente all’oscuro del componente MyCounter ed e’ in grado di fare da wrapper a qualsiasi altro componente. Ciao’ che varia e’ il componente wrappato, il reducer che si occupa di creare il nuovo stato, e la forma dello stato. Questi sono i tre parametri della funzione createWithState.

    Questa implementazione e’ molto semplificata ma con un pizzico di sofisticazione in più si riesce a scrivere un modulo pronto ad essere utilizzato in produzione e a supportare la casistica di applicazioni molto complesse. La nostra implementazione la trovate qui: t-redux e se date un’occhiata al codice ritroverete tutti i concetti spiegati in questo articolo.

    Redux e’ leggermente più complesso ha il concetto di store, di selectors e poco altro ma la sua implementazione, almeno nei concetti e principi e molto simile a quanto presentato in questo post. Una cosa che mi piace sempre ricordare e’ che e’ molto piu’ importante imparare i principi e i pattern utilizzati invece che imparare ad usare una libreria, questo perché i principi restano e le librerie passano (soprattutto nel mondo javascript). Ad esempio Redux implementa molti principi utilizzati in architetture basate su eventsourcing, CQRS e programmazione funzionale, inventate anni fa….come al solito non si inventa quasi mai nulla, si adattano e riusano vecchi concetti.

  • Build your ASP.NET MVC app with Grunt

    Grunt (and Gulp) is a marvellous tool to automate your development and build pipeline but until few months ago it was directly tied to the node environment. But since Microsoft is becaming more open source, some developers started to develope Grunt tasks to support the .NET pipeline. So I tried to combine a set of developer tasks to automate an ASP.NET MVC/WebApi project….and it works! I was able to watch the project folder and to start a set of tasks on every change to a file so that I can rebuild the app, publish it in a folder and refresh the browser to see what’s changed.

    The project structure is:

    /src
    |-- MyProject.sln
    |-- package.json
    |-- Gruntfile.js
    |-- /MyProject
           |-- /App_Start
           |-- /assets
           |-- /Controllers
           |-- /Properties
           |-- /Views
           |-- MyProject.csproj
    

    Task by task I created the Gruntfile. Here is the list of task that I used:

    grunt.loadNpmTasks('grunt-msbuild');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-iisexpress');
    grunt.loadNpmTasks('grunt-contrib-compass');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    
    • grunt-msbuild is used to compile the project. I added a watcher that monitor all the csharp files and everytime one of these change it runs the msbuild task.
    • grunt-iisexpress is used to run the IISExpress local server on the web folder so that we can see the result of our changes
    • grunt-contrib-compass is for compiling the SCSS/SASS files into CSS
    • grunt-contrib-jshint simply analyze the javascript files
    • grunt-contrib-uglify is used to minify the javascript files

    The full Gruntfile.js is available as a gist feel free to use it and modify on your needs.

    Consider that this works without Visual Studio so if you prefer you can use a lighweight editor like SublimeText (with Omnisharp)

  • On learning TDD

    Even if Test Driven Development is an old topic and even if today almost everybody should have learned the benefits of TDD I still do a lot of mentoring on the topic and some people ask me if I have some examples of code written on TDD. Well, my Github account is full code written in TDD, the Kata repository is completely written in TDD but you can’t learn TDD looking at the final result, you learn TDD watching the process that goes to the result.

    It’s like learning Origami. Do you think you can learn how to do a swam just looking a final result?

    TDD is a process and the result come after many iterations made of refactored code, deleted code, tests that are removed and is very difficult to understand why we arrived at that point just looking at the result.

    For example one of my usual first test is a test on a constructor that usually I delete after adding a couple of tests since it became useless and looking at the final result you miss this iteration.

    So what are the best way to learn it? On vimeo and youtube there are lots of kata in different languages, looking at them is a good exercise to learn the basic of the process. Pair with other developers is another way to improve you design skills and to practice TDD. In any case I’m available for remote pairing too! :-)

  • Projects structure

    Frameworks like ASP.NET MVC, Rails & C. impose you a strict folder structure using a “topology approach”. This means that files of same types are in the same folder. So you end up with a Controllers folder that contains tens of files that are uncorrelated since ControllerA doesn’t have anything to do with ControllerB. Even worse the correlated files, for example the ModelA, are in a completely different folder mixed with other tens of uncorrelated files. Topology organization is the most used, I saw folders named Enums, Interfaces and Constants and it was very very difficult find the needed things.

    Starting from one of the last project I tried a completely different approach, I’m using a functional organization creating a folder for every module of my application putting in each folder the complete structure (Controllers, Models, Views, etc).

    ####ContractModule

    • Controllers
    • Views
    • Models
    • Others…

    ####CallCenterModule

    • Controllers
    • Views
    • Models
    • Others…

    Doing this way I obtain a modular application and each folder is actually a micro-application that contains all that it needs to run and to be maintained. It’s easier to find the needed files and eventually move components out of the main project. Usually there is also a “Common folder” that contains the cross-module assets (extension methods, directives in case of angularjs, global filters and so on)

  • About TDD (IMHO)

    In these days everybody talks about TDD due to the post of DHH titled TDD is Dead and the various hangouts with Fowler and Beck. I’m a proponent of TDD, I teach TDD and I practice it for 5 years even if I’m not a fanatic and I don’t do TDD all the time. But I like it, and I gain value from applying TDD in my projects. Why?

    • With TDD I can broke up my story in small tasks and every time I add a test and it became green I’m moving towards the final implementation. One test is equivalent to a small functionality.

    • TDD force me to deeply think at what the customer wants. If I’m not sure what the customer needs I can’t even write a test so I’m forced to ask more informations that I will use to write the tests and then the implementation.

    • Using TDD I’m indirectly creating a test suite that I can run every time I need feedback on the status of my codebase.

    • TDD let you design your classes in a simpler way. Since the tests are naturally simple, the tested code is by default simple too.

    • TDD let me think at my code from the user perspective, this means that the first things that I do is to design the interface of my method: I define the name, the return type and the parameters without caring at the implementation. This results in a cleaner interface.

    • TDD let you do extreme refactoring without worries about breaking the functionalities. Can you really refactor your code without the tests?

    By looking at the list above you can see that TDD is more about design that about testing, the tests are a welcome side effects and TDD really helps you in design orthogonal classes that respect the OOP principles.

    So why DHH said that TDD is dead? There are cases in which TDD doesn’t fit and big frameworks like Rails is one of those situations. Doing TDD on a Ruby on Rails application (or ASP.NET MVC) is useless, the design of the controllers is already defined by the framework itself and TDD doesn’t add anything, so in this case you can add your tests later. Other cases in which TDD doesn’t work, at least for me, is when I have to learn how to use a new library or a new programming language. In these cases using TDD to experiment make the learning process more difficult and complicated so I prefer to try the new stuff without other ballasts that slow me down.

    So, I will continue to do TDD when possible since until now I get lot of value from this practice and the 6 points above are for me very valuable.