emanuele delbono
Remotizziamoci!

Il 2018 è stato per CodicePlastico un anno in cui sono maturatemolte nuove idee, mi piacerebbe raccontarle sia per riuscire a ripercorrerle e metabolizzarle sia per condividerle con la speranza che possano servire anche ad altre aziende o professionisti.

Uno degli obbiettivi che avevamo fissato a gennaio 2018 era trovare un nuovo ufficio più grande e spazioso per tutti. Fino ad allora eravamo stati all’interno del CSMT, un consorzio di aziende dell’innovazione bresciana, ma gli spazi disponibili non erano sufficienti a contenere 15-20 persone quindi o ci splittavamo in più uffici oppure dovevamo cambiare. L’idea di cambiare ci piaceva e a metà anno abbiamo iniziato la ricerca affidandoci ad “esperti” agenti immobiliari. Oggi, un anno dopo, siamo ancora qui!

Cosa è successo nel frattempo? Trovare un ufficio che ospiti 15-20 persone è una soluzione valida ma non è definitiva, chi può dire se tra 5 anni sarà sufficiente o sarà troppo piccolo ( o troppo grande)? Un nuovo ufficio implica grosse nuove spese: trasloco, adeguamento, nuovo canone d’affitto, attivazione dei contratti. Cercare un nuovo ufficio è dispendioso in termini di tempo ed è dannatamente noioso avere a che fare con gli agenti immobiliari.

Fatte queste considerazioni verso la fine dell’anno ci siamo detti: e se rimanessimo qui? Basterebbe far si che tutti possano lavorare da casa e che l’ufficio diventi un’opzione da usare solo qualche volta alla settimana. Nessuno avrà più la sua scrivania e le postazioni saranno libere. L’idea ci è piaciuta, ne abbiamo parlato con i colleghi e anche loro hanno apprezzato la possibilità. Ma, come Jacopo insegna, prima di effettuare una cambiamento vanno fatti degli esperimenti per validare l’idea. A novembre abbiamo istituito il remote-day: il giovedì tutto il team di CodicePlastico lavora da remoto. Ci serviva per capire se l’idea poteva funzionare o se c’erano delle grosse inefficienze da colmare che impedissero l’idea di remotizzarci quasi completamente.

Oggi, qualche mese dopo l’esperimento possiamo dire di essere soddisfatti, per molti di noi l’opzione remoto è diventata una buona abitudine e ci prendiamo sempre un paio di giorni per lavorare da casa. Sicuramente abbiamo ancora qualche dettaglio da migliorare ma tutto il team ne è consapevole e tutti sono committed per risolversi e proporre miglioramenti. Abbiamo anche deciso di riorganizzare l’ufficio per renderlo adatto al lavoro da remoto e al fatto che non avremo una postazione fissa per tutti.

Fp-ts validation spiegata bene

In CodicePlastico stiamo studiando la programmazione funzionale, abbiamo fatto un corso con Matteo Baglini (che consiglio a tutti) e in questi giorni stiamo provando a fare un po’ di refactoring verso il paradigma funzionale. Naturalmente i dubbi vengono, e ieri ho scritto una mail a Matteo per chiedere aiuto su una parte di codice dedicata alla validazione. La mail di risposta e’ stata talmente dettagliata che ho pensato fosse uno spreco tenerla solo per me, così (con l’autorizzazione di matteo) la pubblico qui:

[ema] Ciao Matteo, nell’addentrarmi nella programmazione funzionale in Typescript usando questa libreria https://github.com/gcanti/fp-ts mi sono imbattuto in questo meccanismo di validazione che non capisco completamente e mi sembra molto complesso. L’esempio particolare a cui mi riferisco e’ questo: https://github.com/gcanti/fp-ts/blob/master/docs/Validation.md


Ciao Ema,

Personalmente direi articolato non complesso. Più avanti mi spiego.

[ema] Perche’ si deve creare una funzione curried per costruire la Person?

In generale per costruire Person ti serve una funzione, questo banalmente perchè sei in fp e in fp tutto si fa con le funzioni. Le strutture dati algebriche (Person è un product type) non fanno niente se non immagazzinare dati. Le funzioni permettono la costruzione e/o manipolazione di questi dati. Ambienti come haskell e scala (con le case class) ti offrono out-of-box la funzione di costruzione. Typescript no, prima sfiga.

