# Come costruisco il software: fatelo funzionare, fatelo bello, bloccatelo giù

<datetime class="hidden">2025-11-19T10:00</datetime>

<!-- category -- Software Development, Testing, TDD, Craftsmanship, Best Practices -->
**Perche' scrivo i test per ultimo, e perche' non e' quello che pensi significhi**

> **Prendiamo la controversia:**Test-Driven Development è una pratica brillante che risolve il problema sbagliato per la maggior parte del lavoro creativo.

## Ecco cosa funziona meglio.

Le tre fasi del software di costruzione (che funziona effettivamente)

**E' cosi' che costruisco il software.**

E 'semplice, è efficace, e rende i puristi TDD gentilmente solcare le loro sopracciglia:

Fallo funzionare.*Rendilo carino.*Bloccalo con gli esami.

```mermaid
graph TB
    Start[New Feature Request] --> P1[Phase 1: Make It Work]

    P1 --> P1_Private[Private Exploration]
    P1_Private --> P1_Sketch["Sketch the solution<br/>Messy code OK<br/>No tests yet<br/>Focus on learning"]
    P1_Sketch --> P1_Run["Run it manually<br/>Try different inputs<br/>See what breaks<br/>Understand the problem"]
    P1_Run --> P1_Decision{Does it work<br/>basically?}
    P1_Decision -->|No| P1_Iterate[Try different approach]
    P1_Iterate --> P1_Sketch
    P1_Decision -->|Yes| P2

    P2[Phase 2: Make It Pretty] --> P2_Refine[Private Refinement]
    P2_Refine --> P2_Clean["Clean up the code<br/>Better names<br/>Type hints/annotations<br/>Clear structure"]
    P2_Clean --> P2_Align["Align with spec<br/>Cover all requirements<br/>Handle edge cases<br/>Polish API surface"]
    P2_Align --> P2_Optimise["Optimise<br/>Performance<br/>Readability<br/>Maintainability"]
    P2_Optimise --> P3

    P3[Phase 3: Lock It Down] --> P3_Share[Public Sharing]
    P3_Share --> P3_Tests["Write comprehensive tests<br/>Full coverage<br/>Edge cases<br/>Error conditions"]
    P3_Tests --> P3_CI["CI/CD Integration<br/>Automated testing<br/>Code review<br/>Documentation"]
    P3_CI --> P3_Deploy["Ready to Share<br/>Commit to main<br/>Deploy to prod<br/>Other devs can use it"]

    P3_Deploy --> Done[Well-Tested,<br/>Well-Designed Code]

    style P1 stroke:#ff6b6b,stroke-width:3px
    style P2 stroke:#4ecdc4,stroke-width:3px
    style P3 stroke:#95e1d3,stroke-width:3px
    style Done stroke:#38ada9,stroke-width:4px
```

In quest'ordine.*Sempre.*Non perche' sono pigro.

Non perche' non valgo i test.

[TOC]

## Ma perche'

questo è il modo in cui il lavoro creativo realmente accade

quando stai esplorando uno spazio problematico non riesci ancora a capire appieno.

- Non perche' sono pigro.
- Non perche' non valgo i test.
- Ma perche'
- questo è il modo in cui il lavoro creativo realmente accade

**quando stai esplorando uno spazio problematico non riesci ancora a capire appieno.**

Lascia che ti spieghi.

### Fase 1: Farlo funzionare (Lo Schizzo Privato)

Questa e' la parte disordinata.**La parte in cui non ho idea di cosa sto facendo.**

Sto cercando di capire:

Questa API funziona davvero nel modo in cui i documenti sostengono?

Posso risolvere questo problema con gli strumenti che ho?

Che cosa significa "corretto" in questo contesto?*E' un problema di due ore o di due settimane?*Questa e' un'invenzione.

**Questa è esplorazione.**

Questo e' jazz.

```python
# Ugly, exploratory code
def process_thing(data):
    # TODO: This is terrible, fix later
    result = []
    for item in data:
        # Not sure if this is the right approach...
        x = item.get('value')
        if x:  # Is this even the right condition?
            result.append(x * 2)  # Why multiply by 2? Testing something...
    return result
```

