Post

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...

I pattern di concorrenza: accesso a risorse condivise

Immagine
  Introduzione Definiremo alcuni concetti relativi all'accesso di risorse condivise, considereremo alcune situazioni critiche che possono presentarsi e analizzeremo le soluzioni esistenti in letteratura. Processo Definiamo in questa sede un Processo  come una sequenza di istruzioni svolte da un calcolatore per eseguire un programma P. Un processore è un dispositivo in grado di eseguire tali azioni. Un processore può alternare nel tempo l'esecuzione di istruzioni di programmi diversi, viceversa l'esecuzione di un programma può essere sospesa e ripresa più volte, anche su processori diversi. Il processo può dunque essere complessivamente svolto in tempi diversi e su processori diversi. Nota L'interruzione di un processo è un'operazione di solito in carico al sistema operativo, ma per i linguaggi interpretati o semi interpretati può anche essere gestito indirettamente dall'ambiente di run-time in cui avviene l'esecuzione. In ogni istante t un...