# Hur jag bygger programvara: Få det att fungera, göra det snyggt, låsa ner det

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

<!-- category -- Software Development, Testing, TDD, Craftsmanship, Best Practices -->
**Varför jag skriver tester sist, och varför det inte är vad du tror att det betyder**

> **Kontroversiell användning:**Testdriven utveckling är en lysande praxis som löser fel problem för de flesta kreativa arbete.

## Här är vad som fungerar bättre.

De tre faserna av att bygga programvara (som faktiskt fungerar)

**Så här bygger jag mjukvara.**

Det är enkelt, det är effektivt, och det gör att TDD purister artigt får sina ögonbryn:

Få det att fungera.*Gör det vackert.*Lås den med testerna.

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

I den ordningen.*Alltid.*Inte för att jag är lat.

Inte för att jag inte värdesätter tester.

[TOC]

## Men för att

Det är så här kreativt arbete faktiskt händer

När du utforskar ett problemutrymme förstår du inte riktigt än.

- Inte för att jag är lat.
- Inte för att jag inte värdesätter tester.
- Men för att
- Det är så här kreativt arbete faktiskt händer

**När du utforskar ett problemutrymme förstår du inte riktigt än.**

Låt mig förklara.

### Fas 1: Få det att fungera (The Private Sketch)

Det här är den röriga delen.**Jag har ingen aning om vad jag gör.**

Jag försöker förstå:

Fungerar detta API verkligen som dokumenten hävdar?

Kan jag ens lösa detta problem med de verktyg jag har?

Vad betyder "korrekt" ens i detta sammanhang?*Är det två timmars problem eller två veckors problem?*Det här är en uppfinning.

**Det här är utforskning.**

Det här är 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
```

Och vet du vad som dödar jazz?**Någon som står över axeln och säger "skriv provet först".**Varför inga prövningar ännu?

För att*Formen är fortfarande flytande.*Tänk dig att du är en skulptör.

Du har ett marmorblock och en vag idé: "Jag vill skära en fågel."

### TDD säger: " Innan du rör vid den där marmorn, skriv ner exakt hur en fågel ser ut.

Definiera dess vingbredd.**Ange vinkeln på varje fjäder.**

Nu skära till dessa specifikationer."*Det är inte så fåglar blir snidade. (Eller programvara blir skriven, som det visar sig.)*Riktiga skulptörer

Skär ut blanketten först.**De tecknar.**

De gör maquettes.*De skär bort stora stenbitar för att hitta den allmänna formen.*Först senare förfinar de detaljerna.

Koden är densamma.

### I fas 1 skriver jag:

Denna kod är

Det är privat.

Det är ett samtal med mig själv.

Det är så jag listar ut vad "arbete" betyder.

## Att skriva tester för detta är värre än meningslöst – det är

aktivt skadligt.

**För varje gång jag inser att "åh vänta, hela denna strategi är fel," skulle jag behöva skriva om testerna också.**

Det är inte stelbent.

### Det är byråkrati.

**Friheten att misslyckas snabbt**

```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')
    ]