E sai cosa uccide il jazz?**Qualcuno in piedi sopra la tua spalla che dice "scrivi prima il test."**Perche' ancora nessun test?

Perche'*la forma è ancora fluida.*Immagina di essere uno scultore.

Hai un blocco di marmo e un'idea vaga: "Voglio scolpire un uccello."

### TDD dice: "Prima di toccare quel marmo, scrivi esattamente come appare un uccello.

Definisci la sua apertura alare.**Specificare l'angolo di ciascuna piuma.**

Ora scolpisci queste specifiche."*Non e' cosi' che gli uccelli vengono scolpiti (o il software viene scritto, a quanto pare.)*Scultori veri

Per prima cosa distruggi il modulo.**Disegnano.**

Fanno le maquette.*Tagliano via grossi pezzi di pietra per trovare la forma generale.*Solo più tardi affinano i dettagli.

Il codice e' lo stesso.

### Nella Fase 1, scrivo:

Questo codice è

privata.

E' una conversazione con me stesso.

E' cosi' che capisco cosa significhi "lavorare."

## Scrivere test per questo è peggio di inutile

attivamente dannoso.

**Perché ogni volta che mi rendo conto che "oh aspetta, questo approccio è sbagliato," dovrei riscrivere anche i test.**

Quello non e' rigore.

### E' burocrazia.

**La libertà di fallire velocemente**

```python
# Before (Phase 1) - Exploratory code
def process_thing(data):
    result = []
    for item in data:
        x = item.get('value')
        if x:
            result.append(x * 2)
    return result

# After (Phase 2) - Refined code
def extract_doubled_values(items: list[dict]) -> list[int]:
    """Extract 'value' field from items and double each one.

    Only includes items where 'value' is present and truthy.
    """
    return [
        item['value'] * 2
        for item in items
        if item.get('value')
    ]
```

**La fase 1 è circa**

```csharp
// Before (Phase 1) - Exploratory code
public List<int> ProcessThing(List<Dictionary<string, object>> data)
{
    var result = new List<int>();
    foreach (var item in data)
    {
        if (item.ContainsKey("value"))
        {
            var x = item["value"];
            if (x != null)
            {
                result.Add(Convert.ToInt32(x) * 2);
            }
        }
    }
    return result;
}

// After (Phase 2) - Refined code
/// <summary>
/// Extracts 'value' field from items and doubles each one.
/// Only includes items where 'value' is present and non-null.
/// </summary>

public IEnumerable<int> ExtractDoubledValues(IEnumerable<IDictionary<string, object>> items)
{
    return items
        .Where(item => item.ContainsKey("value") && item["value"] != null)
        .Select(item => Convert.ToInt32(item["value"]) * 2);
}
```

velocità di apprendimento.

### Devo provare cinque diversi approcci in un'ora.

Devo scoprire che la libreria di terze parti che ho pensato di usare... non e' esattamente come pubblicizzato.*Devo capire che il problema che sto risolvendo non e' il problema che sto risolvendo.*dovrebbe*Risolvere.*I test rallentano.

Non perché il test è lento, ma perché

- Le specifiche premature sono morte.
- Se scrivo test prima di capire il problema, sto scrivendo test per il
- Una cosa sbagliata.

Allora sono emotivamente coinvolto nella cosa sbagliata.

### Allora difendo la cosa sbagliata nella revisione del codice.

Meglio fallire velocemente, in privato, senza test da mantenere e senza ego da proteggere.*Cosa significa "lavorare" nella fase 1*Significa: "L'ho gestita io.

**Gli ho dato degli input.**

```python
# Phase 1: Works, but awkward to use
process_thing(data)

# Phase 2: Clear, flexible, composable
extract_doubled_values(
    items,
    scale_factor=2.0,
    include_zeros=False
)
```

**Ha prodotto output che sembrano ragionevoli.**

```csharp
// Phase 1: Works, but awkward to use
ProcessThing(data);

// Phase 2: Clear, flexible, composable
ExtractDoubledValues(
    items,
    scaleFactor: 2.0,
    includeZeros: false
);

// Or even better with a fluent API
items.ExtractValues()
     .Scale(by: 2.0)
     .ExcludingZeros()
     .ToList();
```

Sono sicuro al 60% di capire il problema ora."

