Come scrivere g̶o̶o̶d no, ottimo codice

Feb 09 2023
Un'opinione non scientifica e completamente soggettiva da parte di uno sviluppatore casuale online.
chi è questo tizio che pensa sia? Cosa ne sa di scrivere codice "fantastico"?! Avresti ragione al 100% se lo pensassi - e ad essere completamente onesto ... ho molta più esperienza nella scrittura di codice non eccezionale. il codice non eccezionale viene scritto per molte ragioni (alcune elencate di seguito) Nonostante la mia profonda esperienza con il codice non ottimale, ho quasi un decennio di esperienza nel chiedere al computer (il più gentilmente possibile) di fare le cose che io e altri umani vogliamo.
Live Oaks (Un bellissimo organismo dinamico complesso) — Wormsloe Historic Site, Savannah, GA, USA di Ryan Arnst

chi è questo tizio che pensa sia? Cosa ne sa di scrivere codice "fantastico"?!

Avresti ragione al 100% se lo pensassi - e ad essere completamente onesto ... ho molta più esperienza nella scrittura di codice non eccezionale.

il codice non eccezionale viene scritto per molte ragioni (alcune elencate di seguito)

  1. è difficile
  2. "ottimo" è soggettivo
  3. il software non è mai finito (non può "essere" eccezionale, deve "rimanere" eccezionale)
  4. la qualità può cambiare in base alle esigenze attuali
  5. un sacco di software funzionante non è eccezionale (cattivi modelli di ruolo)
  6. le persone che vogliono il software spesso non sono ingegneri del software
  7. …

Nonostante la mia profonda esperienza con il codice non ottimale, ho quasi un decennio di esperienza nel chiedere al computer (il più gentilmente possibile) di fare le cose che io e altri umani vogliamo.

In questo periodo ho imparato ad apprezzare vari concetti e modelli, e ho anche imparato una profonda sfiducia per gli altri.

In questo articolo delineerò alcuni degli aspetti positivi e negativi del software e fornirò prove a sostegno di persone realmente intelligenti.

Benvenuti alla corsa

Cosa è "ottimo"

Iniziamo definendo cos'è "grande". Tuttavia potrebbe essere più facile da definire affermando rapidamente cosa non è.

Ottimo codice è

  1. non è difficile da leggere
  2. non è difficile ragionare
  3. non ti fa odiare te stesso oggi o 7 giorni dopo averlo scritto
  1. 90% struttura e 10% sintassi
  2. una funzione di astrazione delle informazioni abbinata alla gestione prevista delle risorse
  3. un amico della matematica (in particolare teoria degli insiemi/categoria)
  4. scritto per gli esseri umani non per l'hardware

1. Struttura al 90% e sintassi al 10%.

Tutte le idee di tesi sono ispirate da argomenti molto più completi e profondi. Per quanto riguarda la struttura possiamo guardare al paradigma di programmazione SOLID.

SOLID sta per un insieme di 5 "regole" che dovrebbero essere seguite per creare software gestibile. Concetti elencati di seguito

S - Single-responsiblity Principle
O - Open-closed Principle
L - Liskov Substitution Principle
I - Interface Segregation Principle
D - Dependency Inversion Principle

Questi principi ruotano attorno al potere della programmazione orientata agli oggetti (lo adori o lo odi) e descrivono un modo elegante per suddividere le tue astrazioni in blocchi compatibili con il software.

Seguendo questi principi è possibile evitare molte brutte complessità che sorgono nel software funzionale.

Ad esempio, con i principi SOLID ridurrai l'impronta del tuo codice e centri i file attorno a funzionalità comuni; semplificando la navigazione e l'aggiunta/rimozione di funzionalità senza influire su altre parti della base di codice.

Questi problemi vengono completamente evitati a livello di struttura della tua applicazione, piuttosto che a livello di codice

La pulizia a livello di struttura è un modo potente per imporre un'organizzazione duratura.

Articolo facile da digerire su SOLID di Digital Ocean: qui

