Post

Refactoring: improving Hierarchy

Immagine
Gerarchia La gerarchia è un principio che suggerisce la creazione di una organizzazione gerarchica di classi sulla base della loro generalità, classificazione, sostituibilità. La gerarchia è il modo naturale con cui suddividiamo le entità anche nel mondo naturale. Nel software abbiamo due principali relazioni che si prestano alla istituzione di gerarchie: la relazione "is a" e la relazione "is part of". La relazione "is a" è di tipo strutturale ed è quella che nella programmazione ad oggetti viene implementata con l'ereditarietà.  C'è da dire che il meccanismo di ereditarietà inizialmente concepito nei linguaggi OOP nel tempo ha perso un po' del suo appeal iniziale, ed è stato via via sostituito con la mera esposizione di interfacce, per via della migliore manutenibilità e possibilità di refactoring che queste offrono, tuttavia rimangono in molti ambiti in cui l'ereditarietà è un meccanismo perfettamente valido ed efficace. Linee guida La s...

Crittografia e Hashing

Immagine
Introduzione Esamineremo in questa nota i concetti principali di crittografia e hashing, a cosa servono, come vengono usati e le best practice in ambito di sicurezza dei dati. Occorre innanzitutto distinguere due tipi di funzioni che possono essere applicate ai dati: la cifratura e l'hashing. Entrambi trasformano un testo "in chiaro" in un testo completamente diverso, ma con differenze sostanziali: la cifratura produce una serie di caratteri che può essere, mediante la decifratura, ritrasformata nel testo iniziale, mentre l'hashing non è una funzione invertibile. La dimensione di un file criptato è in generale molto simile alla dimensione del file originale, mentre l'hashing occupa molto meno spazio (a meno che il file originale non sia di pochi caratteri). La cifratura serve a trasmettere un file in modo che sia leggibile solo a chi sappia come decifrarlo . Durante la seconda guerra mondiale la decifratura di messaggi ha consentito di intercettare...

Refactoring: improving abstraction

Immagine
 Astrazione L'astrazione consente di semplificare le entità attraverso la riduzione dei dettagli non rilevanti e la generalizzazione, operata individuandone le caratteristiche principali. L'astrazione è cruciale nel problem solving per poter decomporre un sistema reale in componenti e stabilire le loro connessioni in modo da poterlo gestire più efficacemente. I principi che dovrebbero guidare la progettazione e l'individuazione delle varie entità per comporre un modello di un sistema sono: Identificare  e definire il contorno di un "oggetto" Gli oggetti del dominio applicativo dovrebbero avere corrispondenza nel suo modello logico o concettuale. E' molto più facile parlare di oggetti che  hanno una corrispondenza nel mondo reale che di oggetti completamente astratti, pensiamo al caso in cui si voglia validare il modello con il cliente, o anche solo parlarne con un collega. Ogni componente  del modello dovrebbe essere un oggetto "completo" di tutte le...

Numeri primi e funzione Z di Riemann

Immagine
Introduzione In questa nota raccoglierò alcune formule e teoremi inerenti i numeri primi e la funzione Z, al solo fine di avere un punto di raccolta online sul tema, per coloro (presumo pochi) che fossero, come me, appassionati dell'argomento. Non esporrò tutte le dimostrazioni, ma eventualmente darò i riferimenti su dove trovarle ove si fosse interessati ad esse. In fondo all'articolo c'è una bibliografia con tutto il materiale per approfondire. La presente nota sarà integrata nel tempo, ossia non è (e forse non lo sarà mai) "finita". Nomenclatura \(\pi(n)\) = quanti numeri primi ci sono tra 1 e \(n\). Teorema dei numeri primi Questo teorema è talmente importante che ha una sua sigla propria, ossia TNP. Afferma che $$\pi(x) \sim \frac{x}{\log x} \qquad [1]$$ ossia che tra 1 ed \(n\) ci sono circa \(n/\log n\) numeri primi. Statisticamente la probabilità che un numero compreso tra 1 ed \(n\) sia primo è \(1/\log n\). Alternativamente, l'\(n\...

Refactoring: improving modularization

Immagine
  Modularità In generale, per modularità si intende la misura in cui un sistema può essere decomposto e ricombinato. La modularizzazione è applicata al fine di ridurre la complessità di un sistema decomponendolo in varie parti che presentano relazioni di indipendenza e di interdipendenza. In questa sede parleremo di modularità riferendoci alla decomposizione in classi e non a "moduli" intesi come insiemi di classi. La dipendenza tra classi diverse è identificata dall'accoppiamento tra di esse, mentre la qualità della decomposizione ha come buon indicatore la coesione della classe stessa. Accoppiamento L'accoppiamento misura la dipendenza tra due moduli, e idealmente deve essere minore possibile. Distinguiamo vari livelli di accoppiamento, che elenco dal migliore al peggiore: nessun accoppiamento per dati: lista di parametri passati costituiti da dati semplici, oppure un modulo usa un dato, semplice, prodotto da  un altro modulo per struttura: nell'interfaccia di u...

Refactoring: improving encapsulation

Immagine
  Incapsulamento L'incapsulamento è la proprietà che hanno le classi di nascondere i dettagli di una certa funzionalità o servizio ed esporre un'interfaccia che consenta al client di poterla utilizzare ad un maggior livello di astrazione. L'incapsulamento attua il principio dell'information-hiding, che è uno dei principali cardini della programmazione. Affinché questo sia ben progettato, occorre quindi che siano nascosti al client i dettagli implementativi, e che modifiche dell'implementazione non rendano necessarie variazioni dei client. Esamineremo alcuni problemi che si possono presentare sull'incapsulamento e vedremo come risolverli. Insufficiente incapsulamento Avviene quando una classe espone dei dettagli implementativi esponendo uno o più membri, creando quindi un accoppiamento indesiderato che esporrà i client ad un impatto qualora l'implementazione cambi.  Il peggiore dei casi è esporre variabili globali che possono dunque essere modificate da più c...

Gestione del technical debt

Immagine
 Technical debt Il peso del technical debt Introduzione Il mondo è in continua evoluzione e con esso cambiano i requisiti e le funzionalità che si richiedono ai software. La manutenzione del software occupa l'80-90% della vita di un software, a volte anche più.  Le continue modifiche al software deteriorano la qualità del software e il suo technical debt. Questo nome, introdotto da Ward Cunningham, rappresenta il costo aggiuntivo delle manutenzioni successive dovuto a scelte non ottimali effettuate.  Una manutenzione non attenta alla limitazione del technical debt fa si che i costi delle manutenzioni successive aumentino sempre più   sino a quando diventa più economico scrivere un nuovo software che manutenere il vecchio, con costi enormi ove si tratti di software di grande complessità. E' dunque essenziale prendere coscienza dei motivi per cui nasce il technical debt e sia riconoscere le varie forme in cui esso si presenta, al fine di poter sia evitarlo che cor...