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
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.
queste considerazioni hanno effetti particolarmente accentuati nel caso si tratti di frameworks, quindi astrazioni che impongono un predeterminato design.
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 } }
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.
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.
Le opinioni espresse nel mio blog sono solo questo: mie opinioni.
In nessun modo rappresento le opinioni dei miei clienti in questa sede.