Se ciò non bastasse, lo zio Bob continua a lanciare colpi .

Consiglio vivamente il suo libro più recente pubblicato nel 2017 (e onestamente anche tutto ciò che è più recente).

"Architettura pulita: guida di un artigiano alla struttura e al design del software" —https://www.oreilly.com/library/view/clean-architecture-a/9780134494272/

Questo libro esplora come estendere questi concetti al livello di sistema .

Man mano che spostiamo più applicazioni nel "cloud" e sfruttiamo i servizi distribuiti. Questi principi di progettazione hanno un impatto sempre maggiore sulla grandezza del tuo codice.

ottimo codice è solo uno strumento che riempie la struttura del design delle tue applicazioni, il tuo sistema dovrebbe essere espresso tramite la sua struttura e non la sintassi.

2. una funzione di astrazione delle informazioni abbinata alla gestione prevista delle risorse

Ehm, cosa. Mi hai davvero perso con quello. una funzione di whaa?

scomponiamolo.

"una funzione di astrazione delle informazioni" è un modo conciso per esprimere che il nostro codice è l'output delle nostre astrazioni .

In altre parole, il nostro codice riflette il modo in cui abbiamo deciso di suddividere i concetti della nostra applicazione.

Più concretamente; se ci troviamo di fronte a un problema e decidiamo di creare "Utenti" e "Sessioni", abbiamo effettivamente suddiviso il nostro problema in quelle idee astratte di utenti e sessioni.

…okay Penso che abbiamo coperto “una funzione di astrazione delle informazioni”.

Successivamente lo abbiniamo alla "gestione prevista delle risorse", che è un modo elegante per dire che gli ingegneri del software hanno il compito di essere in grado di vedere nel futuro e costruire sistemi in grado di resistere ai cambiamenti futuri

Se non lo sapevi, è colpa tua come programmatore se non hai utilizzato il framework più recente un anno prima che fosse creato. Come hai fatto a non saperlo!? (si prega di leggere come sarcasmo - prometto che non è personale).

Quindi, per riassumere; la qualità del nostro codice non è sempre la sua complessità computazionale, il numero di righe oi nomi eleganti delle variabili.

È la capacità di suddividere efficacemente il tuo problema in blocchi astratti che resisteranno ai cambiamenti imprevedibili di domani.

Sì sì sì, lo so; non sembra possibile. Beh, non lo è - ed è nostro compito come sviluppatore gestire le cose che sappiamo e le cose che sappiamo di non sapere.

È un esercizio di valutazione del rischio e pianificazione dei costi - eh, non sapevo che ti fossi iscritto a quello vero.

Tuttavia, c'è speranza!

Seguendo concetti affidabili (ne arriveranno altri a breve) possiamo rafforzare noi stessi e le applicazioni per un mondo che cambia.