[ema] Allora perchè curried?

Questo accade perchè Applicative serva a comporre una funzione con effetti (le funzioni di validazione) + una funzione senza effetti con due parametri (la funzione di creazione di person). Nel mondo fp ovvero haskell una funzione con due paramentri (a, b) => c è di fatto (grazie a curry) 2 funzioni da 1 parametro a => b => c. Molto probabilmente Fp-Ts ha scelto di seguire più da vicino lo stile haskell, seconda sfiga. In scala gli autori di librerie tendono ad evitare il currying perchè non è naturale nel linguaggio.

Detto questo, perchè validatePerson nell’esempio di Fp-Ts è così complessa? Perchè ti mostra a basso livello come si compone una funzione con effetto con una funzione senza effetti con due parametri (curried).

Dissezioniamo questo mostro:

A.ap(validateName(input['name']).map(person), validateAge(input['age']))

la funzione ap è fatta così:

readonly ap: <A, B>(fab: HKT<F, (a: A) => B>, fa: HKT<F, A>) => HKT<F, B>

in scala

def ap: [A, B](fab: F[A => B], fa: F[A]): F[B]

in poche parole

  1. accetta fab: una funzione da A=>B wrappata in un effetto F aka F[A => B]
  2. accetta fa: un valore A wrappato in un effetto aka F[A]
  3. restutisce un F[B]

invocando le singole validazioni ottengo

const nameResult: Validation<NonEmptyArray<string>, string> = validateName(input['name'])
const ageResult: Validation<NonEmptyArray<string>, number> = validateAge(input['age'])  

A.ap(nameResult.map(person), ageResult)  

ora concentriamoci qui

nameResult.map(person) 

passando alla map (che accetta in ingresso una funzione con 1 parametro) il curried constructor ottengo

const nameResultBindend: Validation<NonEmptyArray<string>, number => Person> = nameResult.map(person)

dai! non ci credo! ho una funzione wrappata in un effetto sta a vedere che ora posso chiamare ap! ;-)

A.ap(nameResultBindend, ageResult)

applicando più volte la stessa tecnica (ap + map) posso comporre funzioni con 3/4/5/N parametri. Ripeto è un dettaglio low level, importante, ma low level.

Durante il corso per non andare così low level abbiamo usato la map2/map3/etc oppure la mapN. Prendiamo la map2, in scala la sua firma è:

def map2[A, B, Z](fa: F[A], fb: F[B])(f: (A, B) => Z): F[Z]

il suo scopo è quello di valutare in maniera indipendente 2 effetti (fa e fb), passare i risultati alla funzione f e liftare quanto prodotto (Z) nel solito effetto (F). Questo ci permetteva di fare una roba tipo

case class Person(name:String, age:Int)
def makePerson(name:String, age:Int):ValidationResult[Person] = 
   Applicative[ValidationResult].map2(validateName(name), validateAge(age))(Person.apply)