Tutto qui.**Niente bordelli.**Nessun errore di gestione.

```mermaid
graph LR
    subgraph "Phase 2 Refinement Process"
        A[Rough Code] --> B[Clean Structure]
        B --> C[Add Types]
        C --> D[Polish API]
        D --> E[Static Analysis]
        E --> F{Quality Gates Pass?}
        F -->|No| G[Fix Issues]
        G --> B
        F -->|Yes| H[Ready for Phase 3]
    end

    style A stroke:#ff6b6b,stroke-width:3px
    style H stroke:#95e1d3,stroke-width:3px
```

### Nessuna eleganza.

*Solo un picco.*Una prova di concetto.

Uno sketch.*Fase 2: Rendilo gradevole (Il affinamento)*

Ok, ora capisco il problema.**Ho qualcosa che funziona, almeno per il percorso felice.**

Ora posso iniziare a preoccuparmi della qualita'.

- La fase 2 è dove io:
- 1.
- Pulisci il messaggio

Esempio di Python:*Esempio di C#:*Nome migliore.

Digitare annotazioni.*Documentazione XML.*Implementazione LINQ più pulita.

## 2.

Allinea con lo specifico

Ora che so cosa sto costruendo, torno ai requisiti originali e mi assicuro di risolvere il problema.

**destra**

### problema, non solo

a**Problema.**

Spesso ciò rivela lacune:

"Oh, volevano che questo gestisse i numeri negativi in modo diverso."

1. **"Aspetta, c'e' un caso in cui il valore potrebbe essere Nessuno contro 0."**"La specifica dice "doppio" ma penso che intendessero "scalare per un fattore configurabile."
2. **Li sistemo io.**A volte rispondo alle specifiche: "In realtà, dovremmo fare X invece perché Y."
3. **3.**Lucida la superficie delle API
4. **E' qui che penso al**chiamante

esperienza.**Python:**C#:

Meglio chiamare.

- Predefiniti sensibili.
- Configurazione dove conta.
- API fluenti, se del caso.
- Questo e'
- Un mestiere.

### E' da qui che proviene un buon software.

Perche' ancora nessun test?

```python
def test_extract_doubled_values_basic():
    items = [{'value': 5}, {'value': 10}]
    assert extract_doubled_values(items) == [10, 20]

def test_extract_doubled_values_skips_missing_values():
    items = [{'value': 5}, {'name': 'foo'}, {'value': 3}]
    assert extract_doubled_values(items) == [10, 6]

def test_extract_doubled_values_handles_zeros():
    items = [{'value': 0}, {'value': 5}]
    # By default, zeros are excluded (falsy)
    assert extract_doubled_values(items) == [10]

def test_extract_doubled_values_includes_zeros_when_configured():
    items = [{'value': 0}, {'value': 5}]
    assert extract_doubled_values(items, include_zeros=True) == [0, 10]

def test_extract_doubled_values_custom_scale_factor():
    items = [{'value': 5}]
    assert extract_doubled_values(items, scale_factor=3.0) == [15.0]

def test_extract_doubled_values_rejects_negative_scale_factor():
    with pytest.raises(ValueError):
        extract_doubled_values([], scale_factor=-1.0)

def test_extract_doubled_values_handles_empty_list():
    assert extract_doubled_values([]) == []

def test_extract_doubled_values_handles_non_numeric_values():
    items = [{'value': 'not a number'}]
    with pytest.raises(TypeError):
        extract_doubled_values(items)
```

**Oh, lo gestisco sempre.**

Ho una REPL aperta.

- Sto provando ingressi diversi.
- Sto esercitando tutte le strade.
- Ma non lo sono.
- Scrivo quegli esperimenti come test formali.

### Perché?

Perche'

```python
# This comment will drift from reality:
# Doubles all numeric values, skipping None

# This test will fail if reality changes:
def test_extract_doubled_values_skips_none_values():
    items = [{'value': None}, {'value': 5}]
    assert extract_doubled_values(items) == [10]
```

Sto ancora scoprendo cosa vale la pena testare.

Nella Fase 1, non sapevo nemmeno se questa funzione esistesse.**Nella Fase 2, sto scoprendo:**"Oh, il fattore di scala non può essere negativo.

### E' una convalida."