```

**Fas 1 handlar om**

```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);
}
```

inlärningshastighet.

### Jag måste prova fem olika inflygningar om en timme.

Jag måste upptäcka att det tredje partsbibliotek jag tänkte använda... inte är riktigt som det annonseras.*Jag måste inse att problemet jag löser inte är problemet.*bör*Vara lösa.*Testerna saktar ner det här.

Inte för att tester är långsamma, utan för att

- Förtida specifikation är död.
- Om jag skriver tester innan jag förstår problemet, Jag skriver tester för
- Det är fel.

Då är jag känslomässigt engagerad i fel sak.

### Då försvarar jag fel saker i kodgranskningen.

Bättre att misslyckas snabbt, privat, utan några tester att upprätthålla och inget ego att skydda.*Vad "arbete" innebär i fas 1*Det betyder: " Jag körde den.

**Jag gav det några ingångar.**

```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
)
```

**Det gav resultat som verkade rimliga.**

```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();
```

Jag är 60 % säker på att jag förstår problemet nu."

Så där ja.**Inga kantfall.**Ingen felhantering.

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

### Ingen elegans.

*Bara en spik.*Ett bevis på koncept.

En skiss.*Fas 2: Gör det vackert (Förfiningen)*

Nu förstår jag problemet.**Jag har något som fungerar, åtminstone för den lyckliga vägen.**

Nu kan jag börja bry mig om kvalitet.

- Fas 2 är där I:
- 1. Vad är det som händer?
- Städa upp röran

Exempel på Python:*C# Exempel:*Bättre namn.

Skriv anteckningar.*XML-dokumentation.*Genomförande av renare LINQ.

## Två.

Anpassa dig till specifikationerna

Nu när jag vet vad jag faktiskt bygger, går jag tillbaka till de ursprungliga kraven och se till att jag löser

**höger**

### problem, inte bara

a**Problemet.**

Ofta avslöjar detta luckor:

"Åh, de ville att detta skulle hantera negativa tal annorlunda."

1. **"Vänta, det finns en kant fall där värdet kan vara Ingen vs. 0."**"Specen säger 'dubbel' men jag tror att de menade 'skala med en konfigurerbar faktor.'"
2. **Jag fixar de här.**Ibland trycker jag tillbaka på spec: "Faktiskt bör vi göra X istället för att Y."
3. **3. Vad är det som händer?**Polera API-ytan
4. **Det är här jag tänker på**Anropsmottagarens

erfarenhet.**- Vad är det? - Python:**C#: Vad är det?

Bättre namngivning.

- Förståeliga standardvärden.
- Konfiguration där det är viktigt.
- Flytande API:er där så är lämpligt.
- Det här är
- Fartyg.

### Det är här bra programvara kommer ifrån.

Varför finns det fortfarande inga prövningar?

```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)
```

**Jag sköter det hela tiden.**

Jag har en REPL öppen.

- Jag försöker med olika ingångar.
- Jag tränar alla vägar.
- Men det är jag inte.
- Skriva ner experimenten som formella tester än.

### Varför?

För att

```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]
```

Jag upptäcker fortfarande vad som är värt att testa.

I fas 1 visste jag inte ens om den här funktionen skulle existera.**I fas 2 upptäcker jag:**"Åh, skalfaktorn kan inte vara negativ.

### Det är en bekräftelse."

"Om listan är tom, bör vi återvända tomma, inte Inga."**"Vi måste hantera icke-numeriska värden graciöst."**

Dessa insikter

framträder från refaktoring.

De är inte uppenbara i förskott.

1. **Om jag hade skrivit prov i fas 1 hade jag skrivit om dem nu.**Om jag skriver dem
2. **efter**Jag har förfinat genomförandet, de kommer att ha rätt första gången.
3. **Fas 3: Lås den med test (Delningsfasen)**Okej, nu är det på riktigt.

Koden är ren.*API:et är vettigt.*Jag har tagit hand om kanterna.

## Jag är säker på vad jag har byggt.

Nu skriver jag prov.

Massor av tester.

Så nära-full täckning-som-möjliga tester.**Varför nu?**

För att

Tester är en delningsmekanism.*De är inte till mig längre.*

Jag förstår redan denna kod intimt.

- Jag har levt i det i timmar eller dagar.
- Testerna är avsedda för:
- Framtida jag
- (som kommer att glömma allt på tre månader)*Mina lagkamrater*(som måste lita på denna kod fungerar)

CI- pipelinen

**(som måste förhindra regression)**

Framtida utvecklare

## (som behöver för att säkert refaktor detta)

Tester är**presentationsskikt**

för mitt genomförande.**De innehåller följande dokument:**

Vad denna kod gör*Vilka indata som är giltiga*Vilka resultat att förvänta sig

### Vilka kantfall jag har tänkt på

Vilka antaganden jag gör

**Fullständig täckning, inga kompromisser**

- I fas 3 går jag hårt på att testa:
- Det här är säkerhetsnätet.
- Nu kan mina lagkamrater:

**Ändra denna funktion med tillförsikt**

- Förstå kanterna fall
- Fånga regressionerna omedelbart
- Refaktor utan rädsla

**Tester som dokumentation**

- Bra tester är bättre dokumentation än kommentarer:*Tester ljuger inte.*De kan inte glida.
- Om beteendet ändras bryts testet.
- Det är

**körbar dokumentation.**

- Det är det som gör testerna värdefulla.
- Delningsgränserna*Här är den avgörande punkten:*Fas 3 händer innan någon annan rör koden.
- Jag delar inte kod utan tester.

### Någonsin.

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

**Men jag skriver inte heller tester innan koden är klar att delas.**Faserna är följande:

**Privat utforskning**(bara jag, inga tester)

Privat förfining

(bara jag, fortfarande inga tester)
|-----|-------------|
Offentligt deltagande
(test, CI, kodgranskning, hela nio varvet)
Detta skyddar både min kreativitet*och* |
Mina lagkamraters mentala hälsa.
Varför detta skyddar kreativiteten

### TDD förespråkare säger "test ger dig självförtroende att refaktor."

Det är sant!**Men bara om du redan vet vad du bygger.**

**När jag är i fas 1 behöver jag inte självförtroende för att refaktor.**

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

**Jag behöver tillstånd att kasta bort allt.**

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

Tester skapar psykologiska skulder.

### När jag skrivit dem vill jag inte radera dem.

Även om de testar fel sak.**Genom att skjuta upp testerna till fas 3, behåller jag fas 1 och 2**

Psykologiskt billigt.

Jag kan:

- Prova vilda idéer
- Kasta bort hela tillvägagångssätt
- Radikalt ändra designen

Upptäck problemet jag är*faktiskt*lösning

### Utan skuldkänslorna av "men jag skrev alla dessa tester..."

**Det är så kreativitet fungerar.**

```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 }));
}
```

Du ritar löst först.

**Du börjar inte med detaljerna.**

```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);
    }
}
```

Hur detta passar med Agile och XP (Och där det avviker)

### Låt oss vara tydliga med en sak:

Detta är inte "test senare utveckling".

**Det här är**

- "prova medan du utvecklas, men i rätt tid."*Tidpunkten för*
- när

**Att lägga till enhetstester är kritiskt.**

- För tidigt och du anger det okända.
- För sent och du fraktar utan skyddsnät.

**De XP - metoder jag håller**

- Extrem programmering har briljanta metoder värda att följa:
- Kontinuerlig integration

**Varje funktion går igenom CI innan sammanslagning**

- Automatiserade test körs på varje åtagande till huvud*Inga trasiga byggnader tolereras*Parprogrammering / översyn av kod
- Fas 3-kod granskas innan delning

## Tester är en del av den recenserbara artefakten

Samverkansförfining förbättrar designen**Enkel design**

Fas 2 är

- Allt om
- Förenkling
- Ta bort det du inte behöver
- Gör det så enkelt som möjligt, inte enklare

Tillverkning

Fas 2 är dedikerad refaktortid*Rengör koden*före

### Låsa ner den

**Tester skyddar refaktorn (i fas 3+)**Där jag avviker från strikt TDD

**TDD säger:**"Test först.

Alltid.*Red-Green-Refaktor är det enda sättet."*

**Jag säger:**"Testar när man vet vad man testar.

Explore-Refine-Lock är mer naturligt."

## Den viktigaste skillnaden:

TDD  på trefas*till Test definierar gränssnittet  på Exploration definierar gränssnittet  på*

- Red-Green-Refaktor cykel  på Explore-Refine-Lock progression
- till Tester skrivna före genomförande  på test skrivna innan
- delning

Pröva först för allt och testa vid rätt tidpunkt för varje sak

- på mikrocyklar (minuter)  på makrofaser (timmar/dagar)
- Tidpunkten är kritisk
- Här är den avgörande insikten:
- Det är inte "test sist". Det är "test innan du delar med dig".
- Fel timing (för tidigt):

*Rätt tidpunkt (fas 3):*

Samma kvalitetsresultat.*Hälften av churn.*Detta är agilt

### Agile säger:

"Skjut om att ändra sig efter en plan."**TDD kan bli sin egen form av planuppföljning.**

När du har skrivit prov, är du psykologiskt engagerad i den designen.

- Mitt tillvägagångssätt omfattar förändring:
- Fas 1: Ändra snabbt, upptäck rätt lösning
- Fas 2: Ändra medvetet, förfina mot elegans
- Fas 3: Ändra noga, skydda det som fungerar

Det här är*fler*

## smidig än strikt TDD, eftersom det skjuter upp engagemang tills du har information.

Kontrasterande metoder: Ett exempel på C#

### Strikt TDD-metod:

Lägger du märke till churnen?

Tre test omskriver som designen utvecklats.

1. **Trefasmetoden:**En uppsättning tester.
2. **Skrivet en gång.**Rätta första gången.
3. **För att jag visste vad jag byggde.**Anslutningen till agilt manifest

Kom ihåg värdena:

### "Arbeta programvara över omfattande dokumentation"

Fas 1 kommer till arbetsprogramvaran

snabb

1. **Fas 3 gör tester till den omfattande dokumentationen**"Skjut på att ändra sig efter en plan"
2. **Faser 1-2 omfamna förändring**Fas 3 lås i den slutliga konstruktionen
3. **"Individuella och interaktioner över processer och verktyg"**Låt inte TDD:s dogm överskugga gott omdöme

Samarbeta när det hjälper (fas 2-3), utforska ensam när det inte gör det (fas 1)

### "Kundsamarbete över avtalsförhandlingar"

Fas 2 ligger i linje med specifikationerna

efter

1. **förstå problemet**Bättre att leverera vad de behöver än vad de angav
2. **Varför detta minskar den oanvändbara Churn**TDD: s smutsiga hemlighet:
3. **De flesta tester som skrivs innan genomförandet skrivs om eller raderas.**Varför?

Därför att:

## Du missförstod kraven.

Du kände inte till de bästa fallen än.*Du upptäckte en bättre API-design*Du insåg att funktionen inte behövdes alls

Varje test du skriver i fas 1 är förmodligen bortkastad ansträngning.

### Bättre att skriva

en

uppsättning tester i fas 3, när du faktiskt vet vad du bygger, än att skriva-skriva-skriva-skriva om under utforskning.**TDD-löftet mot verkligheten**TDD lovar:

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

"Tests kör din design!

- De hjälper dig att upptäcka bra API:er!"
- TDD verklighet:
- "Jag skrev tester för ett API jag tyckte var vettigt.
- Sedan implementerade jag det och insåg att API:et var besvärligt.

Nu skriver jag om både testerna och koden."**Det är inte design.**Det är

Knuffas.**Mitt tillvägagångssätt:**

Designa genom implementation, sedan låsa ner den med tester.

1. Slutresultatet är detsamma – väl beprövad, väl utformad kod.
2. Men jag kom dit med hälften av churn.
3. Varför detta fortfarande levererar disciplinerad programvara
4. Så här går det till:
5. inte:
6. "Kowboykodning"

"Inga tester"*"Skicka och be"*När jag är klar med fas 3 har min kod:

**Omfattande testtäckning**Handläggning av kantfall

### Ett rent och läsbart genomförande

Rensa API-design**Dokumentation (via tester)**

Exakt samma som TDD.

1. **Skillnaden är**
   
   - när
   - Dessa tester skrevs.
   - Disciplinen kommer från gränsen

2. **Regeln är enkel:**
   
   ```
   - flake8 (style checking)
   - pylint (code quality)
   - mypy (type checking)
   - black (formatting)
   - radon (complexity analysis)
   ```

3. **Ingen kod lämnar fas 2 utan fas 3.**Jag vet inte:
   
   ```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
   ```

Kommit oprövad kod*Öppna PR utan tester*Sammanfoga till huvud utan att CI passerar

- Utplacering utan täckningsrapporter
- Disciplinen är inte i skrivande tester tidigt.
- Den är inne.
- inte dela kod utan tester.
- Konsthantverksmetaforerna

Det här är ingen ny idé.*Det är så kreativt arbete alltid har fungerat:*

### Sketch → Raffinera → Varnish

Målare börjar inte med de sista penseldragen.*De har följande egenskaper:*Skiss**Sammansättningen (fas 1)**

Färg*skikten (fas 2)*Varniska

```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)
"""
    )
```

att skydda och presentera (fas 3)

- Lacken kommer inte först.
- Men det är inte frivilligt.
- Utkast → Redigera → Publicera
- Författare redigerar inte som de skriver.

De har följande egenskaper:*Utkast*stökigt (fas 1)

1. Redigera**hänsynslöst (fas 2)**Publicera
2. med tillförsikt (fas 3)**"Skriv full, redigera nykter" är hemska livsråd men bra skriftliga råd.**Lera → Form → Glaze
3. Potters glaserar inte innan de formar sig.**De har följande egenskaper:**Kasta
4. leran (fas 1)**Trim och raffinering**Formuläret (fas 2)**Glasyr och eld**

**för hållbarhet (fas 3)**Glasyren är avgörande.

### Men det kommer sist.

Hur detta kartor till DiSE Codegen Pipeline*Här blir det intressant: Jag har faktiskt*Genomförande

**denna filosofi i systemet DiSE (Dired Synthetic Evolution).**

- Codegen pipeline förkroppsligar uttryckligen dessa tre faser:
- Fas 1 i diSE: Explorationssteget
- När du ber DiSE att lösa ett problem, det inte hoppa direkt till skriva perfekt, testad kod.
- I stället,

**Generator**

- (codelama eller liknande) får ett tydligt mandat:
- Systemet genererar explorativ kod:
- Fokuserad på den lyckliga vägen
- Minimal felhantering

**Ingen för tidig optimering**

- Bara tillräckligt för att testa tillvägagångssättet*Och sen*Utförare
- Kör den.*Inte med formella enhetsprovningar – bara med indata från specifikationen.*Om det misslyckas?
- Ingen orsak.*Det är*Att lära sig.
- Systemet har en 6-stegs adaptiv upptrappning:

### Prova med en snabb modell (låg temperatur)

Försök igen med högre kreativitet (högre temperatur)

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

Rulla vidare till en kraftfullare modell

- Lägg till felsökningsloggning för att förstå fel
- Ge den kraftfulla modellen ett fullständigt sammanhang
- Använd "gud-nivå" modellen som en sista utväg
- Det här är

*exakt*Fas 1 .

### Systemet utforskar lösningsutrymmet, lär sig vad som fungerar, misslyckas snabbt och anpassar sig.

Inga tester skrivs under denna fas.*Koden är privat till generationsprocessen.*

Fas 2 i diSE: Optimeringsstadiet**När koden passerar grundläggande utförande, DiSE flyttar till**Optimering.

1. **Det här är förfiningsfasen.**Systemet:
2. **Rensar upp genomförandet**Tar bort felsökningsloggning som lades till vid fel
3. **Förenklar alltför komplex kod**Förbättrar namngivning och struktur
4. **Kör statisk analys**Iterativt optimerar

(3 iterationer som standard)

Det här är*exakt*

## Fas två.

Koden är fortfarande privat (inte i registret ännu), men vi polerar den:**Bättre namn**

Skriv tips*Renare struktur*

Lägre komplexitet

Bättre resultat**Formen är inte längre flytande.**

Vi vet vad vi bygger.

1. **Nu klarar vi det.**Bra.
2. **Fas 3 i diSE: Test- och lagringsstadiet**Endast
3. **efter**optimering genererar och kör DiSE

formella enhetsprovningar.

- Här är den avgörande delen: testerna genereras från
- förfinad specifikation och genomförande
- , inte den första utforskningen.

Testerna omfattar följande:*Exempel på specificering (korrekthet)*Kantfall upptäckta under fas 2

## Felhantering som tillkom under förfining

Prestandaegenskaper som mättes*Och sen*Endast om proven godkänns

, koden är:

### Förvaras i

RAG-minne

```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]
```

### (med inbäddningar)

Tillagd till*Nodregister*:

1. (som en körbar artefakt)
2. Görs tillgänglig för
3. Återanvändning

i framtida arbetsflöden

### Spårad med

kvalitetspoäng