Prima di entrare nelle cose veramente buone, possiamo riconoscere alcune idee degne di "fiducia" qui.

  • Organismi di standardizzazione (ci sono persone che ci hanno già riflettuto a fondo e apprezzerebbero davvero se usufruissi del loro ottimo lavoro. Questo vale soprattutto per algoritmi, sicurezza, multipiattaforma e altre cose davvero importanti come i codici QR).
  • Linguaggi statici e fortemente tipizzati (onestamente non si tratta proprio dei problemi di sicurezza di basso livello che eviterai. Riguarda la natura incentrata sull'uomo dei tipi. uno, se violi il tipo nel tuo codice il compilatore ti urlerà contro e due, altri sviluppatori sapranno effettivamente cosa sta facendo il tuo codice).
  • Poesia (meno sulle parole e più sulla capacità di comunicare significati complessi con pochi simboli. Il tuo codice è poesia, anche se un pubblico molto privo di fantasia, ma dovrebbe comunque essere breve e dolce).

Anche se potresti non esserlo, il tuo codice dovrebbe essere amico della matematica.

Sì, lo so: la matematica è noiosa e non hai mai usato una derivata nella vita reale.

Ma…. Lo prometto: può essere di grande aiuto. In realtà è lo strumento più affidabile che abbiamo.

È affidabile perché ha una lunga storia di contributi open source e hanno risolto la maggior parte dei bug nel software di base. Ora gli sviluppatori (matematici) sono impegnati a capire cose folli come la fisica quantistica.

Possiamo fidarci di cose utili come la crittografia per proteggere i nostri conti bancari e le nostre comunicazioni. Possiamo fidarci della teoria degli insiemi per imporre il sistema di tipi di [AGGIUNGI QUI IL LINGUAGGIO DI PROGRAMMAZIONE PREFERITO]. Possiamo persino spingerci fino a fidarci dell'algebra lineare per ottimizzare il nostro percorso su Google Maps e ChatGPT per rimanere cose stupide.

È importante ricordare che dietro tutta l'interfaccia utente fantasiosa e lo schermo brillante, i nostri computer sono proprio questo; computer.

Se elimini tutte le complessità, rimani con le ossa nude dell'addizione e della sottrazione.

Forse, solo forse... c'è un modo per trasferire tutto quel potere al nostro codice.

Andiamo un po' più a fondo

Farò un'ipotesi selvaggia e presumo che tu (il lettore) abbia familiarità con la programmazione orientata agli oggetti,

E... arriverò anche a indovinare che hai sentito parlare di Programmazione funzionale, ma hai deciso che era qualcosa da imparare un altro giorno.

Se sei in quel campo, potresti non essere consapevole della bellezza e dell'eleganza dei linguaggi di programmazione che seguono più da vicino la semantica della matematica tradizionale.

Noi (persone normali) siamo viziati dalle astrazioni fornite dai linguaggi tradizionali. Ci aspettiamo di poter creare variabili ogni volta che vogliamo e costruire flussi di controllo complessi con torri di ifeelse

Noi (persone normali) dovremmo tuttavia prendere nota della nostra controparte di programmazione funzionale più intelligente.

Ci sono superpoteri nascosti in linguaggi semplici e vincolanti. Forniscono metodi dimostrabili ( ⚡️ alimentati dalla matematica ) per dimostrare che il tuo codice copre tutti i casi o che può essere suddiviso in parti discrete di lavoro che possono essere distribuite su infinite macchine.

Infinity e Proofs sono idee difficili per il programmatore medio, ma qualsiasi matematico le mangia a colazione.

Ad esempio, uno di questi supereroi nel video qui sotto mostra come la modellazione di un sistema può fornire modi per trovare istruzioni passo passo per sfruttare bug incredibilmente complessi senza guardare una riga di codice reale

Il segreto sta nel potere della matematica formale applicata alla progettazione del sistema.

Se applicato correttamente (e no, questo non richiede la riscrittura di tutto in un linguaggio funzionale), otterrai gratuitamente tutti i vantaggi della matematica.

Questi vantaggi includono ma non sono limitati a

  • generando automaticamente test per ogni singolo modo possibile in cui il tuo programma potrebbe essere utilizzato
  • esplorare le implicazioni dell'aggiunta di componenti o sistemi di rimozione alla tua applicazione
  • essere sicuro al 100% che il codice funzionerà. Vuoi essere davvero sicuro che il software del carrello di atterraggio del tuo aereo funzioni, vero?
  • altre cose più complesse che i relatori in questi video possono insegnarti. Oh, e se sei seriamente intenzionato a imparare questo, dai un'occhiata a TLA+

Forse possiamo usare alcuni di quei concetti incredibilmente noiosi per rendere il nostro codice noiosamente sorprendente.

il grande codice dovrebbe aspirare ad avere idee così concrete che quelle stesse idee siano vere tra più di 1000 anni

Pathagotem ha inventato un ottimo software per i triangoli nel ~ 570 aC…. è come 1500 anni fa!

Forse dovremmo imparare o usare la matematica quando possibile: è il modo migliore in cui noi umani conosciamo per esprimere astrazioni di lunga durata.

4. scritto per gli esseri umani non per l'hardware

Va bene abbastanza con le cose di matematica. Quando parliamo di software, tanto quanto cerchiamo di evitare gli umani. Entrano sempre nel mix.

Parliamo di umani. Come si inseriscono gli esseri umani?

Beh... sono quelli che vogliono il software in primo luogo, e in realtà sono quelli che hanno inventato questi linguaggi.

Inoltre sono quelli che si preoccupano di tutta questa faccenda: i computer non hanno opinioni sul codice che eseguono.

Le persone fanno. Le persone definiscono cosa "funziona" e cosa no.

Quindi - immagino che dovremmo orientare tutto per il diritto umano?

SÌ! e questo non significa solo che abbiamo bisogno di belle interfacce utente e app mobili ergonomiche.

Dobbiamo estendere l'umanità allo sviluppo del software. Dovremmo sentirlo a molti livelli.

L'umanità dovrebbe essere nell'esperienza dello sviluppatore a tutti i livelli. Quelle che seguono sono alcune domande incentrate sull'uomo.

  • Le persone vengono imbarcate su codebase. La tua documentazione lo facilita?
  • Quanti strumenti/comandi o passaggi di configurazione speciali devo eseguire?
  • Che aspetto ha l'aggiunta di un nuovo test? una nuova funzionalità?
  • Quanti framework/linguaggi impone il tuo progetto? Potrebbe essere di meno?
  • Quanto impegno è necessario per passare da completamente nuovo a completamente in produzione?
  • Che aspetto ha la rottura? e dovrò svegliarmi per ripararlo?

Ma un piccolo team di bravi sviluppatori è maggiore della somma se si tratta di parti (se eseguite correttamente).

Quindi, come otteniamo un ottimo codice da un team?

Alcune soluzioni sono più facili di altre. Ad esempio, uno semplice ma efficace è quello di standardizzare tutto: rimuovere ogni personalità dai contributi individuali.

Anche se suona duro, un sistema solido avrà modi/tipi/modelli specifici per fare le cose. Dovrebbe esserci pochissima personalizzazione e creatività all'interno della sintassi del codice.

Perché questa è una cosa buona? Allevia notevolmente il carico mentale dello sviluppatore. Se c'è un "modo" per fare qualcosa, allora dovrebbe essere fatto in quel "modo".

Ciò sposta efficacemente la soluzione dal livello del codice al livello della struttura (menzionato in precedenza). Dal momento che dobbiamo fare affidamento su decisioni e modelli a livello di sistema piuttosto che su misura.

Più semplicemente, tutti gli sviluppatori dovrebbero condividere tipi comuni. Ciò rimuove la personalizzazione e rende molto più semplice l'integrazione del lavoro di vari sviluppatori.

Questa idea dovrebbe estendersi ben oltre i tipi e tanti concetti che possono essere efficacemente standardizzati a livello di sistema, maggiore sarà il tuo codice.

ottimo codice è così ben scritto dai contributi di diversi membri del team è spesso indistinguibile da altre parti della base di codice. Inoltre non dovresti essere in grado di vedere dove una persona ha iniziato e un'altra è finita.

Nel seguente video vengono analizzate in dettaglio le strategie per creare team e aumentare la produttività man mano che un sistema diventa più complesso.

Questo è un argomento affascinante poiché le idee sulla progettazione di sistemi complessi sono ben al di fuori dell'ambito dei computer e toccano fenomeni naturali come la biologia animale/vegetale, le interazioni sociali ei pianeti.

Noi semplici mortali/sviluppatori deteniamo molto potere nelle nostre mani. Possiamo costruire enormi pile di merda complessa e inutile - e con quelle stesse mani possiamo costruire i nostri complessi sistemi dinamici non diversi dal pianeta su cui sto scrivendo questo.

Alla prossima volta, continua a programmare, diffondi amore e pace ✌️