"Se la lista è vuota, dovremmo tornare vuoti, non Nessuno."**"Dobbiamo gestire con grazia i valori non numerici."**

Queste intuizioni

emergono dal refactoring.

Non sono ovvi in anticipo.

1. **Se avessi scritto dei test in fase 1, li riscriverei ora.**Se le scrivo
2. **dopo**Ho perfezionato l'implementazione, saranno corrette la prima volta.
3. **Fase 3: Bloccarlo con i test (fase di condivisione)**Ok, ora e' reale.

Il codice e' pulito.*L'API ha senso.*Ho coperto le valigie.

## Sono sicuro di quello che ho costruito.

Ora scrivo dei test.

Un sacco di test.

Test di copertura quasi completa come possibili.**Perche' adesso?**

Perche'

I test sono un meccanismo di condivisione.*Non sono piu' per me.*

Capisco già questo codice intimamente.

- Ci ho vissuto per ore o giorni.
- Le prove sono per:
- Future Me
- (che dimenticherà tutto in tre mesi)*I miei compagni di squadra*(chi ha bisogno di fidarsi di questo codice funziona)

Il gasdotto CI

**(che deve prevenire le regressioni)**

Manutentori futuri

## (che hanno bisogno di rivalutare in modo sicuro questo)

Le prove sono le seguenti:**livello di presentazione**

per la mia attuazione.**Essi documentano:**

Cosa fa questo codice*Quali ingressi sono validi*Che risultati ci aspettiamo?

### Quali casi di bordo ho preso in considerazione

Che supposizioni sto facendo?

**Copertura completa, senza compromessi**

- In fase 3, vado duro sul test:
- Questa è la rete di sicurezza.
- Ora i miei compagni di squadra possono:

**Modifica con fiducia questa funzione**

- Comprendere i casi di bordo
- Regressioni di cattura immediatamente
- Refattore senza paura

**Prove come documentazione**

- Buoni test sono una migliore documentazione rispetto ai commenti:*I test non mentono.*Non possono andare alla deriva.
- Se il comportamento cambia, la prova si rompe.
- E'

**documentazione eseguibile.**

- E' questo che rende preziosi i test.
- Il confine della condivisione*Ecco il punto cruciale:*La fase 3 avviene prima che qualcun altro tocchi il codice.
- Non condivido il codice senza test.

### Mai.

```mermaid
graph TB
    subgraph "Traditional TDD (Red-Green-Refactor)"
        TDD1[Write Failing Test] --> TDD2[Write Minimal Code to Pass]
        TDD2 --> TDD3[Refactor]
        TDD3 --> TDD1
    end

    subgraph "Three-Phase Approach (Explore-Refine-Lock)"
        P1[Explore Solution Space] --> P2[Refine Implementation]
        P2 --> P3[Write Comprehensive Tests]
        P3 --> P4[Share With Team]
    end

    style TDD1 stroke:#ffaa00,stroke-width:2px
    style TDD2 stroke:#ffaa00,stroke-width:2px
    style TDD3 stroke:#ffaa00,stroke-width:2px
    style P1 stroke:#ff6b6b,stroke-width:3px
    style P2 stroke:#4ecdc4,stroke-width:3px
    style P3 stroke:#95e1d3,stroke-width:3px
```

**Ma non scrivo test prima che il codice sia pronto a condividere.**Le fasi sono:

**Esplorazione privata**(solo io, nessun test)

Rifinizione privata

(solo io, ancora nessun test)
|-----|-------------|
Condividere il pubblico
(test, CI, revisione del codice, tutti i nove metri)
Questo protegge sia la mia creatività*e* |
La sanita' mentale dei miei compagni di squadra.
Perché questo protegge la creatività

### I sostenitori del TDD dicono "i test ti danno fiducia nel refattore."

Vero!**Ma solo se sai gia' cosa stai costruendo.**

**Quando sono in fase 1, non ho bisogno di fiducia per rifattore.**

```
Hour 1: Write test for API I haven't designed yet
Hour 2: Realize the API is wrong, rewrite test
Hour 3: Discover a better approach, rewrite both
Hour 4: Finally get it working
Hour 5: Rewrite tests to match what actually works
```

