This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Hur jag bygger mjukvara
Wednesday, 19 November 2025
Varför skriver jag test i sista gången och varför det inte är vad du tror att det betyder
Kontroversella antaganden: Testing-Driven Development är en lysande praxis som löser det felaktiga problemet för de flesta kreativa projekten.
De tre stadierna i byggandet av mjukvara ( som faktiskt fungerar)
Det är så jag bygger mjukvaran.
Få den att fungera . Få den till att vara vacker. Sluka ner den med tester
I den ordningen
Inte för att jag är lata. det här är hur kreativt arbete faktiskt sker när du utforskar ett problem som du inte förstår ännu
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
Inte för att jag är lata. det här är hur kreativt arbete faktiskt sker när du utforskar ett problem som du inte förstår ännu
Låt mig förklara
Fasen 1: Få det att fungera (Privatskivan | )
Det här är den röriga delen, där jag inte har någon aning om vad jag gör.
I'Jag försöker förstå
- Fungerar denna API faktiskt på samma sätt som dokumenten säger
- Kan jag till och med lösa problemet med de verktyg jag har?
- Vad betyder "korrigt
- Är det ett två timmars problem eller ett två veckors problem?
Det här är uppfinning.
Och du vet vad som dödar jazz.
Varför inga tester än?
För att formen är fortfarande flytande.
Föreställ dig att du är en skulptör. Du har ett block av marmor och en vag idé.
TDD säger: "" Before you touch that marble, write down exactly what a bird looks like. "" "" Define its wingspan, ., Specify the angle of each feather, ., Now carve to those specifications."
Att det inte är så att fågel är graverade, utan att mjukvaran blir skriven, som det visar sig.
Verkliga skulptörer rough out the form first. De skissar.
Kod är densamma.
I fasen 1, I' m skrivande :
# 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
Den här koden är privat. Det är ett samtal med mig själv. Det är hur jag listar ut vad det betyder att arbeta
Att skriva tester för detta är värre än värdelöst. kraftigt skadlig. För varje gång jag inser """, "" Åh, vänta! "" ",, hela den här metoden är fel!"
Att "'" inte är rigoröst , ".", och att МSK 2 är byråkratiskt ,
friheten att misslyckas snabbt
Fasen 1 är ungefär lärandehastighet.
Jag måste pröva fem olika sätt på en timme. borde att lösa
Tester saktar ner det här.. Inte för att tester är långsamma, för tidigt specifikation är död.
Om jag skriver tester innan jag förstår problemet fel sak. Sedan investerar jag känslomässigt i det felaktiga. Sedan bekämpar jag det felliga med kodbevakning.
Bättre att misslyckas snabbt, i privatt, utan att göra några test för att hålla kvar och utan ego för att skydda
Vad betyder "Arbeting" i fas 1
Det betyder: :, " Jag körde den. ., jag gav den några intryck.., den gav ett rimligt uttryck.
Det är det.
Inga randkoster. Inga felbehandlingar . Ingen elegans
Bara en pisk. Ett bevis på konceptet. En skiss .
Fasen 2: Gör det vackert | ( | Utfinning |)
Okej, så 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
Fasen 2 är där
1. Skolla upp meddelandet
Python exempel:
# 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')
]
C# exempel :
// 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);
}
Bättre namn. Typbeteckningar . XML-dokumentationen. En renare LINQ-implementering
2. Lika ihop med Specen
Nu när jag vet vad jag faktiskt bygger, går jag tillbaka till de ursprungliga kraven och ser till att jag löser högra problem, inte bara a problem.
Det visar ofta luckor
- De ville att detta skulle hantera negativa siffror annorlunda.
- " Vänta, , det finns ' som är ett marginalfall där värdet kan vara Ingen mot
- Specen säger "" ', dubbelt, ' "", men jag tror att det betydde "', skala med en konfigurerad faktor."
Jag fixar dessa. Ibland trycker jag tillbaka på specifikationen.
3. Polisera API: s yta
Det är här jag tänker på ringare's erfarenhet.
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
)
C#:
// 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();
Bättre namngening. Uppmärksama standarder . Konfiguration där det spelar roll
Det här är craft. Det är här som bra mjukvara kommer ifrån
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
Varför finns det fortfarande inga tester?
Oh, JagM SK1 Jag kör den hela tiden . Jag har en REPL öppen.
Men det är inte så. skriva ner dessa experiment som formella tester än
Varför? Eftersom Jag upptäcker fortfarande vad som är värt att testa.
I Fasen 1, visste jag inte ' om denna funktion skulle existera.
- ", oh, ,, skalfaktorn kan inte vara negativ.
- "Om listan är tomt , så borde vi ge tillbaka tomt
- " Vi måste hantera icke-
Dessa insikter dyker upp från att återformera De är inte uppenbara från början.
Om jag skrev tester i fas 1,, skulle jag skriva om dem nu. efter I' har förfinat implementeringen , de M SK2 kommer att vara korrekt den första gången
Fasen 3: låsa ner den med tester (Springfasen | )
Ok, nu är det ', det riktiga
Koden är ren.
Nu skriver jag tester.
Varför nu?
För att tester är en samarbetsmekanism.
De är inte längre för mig. Jag förstår redan den här koden på ett nära sätt. Jag har levt i den i timmar eller dagar.
Test är för:
- Framtiden för mig (som kommer glömma allt inom tre månader )
- Mina lagkamrater (som behöver lita på att den här koden fungerar
- CI-tunneln ( som behöver förhindra regressioner )
- Framtidens underhållare (som behöver bygga om det här på ett säkert sätt
Tester är presentationslayer för min realisation.
De dokumenterar:
- Vad den här koden gör
- Vilka ingångar är korrekta
- Vilka resultat ska man förvänta sig
- Vilka marginalfall har jag tänkt på
- Vilka antaganden gör jag?
Full Coverage, Inga kompromisser
I fasen 3, går jag hårt på att testa
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)
Det här är säkerhetsnätet
Nu kan mina lagkamrater
- Modifiera denna funktion självsäkrat
- Understand the edge cases
- Att fånga återfall omedelbart
- Refaktor utan rädsla
Test som dokumentation
Bra tester är bättre dokumentation än kommentarer:
# 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]
Testar inte ljuger. De kan drifta. Om beteendet ändras.
Det's utförbar dokumentation. Det är det som gör tester värdefulla
Det delade gränsen
Här är det kritiska: Fasen 3 händer innan någon annan rör vid koden .
Jag delar inte koden utan att göra tester.
Men jag skriver inte heller tester innan koden är redo att dela.
De stadierna är:
- Privatexploration ( bara mig , inga tester
- Privat raffinering ( bara mig , fortfarande inga tester
- Öffentligt dela (tester
Det skyddar både min kreativitet och mina lagkamrater
Varför detta skyddar kreativiteten
TDD-aktivister säger: "" Testar ger dig självförtroende till att rekonstruera "".
Verkligen, men bara om du redan vet vad du bygger.
När I'm är i fas 1, behöver jag inte confidence för att göra om Jag behöver tillåtelse att kasta allt bort
Test skapar psykologisk skuld.
Genom att skjuta upp tester till Fasen 3, så håller jag Fasen psykologiskt billigt.
Jag kan
- Försök vilda idéer
- Släng bort hela angrepp
- ändra designen på ett radikalt sätt
- Ta reda på problemet I'm faktiskt att lösa
Allt utan skuldbekännelsen för """, men jag skrev alla dessa tester.
Det är så kreativitet fungerar.
Du skissar loosen först. Du gör det inte
Hur det passar med Agile och XP ( Och vart det skiljer sig
Låt oss vara tydliga med något. det här är inte "test senare utveckling
Det här är "test medan man håller på med utvecklingen , men vid rätt tidpunkt
Timing av när att lägga till enhetens tester är kritiskt.
XP-metoderna jag håller på med
Extreme Programming har fantastiska metoder värda att följa:
Kontinuös integrering
- Varje egenskap går igenom CI innan de går samman
- Automatiserad test drivs på varje kommando till huvud
- Inga brutna byggnader toleras
Par programmering / Kodexbevakning
- Fasen 3 kod blir överprüft innan du delar den
- Tester är en del av den överprüfbara artefakten
- Kollaborativ raffinering förbättrar designen
Enkel design
- Fasen 2 är allt om förenkling
- Ta bort vad du inte behöver
- Gör det så enkelt som möjligt, inte enklare
Refactoring
- Fasen 2 är en dedikerad reafaktoreringstid
- Skoda koden före att låsa ner den
- Test skyddar omformeringen ( i fas 3+)
Var jag skiljer mig från strikt TDD
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
TDD säger: : " Testar först . Särskilt . Röd M SK3 Grönt MSC4 Refaktorn är det enda sättet
Jag säger:". "Tester när du vet vad du testar 'testar du. UtforskaM SK3Rexifiera
Den viktiga skillnaden:
| TDD | ||||
|---|---|---|---|---|
| Test definierar gränssnittet ♫ | ♫ Exploration definierargränssnittet | |||
| Röd-GrönM SK2Refaktorcycling | Utforska | |||
| Test skrivna innan implementering | Test skriven innan att dela | |||
| Testa först för allting ♫ | ♫ Testa i rätt tid för varje sak ♫ | |||
| Mikro, -cykler, minuter, M SK3, | Makro, - | stadier, |
Timeringen är kritisk
Här är den avgörande insikten. Det' är inte M SK1testar sist." Det 's "tester innan du delar ut
Verklig timing (för tidigt
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
Rätt tidning (Phasen 3):
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
Samma kvalitet i resultat
Detta är Agile
Agile säger:". " Svara på förändring efter en plan
TDD kan bli sin egen form av plan.
Min metod omfamnar förändring
- Fas 1: ändra snabbt , hitta rätt lösning
- Fas 2: ändrad avsiktligt , raffineras mot elegans
- Fas 3: ändra försiktigt , skydda vad som fungerar
Det här är mer agiler än strikt TDD, eftersom det skjuter upp engagemang tills du har information.
Motsägelsefulla tillvägagångssätt : A C# exempel
Strak TDD-metod:
// 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 }));
}
Notera gungen? Tre omskrivna tester medan designen utvecklades
Tre-Phas Approach:
// 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);
}
}
Ett testsystem . En gång skrivet. Korrigera första gången. Eftersom jag visste vad jag byggde
Agile Manifesto Connection
Kom ihåg värdena:
"Working software over comprehensive documentation
- Fasen 1 får igång mjukvara fort
- Fasen 3 gör tester av den kompletta dokumentationen
"Atbild till förändring efter en plan
- Faser 1-2 omfamnar förändring
- Fasen 3 låser i den slutgiltiga designen
"Individueller och interaktioner över processer och verktyg"
- Låt inte TDDs dogma överrösta gott omdöme
- Samarbeta när det hjälper
"Kunssamarbete över kontraktförhandlingar "
- Fasen 2 följer specifikationen efter att förstå problemet
- Det är bättre att leverera vad de behöver än vad de specifikerade
Varför reducerar detta värdelösa knapr
TDD's smutsiga hemlighet de flesta tester som skrevs innan implementeringen är omskrivna eller lösda.
Varför?
- Du missförstod kraven
- Du visste inte edge cases än
- Du upptäckte en bättre API-design
- Du insåg att funktionen inte alls behövdes
Varje test du skriver i Fasen 1 är antagligen slösaktigt
Bättre att skriva ett uppsättning test i Fasen 3, när du faktiskt vet vad du bygger '
TDDs löfte mot verkligheten
TDD lovar "Prätestar driver din design ! De hjälper dig att upptäcka bra APIs
TDD verkligheten: " Jag skrev tester för en API som jag tyckte var vettigt, . Sedan implementerade jag den och insåg att APIn var obekväm, ♫ . ♫ Nu skriver jag om både testerna och koden ♫
Att "'" inte är design. thrashing.
Mitt tillvägagångssätt: Design genom att implementera
Slutresultatet är samma.
Varför detta fortfarande tillhandahåller disciplinerad mjukvara
Här är vad den här ansatsen är inte:
- "Cowboykodering
- " Inga tester
- "Såge och ber
Vid den tid jag ' gör med Fasen 3, har min kod
- Omgripande testbeläggning
- Edge fall hanterade
- Clean, läsbar implementering
- Klara API-design
- Dokumentation (med hjälp av tester)
Precis samma sak som TDD.
Skillnaden är när dessa tester skrevs
Disciplinen kommer från gränserna
Reglerna är enkla: Ingen kod lämnar Fasen 2 utan Fasen
Jag tror inte
- Stuur in otestad kod
- Att öppna PR utan att göra tester
- Merge till huvuden utan att skicka CI
- Deploy utan rapporter om skydd
Disiplinen är: "'t i skrivandetests tidigt. att inte dela koden utan att göra tester.
Craft-metaforerna
Det här är ingen ny idé, det är hur kreativt arbete alltid har fungerat.
Sketch → Refinera → Varnish
Malare kan inte börja med de slutgiltiga pensels strokerna.
De:
- Sketch sammansättning (Phasen 1)
- Färg lagerna (Phasen 2)
- Varnish för att skydda och presentera (Phasen 3)
Varnishmen kommer inte först, men det är optionellt.
ritning → redigera → publicera
Redare kan inte redigera när de skriver.
De:
- ritning otäckt (Phasen 1)
- Reda grymt (Phasen 2)
- publicera med självförtroende (
"skriv drunken, , redigera nykter, " är en hemsk livsrådet men bra när det gäller att skriva.
Plast → Form → Glazier
Potterer använder inte glasier innan de formar sig.
De:
- Slänga lera (Phasen 1)
- Förbrylla och raffinera formen (Phasen 2)
- Glazier och eld för hållbarhet (Phasen 3)
Glazjan är avgörande. Men den kommer sista.
Hur det här kartläggs till DiSE-kodgen-pingelin
Här är "'", där det blir intressant. implementerad denna filosofi i DiSE: s system
Koderingskedjan förkroppsligar explicit dessa tre faser:
Fas 1 i DiSE: Explorationsfasen
När du frågar DiSE om att lösa ett problem
Istället Generator (codellama eller liknande ) får ett tydligt mandat
"Write code that solves the specification.
Don't worry about perfection yet.
Just get it working."
Systemet genererar utforskningskod:
- Fokuserad på den lyckliga vägen
- Minimalt felbehandling
- Ingen för tidig optimering
- Bara tillräckligt för att testa angreppet
Sedan Operatör kör den. Inte med formella enhetens tester — bara med intrycken från specifikationen
Om det misslyckas? Inga problem lärande.
Systemet har en 6- stegad adaptiv upphöjning
- Försök det med en snabb modell ( låg temperatur
- Försök igen med större kreativitet ( högre temperaturM SK1
- Spring till en mer kraftfull modell
- Lägg till debug-loggning för att förstå fel
- Ge hela sammanhanget till den kraftfulla modellen
- Använd "god-levelM SK2 modellen som sista tillvägagångssättet
Det här är precis Fasen 1. Systemet utforskar lösningsrummet , lär sig vad som fungerar M SK2 misslyckas snabbt , och anpassar sig
Inga tester skrivs under den här fasen. Koden är privat för genereeringsprocessen.
Fas 2 i DiSE: Optimeringsfasen
När koden passerar grundoperationen, flyttar DiSE till optimering.
Detta är raffineringsfasen
Tvättar upp implementeringen
- Ta bort debug-loggen som lagts till under misslyckanden
- Förenklar för komplicerad kod
- Försämrar namn och struktur
kör statisk analys
- flake8 (style checking) - pylint (code quality) - mypy (type checking) - black (formatting) - radon (complexity analysis)Optimerar om och om igen (3 repetitioner standardmässigt
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
Det här är precis Fasen 2. Koden är fortfarande privat ♫ ( ♫ är inte i registret än ♫ ), ♫ men vi ♫' ♫ polerar den ♫ : ♫
- Bättre namn
- Typa ledtrådar
- renare struktur
- lägre komplexitet
- Bättre resultat
Formen är inte längre flytande. bra.
Fas 3 i DiSE: Test- och lagerfasen
Bara efter optimering gör DiSE generera och köra formella unittestar.
Här ' är den avgörande delen: skapas testerna från raffinerad specifikation och implementation, inte den ursprungliga utforskningen
# 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)
"""
)
Testen täcker::
- Spesifikationsexempler ( korrekthet)
- Randfall upptäckta under fas 2
- Ett handlingsfel som lagts till under förfinning
- Förmågor som mätts
Sedan, endast om tester går, koden är:
- Bevarad i RAG minne (med inbäddar
- Läggs till noderregistret ( som en utförbar artefakt
- Made available for återanvända i framtida arbetsflöden
- spårad med kvalitetscore och prestationsmått
Detta är delafasen. Koden är nu offentlig. ( till systemet ). Den har komplexa tester M SK2 Den ' är låst ned
Varför det fungerar i en kodskapande system
Den tre-MSK-phasen-metoden är nödvändigt för AI-driven kod generering eftersom
Fas 1: Modeller förstår inte problemet från början
- De behöver utforska lösningsområdet
- Börjande försök misslyckas ofta på intressanta sätt.
- Misslyckanden ger information för bättre försök
- Framtidstest skulle tvinga framdröjda specifikationer
Fas 2: Modell optimerar bättre med feedback
- Statisk analys visar på verkliga problem
- Performance metrics guida för förbättringar
- Kompleksitetstest visar på möjligheter att förenkla
- Det är här som kvalitet uppstår
Fas 3: Testdokumenterar vad som lärts
- Test fångar slutgiltiga förståelse
- De reflekterar verkliga Kantfall
- De koder raffinerad API-design
- De korrigerar första gången
Evidens: ":" Det fungerar faktiskt
Här är ett verkligt exempel från DiSE-systemet
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
Den slutgiltiga koden är:
- Bra -testat (8 tester, alla passerar
- Bra-optimiserad (15% bättre än den ursprungliga versionen
- Bra-dokumenterad (med hjälp av tester och typstipplar
- Klara att dela ( i registret)
Precis som TDD lovar Bara genom en mer naturlig väg.
Systemet optimerar sig själv
Här är "'", där det blir riktigt intressant. DiSE använder den här tre stadia-metoden till sig själv.
Den Rekursiv systemoptimisator har 4 nivåer
- Pozition 0: Optimera ko-artefakter ( få dem att fungera , göra dem vackra
- Pozition 1: Optimera arbetsflöden som använder dessa artefakter.
- Pozition 2: Optimera verktygen och urvalslogiken ( du gissade det )
- Pozition 3: Optimera optimeringen själv (meta!)
På varje nivå: utforska M SK1 raffinera → testa
Det här är mantran hela vägen ner.
Den verkliga anledningen till att det fungerar
Här är den obehagliga sanningen. De flesta kod är skriven av människor som inte riktigt förstår problemet ännu.
Det är inte ett misslyckande verkligheten.
Benötningarna är tvetydiga . Spektionerna är ofullständiga. Trede- Parties APIs är dåligt dokumenteradeM SK3 Randfall dyker upp från ingenstans
Du kan inte designa den perfekta API: n från början eftersom du har inte tillräckligt med information
De tre faserna erkänner detta
- Fas 1: Lär dig vad du inte vet
- Fas 2: tillämpa vad du lärt dig
- Fas 3: Protect vad du byggt
Genom att separera utforskning från specifikationen
- Utforska fritt (utan att testa skuldenM SK1
- Definiera självförtroendet (med kunskap om vad som är viktigtM SK1
- dela på säkert (med omfattande tester)
Detta gäller för människor som skriver kod. också sant för LLM som genererar kod. Och för system som optimerar sig själva.
När TDD faktiskt verkar vettigt
I'm inte mot -TDDför tidigt TDD.
TDD fungerar bra när:
1. Problemet är bra
Om jag implementerar en känd algoritm
# 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]
2. Du ' löser en bug
Om jag har en regression precis rätt:
- skriva en test som återskapar buggen (red)
- Fixera koden (green)
- Refaktor om nödvändigt (refactor)
Perfekt.
3. Du ' gör om den existerande koden
Om jag redan har en implementering och vill ändra dess struktur (niet beteendeM SK1 tester är nödvändiga före Jag börjar.
Men att "'" är inte Fasen "1.", That 's ' , Fasen 4: Maintenance , .
Den ärliga sanningen
Det här är hur jag faktiskt jobbar. mest utvecklare faktiskt arbetar, till och med de som hävdar att göra strikta TDD
För kreativiteten är rörig.
Du kan inte specifikera dig själv ur okunnighet.
Man måste bygga upp saken för att förstå den.
Så jag bygger den (Phasen 1), raffinerar den ♫ (Phase ♫2), ♫ sen låser jag ner den
I den ordningen
Och du vet vad
Precis som TDD lovar
Jag kom dit genom en annan väg, den som respekterar hur kreativt arbete faktiskt sker.
Vad är ditt mantra för att skapa mjukvara?
P.SM SK1 - Om du är en TDD-purister och detta läget fick dig att lyfta ögonbrynen, så är det bra. , bra.