francescomecca.eu/_site/pescewanda/2018/07/27/dtldr/index.html
2018-08-15 11:49:16 +02:00

965 lines
23 KiB
HTML

<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="UTF-8">
<title>Caught in the Net</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#157878">
<link rel="stylesheet" href="/css/normalize.css">
<!--<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>-->
<link rel="stylesheet" href="/fonts/opensans.css">
<link rel="stylesheet" href="/css/cayman.css">
</head>
<body>
<section class="page-header">
<h1 class="project-name">Caught in the Net</h1>
<h2 class="project-tagline">La rete ti cattura ma libera il pensiero</h2>
<a class="btn" href="/">Home</a>
<a class="btn" href="/about/">About me</a>
<a class="btn" href="/contattami/">Contact me</a>
<a class="btn" href="/archive/">Archive</a>
<a class="btn" href="/feed.xml">RSS</a>
<a class="btn" href="http://francescomecca.eu/git/pesceWanda">Personal Git</a>
<a class="btn" href="https://github.com/FraMecca">Github</a>
<a class="btn" href="/curriculum/CV_Mecca_Francesco.pdf">Curriculum</a>
</section>
<section class="main-content">
<div class="post">
<h1 class="post-title">Un articolo per r/italyinformatica</h1>
<span class="post-date">27 Jul 2018</span>
<p>Questo articolo è stato originalmente scritto per il <a href="https://tldr.italyinformatica.org">blog</a> di <a href="https://reddit.com/r/italyinformatica">r/italyinformatica</a>.</p>
<p>Negli ultimi anni abbiamo assistito all&#39;ascesa di un gran numero di linguaggi di programmazione, in particolare <a href="https://golang.rg">Go</a> (2009), <a href="https://www.rust-lang.org/en-US/">Rust</a> (2010), <a href="https://kotlinlang.org/">Kotlin</a> (2011), <a href="https://elixir-lang.org/">Elixir</a> (2011), <a href="https://crystal-lang.org/">Crystal</a> (2014), <a href="https://www.ponylang.or">Pony</a> (2014).</p>
<p>Questa esplosione di nuovi linguaggi è dovuta, fra le molte motivazioni, alla necessità di adottare paradigmi di programmazione non immediatamente recenti come cittadini di primo tipo.</p>
<p>Rispetto ai più maturi C, C++ o Java, Python o Ruby questi linguaggi offrono &quot;out of the box&quot; supporto per:</p>
<ul>
<li>una visione moderna delle concorrenze (le goroutines di Go o il modello ad attori di Pony ed Elixir)</li>
<li>Memory safeness, in particolare:
<ul>
<li>assenza di NULL (Pony, Rust, Kotlin)</li>
<li>gestione automatica della memoria, il cosiddetto [Garbage Collector](<a href="https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)">https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)</a> (o <a href="https://en.wikipedia.org/wiki/Reference_counting">Reference Counting</a> per Rust)</li>
<li>assenza di puntatori</li>
<li>assenza di deadlocks</li>
</ul></li>
<li>Supporto ad HTTP nella standard library</li>
<li>Management delle dipendenze (ad eccezione di Kotlin)</li>
<li>Namespaces</li>
</ul>
<p>Chiaramente nessuno di questi linguaggi è oggettivamente superiore agli altri, sono tutti <a href="https://en.wikipedia.org/wiki/Turing_completeness">turing completi</a> e la scelta del programmatore ricade su motivazioni del tutto personali (stile, programmazione ad oggetti, familiarità con altri linguaggi).</p>
<h2 id="un-p-di-contesto">Un pò di contesto</h2>
<p>Ho scritto la mie prime due righe di codice nel 2013 per il corso di Computer Science del Politecnico di Torino.</p>
<p>Per mia fortuna, al Politecnico le cose si muovono ancora lentamente e ci hanno fatto usare C per tutta la durata della triennale. Si è aggiunto un corso di principi della programmazione ad oggetti al terzo anno, in Java.</p>
<p>Personalmente ho imparato durante l&#39;estate di quel primo anno le basi di C++ e Python poco dopo.</p>
<p>Sono stati con i miei primi <a href="https://github.com/framecca">progetti</a> che ho capito che non si può avere un buon linguaggio senza un buon tooling ed una community vivace e soprattutto tanta, tanta documentazione. Per questo, per molto tempo C è stata la mia prima scelta, dato che il mio target è sempre Linux.</p>
<h2 id="gli-obbiettivi-prima-del-linguaggio">Gli obbiettivi prima del linguaggio</h2>
<p>Questo post vuole essere una raccolta più o meno organizzata delle motivazioni per cui mi sono dovuto muovere oltre la frontiera di C nel mio ultimo progetto, ovvero un backend per la raccolta e presentazione di pubblicazione di ricerca e materiale didattico per più di 80 centri di ricerca.</p>
<p>Per il Centro <a href="http://nexa.polito.it/">Nexa</a> del Politecnico di Torino mi sono ritrovato per la prima volta responsabile del codice che dovevo scrivere e dell&#39;uso che se ne sarebbe fatto.</p>
<p>Ho dovuto tenere in considerazione, oltre chiaramente alla funzionalità della piattaforma, in ordine di priorità:</p>
<ol>
<li>Sicurezza</li>
<li>Performance e scalabilità</li>
<li>Separazione dal frontend</li>
<li>Facilità di deploy in un server che non controllo</li>
</ol>
<p>Fortunatamente non mi è stata imposta nessuna limitazione sulla scelta del linguaggio, altrimenti Python sarebbe stato la scelta più adeguata se avessi dovuto tener conto anche di altri programmatori.</p>
<h2 id="benvenuto-d">Benvenuto D</h2>
<p>La mia scelta è caduta su <a href="https://dlang.org">D</a>.</p>
<p>Voglio provare ad affrontare ad uno ad uno i motivi di questa scelta magari inusuale.</p>
<h4 id="sicurezza">Sicurezza</h4>
<p>Nessuno vuole davvero vantarsi di usare un backend scritto in C/C++. Il <a href="https://en.wikipedia.org/wiki/Buffer_overflow">buffer overflow</a> può essere considerato il bug più comune e ci sono <a href="https://techaeris.com/2017/09/27/buzz-fuzzing-find-uncommon-vulnerability/">situazioni</a> in cui non appaiono affatto in maniera ovvia.</p>
<p>Inoltre per un applicativo distribuito il Garbage Collector è la scelta più performante, <a href="https://www.usenix.org/node/189882">specialmente se coordinato fra le varie istanze</a>.</p>
<p>D offre questo di design, e benchè il suo GC sia frutto di numerose <a href="https://www.quora.com/Which-language-has-the-brightest-future-in-replacement-of-C-between-D-Go-and-Rust-And-Why/answer/Andrei-Alexandrescu">discussioni</a>, offre in maniera del tutto innovativa, robustezza e <a href="http://www.walterbright.com/gonewild.pdf">sicurezza</a>.</p>
<p>In particolare, D presenta:</p>
<ul>
<li>Array che sono slices (o ranges) ma non puntatori (e neanche oggetti)</li>
<li>Bound checking durante la fase di compilazione.</li>
<li>Inizializzazione automatica delle variabili.</li>
<li>Safe Casting (chiaramente come eredità di C++).</li>
<li>Restricted pointers: si può passare una funzione per referenza dichiarandola <code>ref</code>, ma solo quando passata come parametro o di ritorno. Inoltre non c&#39;è nessuna pointer arithmetic.</li>
<li><a href="https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization">RAII</a>, ovvero l&#39;acquisizione delle risorse equivale alla loro assegnazione e Scopes: le variabili hanno una lifetime limitata allo scope di dichiarazione. Nessun dangling pointer come in C.</li>
<li>Strutture immutabili: come nelle specifiche di molti linguaggi funzionali, si può dichiarare una variabile come <code>immutable</code> e quindi può essere facilmente condivisa fra threads.</li>
<li>@safe, @trusted: le specifiche del linguaggio permettono di annotare delle funzioni come sicure o affidabili affinchè il compilatore controlli che non gestiscano puntatori (ad esempio interfacciandosi con C) ed utilizzino il subset &quot;sicuro&quot; del linguaggio (maggiori dettagli in seguito).</li>
<li>funzioni pure: le funzioni inoltre possono essere dichiarate pure, prive di effetti collaterali e sempre <a href="https://en.wikipedia.org/wiki/Reentrancy_(computing)">rientranti</a>. Questo permette di evitare <a href="https://en.wikipedia.org/wiki/Deadlock">deadlocks</a> e un controllo totale sul risultato delle funzioni.</li>
</ul>
<h4 id="performance">Performance</h4>
<p>Ci sono moltissime soluzioni per scrivere un applicativo che si interfaccia con il web, ma hanno tutte la loro origine nel famoso <a href="http://www.kegel.com/c10k.html">C10K problem</a>.</p>
<p>Nel mio caso ho deciso di utilizzare un approccio <a href="https://stackoverflow.com/questions/10960998/how-different-async-programming-is-from-threads">asincrono</a> con coroutines (anche detti <a href="https://en.wikipedia.org/wiki/Green_threads">threads leggeri</a>).</p>
<p>Benchè D abbia <a href="https://dlang.org/library/core/thread/fiber.html">supporto nativo</a> alle coroutines, ho deciso di appoggiarmi al framework più comune per web dev in D: <a href="vibed.org">vibe.d</a>.</p>
<p>Ogni volta che Vibe accetta una richiesta dall&#39;esterno ed esegue una funzione bloccante (che interrompe l&#39;esecuzione del programma fino al ritorno della funzione), questa viene messa in una pool di azioni da eseguire e Vibe controlla periodicamente che almeno una di queste sia pronta a ritornare un risultato e continuare con l&#39;esecuzione di questa.</p>
<p>Inoltre, benchè questo meccanismo funzioni interamente su un solo thread, è elementare coordinare una <a href="https://en.wikipedia.org/wiki/Thread_pool">thread pool</a> che distribuisa il carico fra i vari core che eseguono migliaia di threads leggeri concorrentemente.</p>
<h4 id="contratti-e-tests">Contratti e Tests</h4>
<p>Non amo scrivere commenti sui programmi. Penso sia assolutamente necessario commentare il codice di librerie ma al di fuori di queste il codice (buon codice) dovrebbe essere autoesplicativo.</p>
<p>Inoltre, nelle mie recenti esperienze, il comportamento del programma era chiaro a partire dai tests.</p>
<p>In D questo concetto viene portato agli estremi applicando il <a href="https://en.wikipedia.org/wiki/Design_by_contract">&quot;Design by Contract programming</a>.</p>
<p>Un contratto è la divisione di una funzione in:</p>
<ul>
<li>Precondizione, ovvero le condizioni che devono essersi verificate prima della chiamata della funzione;</li>
<li>Postcondizione, ovvero le condizioni che devono essere rispettate all&#39;uscita della funzione (solitamente applicate al risultato);</li>
<li>Invarianti, ovvero le specifiche di una struttura dati che devono rimanere verificate in ogni funzione;</li>
<li>Corpo della funzione</li>
</ul>
<p>Un esempio:</p>
<div class="highlight"><pre><code class="language-" data-lang="">
struct Clock {
short time;
invariant {
assert (time &gt; 0);
}
}
short addReturnTime(Clock c, short n)
in {
n &gt; 0;
}
body {
return c-&gt;time + t;
}
out (result){
result &gt; c-&gt;time;
}
unittest {
auto clock = Clock(60);
assert (addReturnTime(clock, 10) == 70);
}
</code></pre></div>
<p>Come si nota dall&#39;esempio il supporto ai tests è built-in nel linguaggio e distanti solo una flag in fase di compilazione.</p>
<h4 id="un-approccio-moderno-alle-concorrenze">Un approccio moderno alle concorrenze</h4>
<p>Il modello primitivo delle concorrenze in Posix è discutibilmente datato e prono ad errori per il programmatore.</p>
<p>D di default evita la condivisione di dati fra Threads.
Fra le varie motivazioni c&#39;è il fatto che questo rifletta più realisticamente l&#39;hardware, ma sicuramente l&#39;obbiettivo finale è la riduzione di bug.</p>
<p>Non voglio dilungarmi nei dettagli di ogni singolo approccio, ma per completezza D offre out of the box i seguenti modelli:</p>
<ul>
<li>Message passing e <a href="http://dist-prog-book.com/chapter/3/message-passing.html">attori</a>, ovvero tutti i dati che vogliono essere condivisi fra thread sono incapsulati in <a href="https://en.wikipedia.org/wiki/Remote_procedure_call">RPC</a>;</li>
<li>Green threads, come nel mio caso;</li>
<li>Multi processing, ovvero <code>man 3 fork</code></li>
<li>TaskPools, ovvero future e promises di Python e Javascript;</li>
<li><a href="http://moss.csc.ncsu.edu/%7Emueller/cluster/ps3/SDK3.0/docs/accessibility/sdkpt/cbet_1simdvector.html">SIMD vectorization</a></li>
</ul>
<p>Andrei Alexandrescu, uno dei due creatori del linguaggio, dedica un intero capitolo alle concorrenze che potete leggere liberamente <a href="http://www.informit.com/articles/article.aspx?p=1609144">qui</a>.</p>
<h4 id="assenza-di-dogmatismi">Assenza di dogmatismi</h4>
<p>Non potrei mai pensare di scrivere un linguaggio di programmazione senza mettere al secondo posto la semplicità.</p>
<p>Ma chiaramente ancora prima di discutere di semplicità la dobbiamo definire.</p>
<p>Go e Python sono due linguaggi semplici. Lo sono per la ridotta sintassi (Go in particolare) e perchè attraverso il loro dogmatismo costringono il programmatore ad adottare dei paradigmi di programmazione scelti dai designer di quel linguaggio. E` il motivo per cui in python non abbiamo delle vere lambda e per cui Go non ha le eccezioni.</p>
<p>In D il programmatore ha libertà piena di scelta. Oltre ad un paradigma di programmazione si può ridefinire la sintassi e evitare il Garbage Collector. Si può in ultimo disattivare tutte le feature del linguaggio che sono @safe e adottare uno stile molto più vicino al C/C++, con tanto di inline asm.</p>
<h2 id="dove-iniziare">Dove iniziare</h2>
<p>Non posso non concludere un post propagandistico senza indirizzare i più interessati alle prime risorse per imparare D.</p>
<p>Personalmente consiglio il <a href="http://www.informit.com/store/d-programming-language-9780321635365?w_ptgrevartcl=Concurrency+in+the+D+Programming+Language_1609144">libro</a> di Andrei che offre in particolare moltissimi dettagli sulle motivazioni del design di D. Non ho ancora letto un libro che affrontasse così chiaramente il design di linguaggi di programmazione e i vari compromessi fra performance, semplicità e complessità del compilatore.</p>
<p>Inoltre il sito della community offre due intro per chi proviene da <a href="https://dlang.org/ctod.html">C</a> e <a href="https://dlang.org/cpptod.html">C++</a>, oltre al classi <a href="https://tour.dlang.org/">tour</a>.</p>
<p>Inoltre la libreria standard, <a href="https://github.com/dlang/phobos">Phobos</a>, è talmente chiara che solitamente mi trovo a mio agio a consultare direttamente il codice piuttosto che la documentazione online.</p>
</div>
<!--<div class="related">-->
<!--<related-posts />-->
<!--<h2>Related Posts</h2>-->
<!--<ul class="related-posts">-->
<!---->
<!--<li>-->
<!--<h3>-->
<!--<a href="/pescewanda/2018/03/27/addio-reddit/">-->
<!--Addio Reddit-->
<!--<small>27 Mar 2018</small>-->
<!--</a>-->
<!--</h3>-->
<!--</li>-->
<!---->
<!--<li>-->
<!--<h3>-->
<!--<a href="/pescewanda/2017/10/02/minidoxguide/">-->
<!--Minidox, a guide for the Europeans and the Scrooges-->
<!--<small>02 Oct 2017</small>-->
<!--</a>-->
<!--</h3>-->
<!--</li>-->
<!---->
<!--<li>-->
<!--<h3>-->
<!--<a href="/pescewanda/2017/05/09/vaporwave/">-->
<!--Cyber-utopia and vaporwave-->
<!--<small>09 May 2017</small>-->
<!--</a>-->
<!--</h3>-->
<!--</li>-->
<!---->
<!--<li>-->
<!--<h3>-->
<!--<a href="/pescewanda/2017/05/07/latestage_handbrake/">-->
<!--Late Stage Capitalism meets FOSS-->
<!--<small>07 May 2017</small>-->
<!--</a>-->
<!--</h3>-->
<!--</li>-->
<!---->
<!--<li>-->
<!--<h3>-->
<!--<a href="/pescewanda/2017/03/20/spazio-digitale-rant-facebook__eng/">-->
<!--Some shallow thoughts from my tiny virtual space-->
<!--<small>20 Mar 2017</small>-->
<!--</a>-->
<!--</h3>-->
<!--</li>-->
<!---->
<!--</ul>-->
<!--</div>-->
<h4>Similar Posts</h4>
<ul>
<li class="relatedPost">
<a href="/pescewanda/2017/05/07/latestage_handbrake/">Late Stage Capitalism meets FOSS
</a>
</li>
</ul>
<footer class="site-footer">
<!--<span class="site-footer-owner"><a href="http://francescomecca.eu">Caught in the Net</a> is maintained by <a href="contattami">Francesco Mecca</a>.</span>-->
<span> CC BY-SA 4.0 International.</br> </span>
<span class="site-footer-credits"><a href="https://jekyllrb.com">Jekyll</a>, <a href="https://github.com/jasonlong/cayman-theme">Cayman theme</a>.</span>
</footer>
</section>
</body>
</html>