**Mi serve il permesso di buttare via tutto.**

```
Hour 1: Explore 3 different APIs, settle on the best one
Hour 2: Refine the implementation, handle edge cases
Hour 3: Write comprehensive tests for what I built
Hour 4: All tests pass, commit with confidence
```

I test creano debiti psicologici.

### Una volta che li ho scritti, sono riluttante a cancellarli.

Anche se stanno testando la cosa sbagliata.**Ritardando le prove fino alla fase 3, mantengo la fase 1 e 2**

psicologicamente a buon mercato.

Posso:

- Prova idee selvagge
- Buttare via interi approcci
- Cambiare radicalmente il design

Scopri il problema che sono*In realta'*soluzione

### Tutto senza il senso di colpa di "ma ho scritto tutti quei test..."

**È così che funziona la creatività.**

```csharp
// Test 1: Write test first (but I don't know the right API yet)
[Test]
public void TestProcessData()
{
    var processor = new DataProcessor();
    var result = processor.Process(new[] { 1, 2, 3 });
    Assert.That(result, Is.EqualTo(new[] { 2, 4, 6 }));
}

// Implementation 1: Make it pass
public class DataProcessor
{
    public int[] Process(int[] data) => data.Select(x => x * 2).ToArray();
}

// Later: Realize I need configurability, rewrite test
[Test]
public void TestProcessDataWithFactor()
{
    var processor = new DataProcessor();
    var result = processor.Process(new[] { 1, 2, 3 }, factor: 3);
    Assert.That(result, Is.EqualTo(new[] { 3, 6, 9 }));
}

// Later: Realize I should use IEnumerable, rewrite test again
[Test]
public void TestProcessDataEnumerable()
{
    var processor = new DataProcessor();
    var data = GetLargeDataset(); // This should be lazy
    var result = processor.Process(data, factor: 3);
    Assert.That(result.Take(3), Is.EqualTo(new[] { 3, 6, 9 }));
}
```

Prima fai uno schizzo sciolto.

**Non inizi con i dettagli.**

```csharp
// Phase 1: Explore (no tests yet)
public int[] ProcessThing(int[] data)
{
    return data.Select(x => x * 2).ToArray();
}
// Try it: var result = ProcessThing(new[] { 1, 2, 3 });
// Hmm, what about configurability? What about lazy evaluation?

// Phase 2: Refine (still no tests)
public static class DataProcessorExtensions
{
    public static IEnumerable<int> Scale(
        this IEnumerable<int> source,
        int factor = 2)
    {
        return source.Select(x => x * factor);
    }
}
// Try it: var result = data.Scale(factor: 3).ToList();
// Much better API!

// Phase 3: Lock it down (NOW write tests, correctly)
[TestFixture]
public class DataProcessorTests
{
    [Test]
    public void Scale_DefaultFactor_DoublesValues()
    {
        var result = new[] { 1, 2, 3 }.Scale();
        Assert.That(result, Is.EqualTo(new[] { 2, 4, 6 }));
    }

    [Test]
    public void Scale_CustomFactor_ScalesCorrectly()
    {
        var result = new[] { 1, 2, 3 }.Scale(factor: 3);
        Assert.That(result, Is.EqualTo(new[] { 3, 6, 9 }));
    }

    [Test]
    public void Scale_LazyEvaluation_DoesNotEnumerateImmediately()
    {
        var enumerated = false;
        var data = GetTestData(() => enumerated = true);
        var scaled = data.Scale(factor: 2);

        Assert.That(enumerated, Is.False, "Should not enumerate yet");

        scaled.ToList();
        Assert.That(enumerated, Is.True, "Should enumerate on materialization");
    }

    [Test]
    public void Scale_EmptySequence_ReturnsEmpty()
    {
        var result = Enumerable.Empty<int>().Scale();
        Assert.That(result, Is.Empty);
    }
}
```

Come questo si adatta con Agile e XP (e dove si diverte)

### Cerchiamo di essere chiari su una cosa:

questo non è "test dello sviluppo successivo."

**Questo e'**

- "provare durante lo sviluppo, ma al momento giusto."*I tempi di*
- quando

**aggiungere test unitari è fondamentale.**

- Troppo presto e stai specificando l'ignoto.
- Troppo tardi e spedisci senza reti di sicurezza.

