Svantaggi del riutilizzo di componenti

Il riuso di componenti, sembra vantaggioso a priori e la formula con cui viene promosso un uso indiscriminato di componenti troppo generici è "don't reinvent the wheel".

Ritengo questo principio venga accettato troppo acriticamente, spinto dalla retorica dei fornitori di componenti e consulenti, se il propio obiettivo è quello di sviluppare sistemi perfomanti e affidabili, vanno fatti dei distinguo.

Se fosse vero che non va "reinventata la ruota", tutte le auto e i camion e le biciclette del mondo dovrebbero, per questo principio, usare la stessa implementazione della stessa idea, cioè la stessa ruota, cosa evidentemente inefficiente sotto ogni punto di vista, motivo per cui non si reinventa certo il la legge fisica del rotolamento, attrito etc. ma si adotta una implementazione dipendente dalla situazione per ottenere prestazioni ottimali.

Se quanto detto sopra è lapalissiano in ingegneria meccanica, nel settore dello sviluppo software i vendor di soluzioni e componenti hanno urlato il "reinvent the wheel" abbastanza da stordire manager e sviluppatori meno smaliziati.

L'idea dominante e che vorrei bilanciare è che sia sempre sbagliato scivere una implementazione ad hoc di un componete che si pensa sia disponibile sul mercato, sia esso opensource o commerciale, persino quando i requirements siano limitati e una implementazione di poche decine di istruzioni basterebbe. La conseguenza di queto diffuso mindset, specialmente con la recente introduzione in tutte le comunity di "gestori" di componenti(ruby gem, node npm, php composer), sono progammi lenti, spesso esposti a rischi di sicurezza di cui lo sviluppatore non ha consapevolezza, esposizione al rischio di malfunzionamenti introdotti dai componenti esterni.

Tuttavia, scivere un componete presenta alcuni vantaggi, talvolta notevoli, rispetto a componenti generici. Il vero problema è sviluppare il giudizio e il "buon gusto" per scegliere tra un componente e una implementazione specifica.

Simplicity is prerequisite for reliability. Edger Djikstra
  1. Le funzioni implementate sono esattamente quelle richieste, ne più(software bloat), ne meno. E lo sono nel esatta sequenza in cui sono comode per l'utente. Questo comporta spesso migliori presazioni.
  2. Permette controllo sulla roadmap degli sviluppi. Un bug può essere corretto quando necesario, una funzione può essere tralasciata perché non rilevante.
  3. Valutare l'efficacia di un componente è una attività molto dispendiosa in termini di tempo, talvolta equivalente a riscrivere la sola funzione necessaria. Inoltre alcuni problemi si paleseranno solo dopo uso estensivo del prodotto quando sarà troppo tardi per sostituire il componente senza perdere tempo.
  4. scrivendo un componente specifico si avrà meno requirements, quindi meno funzioni e codice, quindi il componente presenterà un vantaggio sostanziale essendo più semplice da modificare ed estendere.
  5. Estendere un progetto opensource potrebbe non essere conveniente, perché coordinarsi con gli sviluppatori remoti comporta un investimento di tempo notevole, altrimenti fare fork del progetto iniziale non è molto attraenete perché si perdono i bugfix e gli aggiornamenti del progetto principale.
  6. nel caso si usi un componente commerciale, non opensource, la documentazione disponibile è spesso scarsa o comunque carente.

in questo caso si diventa totalmente dipendenti dal fornitore. In caso il fornitore abbandoni il progetto, si sarà forzati a trovare un altro componente simile e ritestare il tutto. Nel caso di un framework, comporta riscrivere l'applicazione. Nel caso di un linguaggio... comporta migrare il prodotto di anni di lavoro.

  1. si è forzati all'aggiornamento dei componenti secondo tempistiche non dettate dalle proprie opportunità ma da forzature esterne
  2. La licenza potrabbe essere troppo restrittiva

queste considerazioni hanno effetti particolarmente accentuati nel caso si tratti di frameworks, quindi astrazioni che impongono un predeterminato design.

Limitare l'impatto di un componente esterno

Attraverso l'uso del pattern Adapter

Per limitare l'impatto sul design dell'applicazione di un componente esterno è buona pratica isolare l'uso del componente in una interfaccia attraverso il pattern Adapter:

// interfaccia utilizzata dall'applicazione per l'invio di mail
interface IMail {
    public function send();
}
class AppMail implements IMail{
    public function send(){
        // utilizzo di uno specifico compoente per l'invia di email
    }
}
Attraverso la gestione dei Requirements

Vanno valutati attentamente i requisiti che ci si aspetta dal componente e va scelto il componente più semplice che soddisfi i requirements, questa pratica richeide disciplina da parte del team di sviluppo, ma è in assoluto la più produttiva in un ottica di lungo termine.

Conclusione

Vi sono certamente situazioni in cui il riuso di componenti sia l'opzione preferibile, tuttavia non è sempre l'unica e la migliore scelta.

Attenzione anche ai paragoni riduttivi e fuorvianti con altre attività, ritengo metafore come "mattoncini" per la costruzione di muri e il mantra "reinventare la ruota", per quanto intuitivi, non descrivano la complessità dello sviluppo di software per il business.


Tags:
Development

Blog Disclaimer:

Le opinioni espresse nel mio blog sono solo questo: mie opinioni.

In nessun modo rappresento le opinioni dei miei clienti in questa sede.


Notice: Undefined variable: browserName in /var/www/taziomirandola.it/lib/Visitors.php on line 86

Notice: Undefined variable: browserName in /var/www/taziomirandola.it/lib/Visitors.php on line 96

Deprecated: strripos(): Non-string needles will be interpreted as strings in the future. Use an explicit chr() call to preserve the current behavior in /var/www/taziomirandola.it/lib/Visitors.php on line 96

Notice: Undefined index: HTTP_ACCEPT_LANGUAGE in /var/www/taziomirandola.it/lib/Visitors.php on line 39

Fatal error: Uncaught TypeError: Argument 1 passed to safe_text() must be of the type string, null given, called in /var/www/taziomirandola.it/lib/Visitors.php on line 39 and defined in /var/www/taziomirandola.it/lib/Visitors.php:162 Stack trace: #0 /var/www/taziomirandola.it/lib/Visitors.php(39): safe_text() #1 /var/www/taziomirandola.it/lib/Visitors.php(124): Visitors::getData() #2 [internal function]: Visitors::log() #3 {main} thrown in /var/www/taziomirandola.it/lib/Visitors.php on line 162