Quindi se vuoi usare questo tipo di combinatori (a più alto livello) devi cercarli in fp-ts. Ho fatto un giro e controllando la definizione di Applicative (https://github.com/gcanti/fp-ts/blob/master/docs/Apply.md) non ho trovato map2 ma una cosa equivalente liftA2: Lift a function of two arguments to a function which accepts and returns values wrapped with the type constructor F

ovvero data la funzione f: (A, B) => Z passandola a liftA2 otteniamo una funzione g: (F[A], F[B]) => F[Z].

nel mondo curry andiamo da f: A => B => Z a g: F[A] => F[B] => F[Z]

in pratica prendiamo una funzione senza effetti (f) e la trasformiamo in una che funziona allo stesso modo ma effectful.

Se caliamo liftA2 nell’esempio di validation di Fp-Ts dobbiamo prima di tutto prendere il curried constructor

const person = (name: string) => (age: number): Person => ({ name, age })

e liftarlo con liftA2 (non conosco typescript e fp-ts quindi vado un po’ di pseudo codice)

const A = getApplicative(getSemigroup<string>())
const personLiftata = liftA2(A)(person)

ed in fine validationPerson invocherà la versione liftata

function validatePerson(input: Record<string, string>): Validation<NonEmptyArray<string>, Person> {
  return personLiftata(validateName(input['name']), validateAge(input['age']))
}

sintetizzando prendiamo una funzione

string => number => Person

e “senza fare niente” la facciamo operare in un contesto di validazione

Validation<NonEmptyArray<string>, string> => Validation<NonEmptyArray<string>, number> => Validation<NonEmptyArray<string>, Person>

E qui sta la figata, ipotizziamo che validateName e validateAge siano implementate server side, quindi la validazione diventa asyn con i Task (sempre di Fp-Ts). Come cambia il tutto? La contruction function non cambia, non dipende da effetti.

Le validateName e validateAge le riscriviamo.

function validateName(input: string): Task<string> ...
function validateAge(input: string): Task<number>  ...

La definizione della personLiftata non cambia.

Mentre validatePerson cambia solo come tipo di ritorno

function validatePerson(input: Record<string, string>): Task<Person> {
  return personLiftata(validateName(input['name']), validateAge(input['age']))
}

Il tutto accade perchè prendiamo la solita

string => number => Person

e “senza fare niente” la facciamo operare in un contesto di HTTP async

Task<string> => Task<number> => Task<Person>

Forte, no?

[ema] E se avesse 20 campi?

Hai un problema di design! :-) Detto questo, esistono tante liftA con il numero di parametri

fp-ts arriva al max a liftA4. haskell arriva al max fino a liftA3 in scala arriviamo a map22 (siamo troppo avanti :-) scherzi a parte sono 22 perchè in java possiamo definire metodi fino ad un massimo di 22 parametri).

Quindi se cambiano i requisiti ed a Person viene aggiunto un campo “email” da validare dobbiamo:

  1. aggiungere il campo sul product type
  2. aggiungere il parametro curried alla constructor funcion
  3. definire eventuali nuovi validatori
  4. usare liftA3 invece di liftA2
  5. usare il terzo validatore in validatePerson

Meccanico e dal punto 2 in poi guidato dal compilatore, per questo lo vedo articolato, ma non complesso. Una volta conosciute bene le astazioni. :-)

Nel nostro caso le validazioni sono N e sullo stesso campo devo poter fare piu’ validazioni (ad. es. la stringa e’ una data e la data e’ maggiore di oggi).

ti fai una funzione di validazione da stringa a data poi una da data a data in pratica ti fai le singole “check” slegati da cosa andrai a creare

function validateNotEmpty(input: string): Validation<NonEmptyArray<string>, string>
function validateGtToday(input: date): Validation<NonEmptyArray<string>, date>  

dopo la validatione della data per la solution da stringa a data è solo la composizione dei check (faccio ancora un typescript “a braccio”)

function validateDate(input: string): Validation<NonEmptyArray<string>, date> 
              validateNotEmpty.flatMap(validateGtToday)

flatMap, aka composizione monadica, perchè prima devi poter passare da stringa a data e solo se riesci devi vedere se la data è maggiore di oggi, altrimenti non fare niente.

[ema] E in uscita vogliamo:

export type SelectedSolution = {
  from: Station,
  to: Station,
  outbound: TrainDateTime,
}
export type TrainDateTime = {
  date: Date,
  time: Time
}

la validazione della TrainDateTime è una composizione applicativa di validateDate e validateTime (che non ho implemetato…)

function validateTrainDateTime(input: Record<string, string>): Validation<NonEmptyArray<string>, TrainDateTime> 
    createTrainDateTimeLiftata(validateDate(input['date']), validateTime(input['time']))

idem per Station e SelectedSolution, comporre le altre funzioni (che erano a sua volta composte da altre funzioni)

function validateStation(input: string): Validation<NonEmptyArray<string>, Station>
    validateNotEmpty(input).map(createStation)

function validateSelectedSolution(input: Record<string, string>): Validation<NonEmptyArray<string>, SelectedSolution>  
    createSelectedSolutionLiftata(validateStation(input['from']),  validateStation(input['to']), validateTrainDateTime(input))  

:-)

Arcade in Codiceplastico