**Le pratiche XP che tengo**

- Extreme Programming ha pratiche brillanti vale la pena di seguire:
- Integrazione continua

**Ogni funzione passa attraverso IC prima della fusione**

- Il test automatico viene eseguito su ogni commit alla main*Nessun build rotto tollerato*Coppia programmazione / revisione del codice
- Il codice di fase 3 viene rivisto prima della condivisione

## I test fanno parte dell'artefatto rivisitabile

La raffinatezza collaborativa migliora il design**Design semplice**

La fase 2 è

- tutto su
- semplificazione
- Rimuovi ciò di cui non hai bisogno
- Rendere il più semplice possibile, non più semplice

Rifattorizzazione

Fase 2 è dedicato tempo di refactoring*Pulisci il codice*prima

### Bloccalo.

**I test proteggono il refactoring (nella fase 3+)**Dove diverge da rigido TDD

**TDD dice:**"Prima le prove.

Sempre.*Il fattore verde-rosso è l'unico modo."*

**Io dico:**"Prova quando sai cosa stai testando.

Explore-Refine-Lock è più naturale."

## La differenza fondamentale:

| TDD | Trifase |*| Test definisce l'interfaccia | Esplorazione definisce l'interfaccia |*

- |Ciclo rosso-verde-refattore |Progressione dell'esplorazione-rifinitura-blocco |
- | Prove scritte prima dell'implementazione | Prove scritte prima
- condivisione

| Prova prima di tutto | Prova al momento giusto per ogni cosa |

- | Microcicli (minuti) | Macrofasi (ore/giorni) |
- Il tempismo è critico
- Ecco l'intuizione cruciale:
- Non e' "tests last," ma "tests before sharing."
- Tempismo sbagliato (troppo presto):

*Tempismo corretto (fase 3):*

Stesso risultato qualitativo.*Meta' del churn.*Questo e' Agile.

### Agile dice:

"Rispondi al cambiamento dopo aver seguito un piano."**TDD può diventare la sua forma di piano-seguendo.**

Una volta che hai fatto dei test, sei psicologicamente impegnata in quel progetto.

- Il mio approccio abbraccia il cambiamento:
- Fase 1: Cambiare rapidamente, scoprire la soluzione giusta
- Fase 2: Cambiare deliberatamente, affinare verso l'eleganza
- Fase 3: Cambiare con attenzione, proteggere ciò che funziona

Questo e'*di più*

## agile che rigoroso TDD, perché rinvia l'impegno fino a quando non si dispone di informazioni.

Approcci di contrasto: un esempio di C#

### Approccio rigoroso TDD:

Hai notato il hurn?

Tre riscritture di test come il design si è evoluto.

1. **Approccio a tre fasi:**Una serie di test.
2. **Scritto una volta.**Correggi la prima volta.
3. **Perche' sapevo cosa stavo costruendo.**Il Manifesto Agile

Ricorda i valori:

### "Software di lavoro su documentazione completa"

La fase 1 arriva al software di lavoro

veloce

1. **La fase 3 mette alla prova la documentazione completa**"Rispondere al cambiamento dopo un piano"
2. **Fasi 1-2 abbracciano il cambiamento**Serrature di fase 3 nella progettazione finale
3. **"Individuali e interazioni su processi e strumenti"**Non lasciare che TDD dogma override buon giudizio

Collaborare quando aiuta (fase 2-3), esplorare da solo quando non lo fa (fase 1)

### "La collaborazione dei clienti sulla negoziazione di contratti"

La fase 2 si allinea con le specifiche

dopo

1. **capire il problema**Meglio consegnare quello di cui hanno bisogno che quello che hanno specificato
2. **Perché questo riduce l'inutile Churn**Il segreto sporco di TDD:
3. **la maggior parte dei test scritti prima dell'implementazione vengono riscritti o cancellati.**Perché?

Perché:

## Hai frainteso i requisiti

Non conoscevi ancora i casi piu' importanti.*Hai scoperto un design API migliore*Hai capito che la funzione non era necessaria per niente

Ogni test che scrivi in fase 1 è probabilmente uno sforzo sprecato.

### Meglio scrivere

uno

serie di test in fase 3, quando si sa cosa si sta costruendo, piuttosto che scrivere-riscrivere-riscrivere durante l'esplorazione.**Il TDD Promise vs. Reality**TDD promette:

```
"Write code that solves the specification.
Don't worry about perfection yet.
Just get it working."
```

"I test guidano il tuo design!

- Ti aiutano a scoprire buone API!"
- Realtà TDD:
- "Ho scritto dei test per un'API che pensavo avesse senso.
- Poi l'ho implementato e ho capito che l'API era imbarazzante.

Ora sto riscrivendo sia i test che il codice."**Quello non e' design.**E'

Distruggere.**Il mio approccio:**

Progettare attraverso l'implementazione, quindi bloccarlo con i test.

1. Il risultato finale è lo stesso codice ben collaudato e ben progettato.
2. Ma ci sono arrivata con meta' del churn.
3. Perché questo offre ancora il software disciplinare
4. Ecco cos'è questo approccio
5. non:
6. "Codifica del cowboy"

"Nessun test"*"Spedite e pregate"*Quando ho finito con la Fase 3, il mio codice ha:

**Copertura completa dei test**Casi di bordo trattati

### Implementazione pulita e leggibile

Pulisci il design delle API**Documentazione (tramite prove)**

Esattamente come TDD.

1. **La differenza è**
   
   - quando
   - quei test sono stati scritti.
   - La disciplina viene dal confine

2. **La regola è semplice:**
   
   ```
   - flake8 (style checking)
   - pylint (code quality)
   - mypy (type checking)
   - black (formatting)
   - radon (complexity analysis)
   ```

3. **Nessun codice lascia la fase 2 senza la fase 3.**Io non
   
   ```python
   for iteration in range(3):
       # Measure current performance
       metrics = measure_performance(code)
   
       # Generate improved version
       better_code = optimise(code, metrics)
   
       # Keep if better, discard if worse
       if better_code.score > code.score:
           code = better_code
   ```

Codice di commit non testato*Apri PR senza test*Unisce alla main senza passare CI

- Distribuisci senza report di copertura
- La disciplina non è nella scrittura test in anticipo.
- E' dentro
- non condividere codice senza test.
- Le metafore dell'artigianato

Non e' una nuova idea.*È così che il lavoro creativo ha sempre funzionato:*

### Sketch → Refine → Smalto

I pittori non iniziano con le pennellate finali.*Essi:*Sketch**la composizione (fase 1)**

Disegna*i livelli (fase 2)*Smalto

```python
# Test generation happens AFTER optimisation
def generate_unit_tests(specification, optimized_code):
    """Generate comprehensive tests for refined code.

    This happens in Phase 3, after we know:
    - What the code actually does
    - What edge cases exist
    - What the API surface looks like
    """
    return llm.generate(
        f"""Generate comprehensive unit tests for this code.

Specification: {specification}
Implementation: {optimized_code}

Include tests for:
- Happy path (from spec examples)
- Edge cases (discovered during optimisation)
- Error conditions (based on actual error handling)
- Performance bounds (based on measured metrics)
"""
    )
```

proteggere e presentare (fase 3)

- La vernice non viene prima.
- Ma non e' facoltativo.
- Bozza → Modifica → Pubblica
- Gli scrittori non modificano mentre si disegnano.

Essi:*Bozza*disordinato (fase 1)

1. Modifica**spietatamente (fase 2)**Pubblica
2. con fiducia (fase 3)**"Scrivi ubriaco, modifica sobrio" è un pessimo consiglio di vita, ma un ottimo consiglio di scrittura.**Clay → Modulo → Glaze
3. I vasai non smalto prima di modellare.**Essi:**Lancia
4. l'argilla (fase 1)**Taglio e raffinazione**il modulo (fase 2)**Glassa e fuoco**

**per la durata (fase 3)**Lo smalto è cruciale.

### Ma arriva l'ultima volta.

Come questo mappe per il DiSE Codegen Pipeline*Qui è dove questo diventa interessante: In realtà ho*implementata

**questa filosofia nel sistema DiSE (Directed Synthetic Evolution).**