In CodicePlastico abbiamo sempre cercato modi per creare un ambiente piacevole in cui passare la giornata lavorativa. Sappiamo benissimo che il nostro lavoro di programmatori ha parecchi aspetti negativi legati principalmente al poco movimento e al prolungarsi delle ore passate a concentrarsi su un problema. Per questo, senza imporre regole o obblighi, nel tempo ci siamo inventati strumenti e metodi per migliorare la situazione. Abbiamo iniziato anni fa con le freccette, “sport” al quale ci dedichiamo giornalmente con sfide all’ultimo 20 triplo! Da un annetto circa abbiamo introdotto anche l’acquisto aziendale di frutta (esistono fruttivendoli che vendono su internet!) e non ci facciamo mai mancare un po’ di frutta di stagione da consumare durante i meeting interni o durante le pause. Ma la grande novita’ di questi gioni e’ lui:

Eccolo

Ci siamo regalati un cabinato brandizzato CodicePlastico per staccare la mente dal codice e ritornare ai tempi delle scuole medie con i videogiochi del passato.

Insomma le giornate lavorative sono diventate piu’ divertenti e tra un test verde e uno rosso abbiamo tempo per qualche sfida!

Lens in javascript

Qualche settimana fa per un progetto che stiamo sviluppando abbiamo dovuto interfacciarci con le API di wordpress per recuperare alcune informazioni dai post pubblicati su un blog. La struttura dati restituita dalle API di wordpress e’ abbastanza nested e ogni livello potrebbe non essere presente, questo comporta che prima di accedere ad un attributo figlio va controllato che il padre non sia undefined.

Per andare sul concreto questa e’ una parte del json che le API restituiscono:

const obj = {
  ...
  "media_details": {
    "width": 913,
    "height": 1345,
    "file": "2017\/07\/immagine1.jpg",
    "sizes": [{
      "thumbnail": {
        "file": "immagine1-150x150.jpg",
        "width": 150,
        "height": 150,
        "mime_type": "image\/jpeg",
        "source_url": "http:\/\/blog.my-site.com\/wp-content\/uploads\/2017\/07\/immagine1-150x150.jpg"
      },
    },{}]
  }
}

L’attributo che andava estrapolato e’ l’url dell’immagine thumbnail

La prima implementazione che ci e’ venuta in mente e’ questa:

if (obj.media_details) {
  if (obj.media_details.sizes) {
    if (obj.media_details.sizes && obj.media_details.sizes.length > 0){
      if (obj.media_details.sizes[0].thumbnail.source_url) {
        img = obj.media_details.sizes[0].thumbnail.source_url
      }
    }
  }
}

NB: sto andando direttamente sull’indice 0 dell’array thumbnails per semplificare l’esempio

Non e’ sicuramente un’implementazione elegante…ma funziona. Possiamo fare di meglio? A parte fare un po’ di microrefactoring che non porta molto lontano possiamo provare ad usare un costrutto della programmazione funzionale: le Lens (o lenti in italiano). Le lens sono delle functional reference ad un attributo di una struttura dati che permettono di leggerne il valore o di settarne il valore. Librerie come ramda.js hanno un set di funzioni pronte all’uso e il codice sopra puo’ essere riscritto in questo modo:

const imgLens = R.lensPath(['media_details', 'sizes', 0, 'thumbnail', 'source_url'])
img = R.view(imgLens, obj)

Decisamente piu’ semplice, leggibile e mantenibile. La funzione lensPath construisce il percorso per raggiungere l’attributo, la funzione view ne estrae il valore.

Le Lens sono molto utili anche per cambiare il valore di un attributo di una struttura dati tipo quella sopra tramite la funzione R.set di ramda.

Supponiamo di voler modificare l’attributo ricercato prima tramite la lens per ottenere un nuovo obj. Senza il costrutto lens dovremmo scrivere una funzione simile a quella usata per il get (anche se sarebbe meglio che la modifica crei un nuovo oggetto). Con le lens l’operazione di set diventa:

const newObj = R.set(imgLens, 'nuovo_url', obj)

Le Lens sono un costrutto molto utile anche se poco conosciuto e spesso annegato in librerie tipo Ramda.js. La cosa interessante oltre alla semplificazione che portano al codice e’ la peculiarita’ di essere funzioni che possono essere riutilizzate in varie parti del codice e che si possono comporre con altre per ottenere funzionalita’ piu’ complesse, cosa che si sposa benissimo con altri costrutti della programmazione funzionale.

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.