- La conduttura di codegen incarna esplicitamente queste tre fasi:
- Fase 1 in DiSE: Lo stadio di esplorazione
- Quando chiedi a DiSE di risolvere un problema, non salta direttamente alla scrittura del codice perfetto e testato.
- Invece, il

**Generatore**

- (codellama o simili) ottiene un chiaro mandato:
- Il sistema genera codice esplorativo:
- Concentrati sul percorso felice
- Gestione degli errori minimi

**Nessuna ottimizzazione prematura**

- Abbastanza per testare l'approccio*Poi il*Esecutore
- Gestisce tutto.*Non con unità formali di prova [49] solo con gli input della specifica.*Se fallisce?
- Nessun problema.*E'*l'apprendimento.
- Il sistema ha un'escalation adattiva a 6 stadi:

### Prova con un modello veloce (bassa temperatura)

Riprovare con maggiore creatività (temperatura più alta)

```
User: "Calculate fibonacci numbers"

[Phase 1: Exploration - 3 attempts]
  Attempt 1: Works for small inputs, explodes on large ones (no safety limit)
  Attempt 2: Adds safety limit, but inefficient recursive approach
  Attempt 3: Switches to iterative DP (PASS)

[Phase 2: Optimization - 3 iterations]
  Iteration 1: Add type hints, improve naming (Score: 1.05)
  Iteration 2: Optimize memory usage with generator (Score: 1.10)
  Iteration 3: Add input validation (Score: 1.15)

[Phase 3: Testing and Storage]
  Generated 8 unit tests covering:
    - Basic cases (n=0, n=1, n=5, n=10)
    - Edge cases (n=negative, n=100, n=None)
    - Type validation

  All tests pass ✓

  Stored in RAG with quality score: 1.15
  Available for reuse: YES
```

Scalare verso un modello più potente

- Aggiungi la registrazione di debug per capire i guasti
- Dare pieno contesto al modello potente
- Utilizzare il modello "dio-livello" come ultima risorsa
- Questo e'

*esattamente*Fase 1.

### Il sistema sta esplorando lo spazio della soluzione, imparando ciò che funziona, fallendo velocemente e adattandosi.

In questa fase non sono state scritte prove.*Il codice è privato del processo di generazione.*

Fase 2 in DiSE: lo stadio di ottimizzazione**Una volta che il codice passa l'esecuzione di base, DiSE passa a**ottimizzazione.

1. **Questa è la fase di perfezionamento.**Il sistema:
2. **Ripulisce l'attuazione**Rimuove la registrazione del debug che è stata aggiunta durante i guasti
3. **Semplifica il codice eccessivamente complesso**Migliora la denominazione e la struttura
4. **Esegue analisi statiche**Ottimizza in modo iterativo

(3 iterazioni per impostazione predefinita)

Questo e'*esattamente*

## Fase 2.

Il codice è ancora privato (non ancora nel registro), ma lo stiamo lucidando:**Nomi migliori**

Digita suggerimenti*Struttura più pulita*

Abbassare la complessità

Migliorare le prestazioni**La forma non è più fluida.**

Sappiamo cosa stiamo costruendo.

1. **Ora ce la facciamo.**Bene.
2. **Fase 3 in DiSE: Lo stadio di prova e stoccaggio**Solo
3. **dopo**L'ottimizzazione di DiSE genera ed esegue

test formali dell'unità.

- Ecco la parte cruciale: i test vengono generati dal
- specifiche e attuazione perfezionate
- , non l'esplorazione iniziale.

Le prove riguardano:*Esempi di specifiche (correttezza)*Casi di bordo scoperti durante la fase 2

## Errore nel maneggiare che è stato aggiunto durante l'affinamento

Caratteristiche di prestazione misurate*Allora*Solo se le prove passano

, il codice è:

### Conservato nel

Memoria RAG

```python
# I know what sort() should do. Tests first? Sure!
def test_sort_empty_list():
    assert sort([]) == []

def test_sort_single_element():
    assert sort([5]) == [5]

def test_sort_multiple_elements():
    assert sort([3, 1, 2]) == [1, 2, 3]
```

### (con inserti)

Aggiunto al*Registro dei nodi*:

1. (come manufatto eseguibile)
2. Realizzato per
3. riutilizzo

nei flussi di lavoro futuri

### Rintracciato con

punteggi di qualità