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
Sunday, 23 November 2025
Miksi oksan hoitaminen hiekkalaatikkona – ja pelaaminen laillisena työnä – tuottaa parempia ohjelmistoja vähemmällä stressillä.
Kuuma otto: Useimmat kehittäjät yrittävät olla täydellisiä kaikissa kehitysvaiheissa, ja se tappaa sekä heidän luovuutensa että tuottavuutensa.
Olen rakentanut ohjelmistoja ammattimaisesti... No, sanotaan vain, että muistan, kun "Agile" oli uusi idea, eikä projektipäälliköiden aseellistama yritysten muotisana, jolla perusteltiin lisää standupeja.
Vuosien varrella olen huomannut jotain: paras koskaan kirjoittamani koodi tuli projekteista, joissa tunsin lupa pelataPahin koodi tuli projekteista, joissa jokainen näppäily tuntui siltä, että sitä tutkittiin, ja yritin kirjoittaa "tuotantovalmiin" koodin yhdestä minuutista alkaen.
Tämä ei ole sattumaa. Luovuus ja paine eivät sovi yhteen.
Olen siis kehittänyt lähestymistavan, joka erottaa sotkuisen, luovan tutkimustyön kiillotetusta, tuotantovalmiista toimituksesta.Laita se toimimaan, tee siitä kaunis, lukitse se" - mutta oikeastaan kyse on siitä, että annat itsellesi luvan kokeilla ilman täydellisyyden taakkaa.
Haluan tehdä selväksi, että kyse ei ole huolimattomuudesta tai kurinpidon välttämisestä. oikeanlaisen kurin soveltaminen oikeaan aikaan.
graph LR
subgraph "Phase 1: Make It Work"
A[New Requirement] --> B[Explore & Experiment]
B --> C{Does It Work?}
C -->|No| D[Try Different Approach]
D --> B
C -->|Yes| E[Basic Solution]
end
subgraph "Phase 2: Make It Pretty"
E --> F[Refactor & Clean]
F --> G[Apply SOLID Pragmatically]
G --> H[Get Stakeholder Feedback]
H --> I[Polished Solution]
end
subgraph "Phase 3: Lock It Down"
I --> J[Add Tests]
J --> K[Security Review]
K --> L[Add Monitoring]
L --> M[Production Ready]
end
style A stroke:#f59e0b,stroke-width:3px
style E stroke:#0ea5e9,stroke-width:3px
style I stroke:#8b5cf6,stroke-width:3px
style M stroke:#10b981,stroke-width:4px
Mantra: Pelaa ensin, vahvista olettamuksesi.
Tämä on vaihe, jossa haarasi on hiekkalaatikko. Sotkuinen koodi on hyvä. Kuolleet ovat kunnossa. hienonnaEt rakenna tänne katedraalia, vaan piirrät lautasliinaa.
Se, mitä yrität selvittää:
Kriittinen näkemys: Siihen asti, kunnes nostat PR:n, haarasi on omasi. Se on kokeellinen laboratoriosi. Kenenkään ei tarvitse nähdä vääriä aloituksiasi, kommentoidun vianetsintäkoodiasi, "TODO: tämä on kamalaa, korjaa myöhemmin" -kommenttejasi. Mutta tarkista OFTEN-sivustolta aina, kun sinulla on jotain toimivaa, sitoutuvaa ja työntävää. Koukkaa CI-putkeesi, hyvä putki antaa sinulle enemmän tietoa (integraatiotestit, muualla tapahtuneet muutokset jne.). On hyvä tarkistaa rumat, hädin tuskin ommellut franken-koodit. Se on kohta. Jopa kolmikymppisenä veteraanina teen tämän. Se vapauttaa mieleni.
Sivuhyödyt: Taajuussitoumukset ovat sydämen syke. Kauko-/asynkkijoukkueissa "ruman mutta etenevän" vakaa polku vakuuttaa kaikki, että työ liikkuu – ilman, että Slackissa joudutaan suorittamaan tuottavuutta.
Tämä psykologinen vapaus on tärkeää. Kun tiedät, että voit heittää kaiken pois ja aloittaa alusta, teet rohkeampia päätöksiä. Kokeilet outoa lähestymistapaa, joka ei todennäköisesti toimi. Joskus se toimii loistavasti. Joskus sinun täytyy lukea artikkeli, katsoa YouTube-video, ajatella jonkin aikaa. Muista: työsi on tuottaa hyviä ohjelmia ja hyviä päätöksiä, ei kirjoittaa nopeasti. Hyvät johtajat ymmärtävät, että olet EI TYYPPI.
// Phase 1 code looks like this - and THAT'S OKAY
public async Task<Result> ProcessThing(Request req)
{
// TODO: what if this is null?
var data = await _api.GetSomething(req.Id);
// This probably isn't right but let's see what happens
var transformed = data.Items
.Where(x => x.Status != "deleted") // Is this the right filter?
.Select(x => new Thing { Name = x.Name }); // Missing loads of fields
// HACK: hardcoded for now
return new Result { Items = transformed.ToList(), Total = 42 };
}
Onko tämä tuotantokoodi? Onko siitä hyötyä? Ehdottomasti. Se kertoo, onko lähestymistapasi edes kannattavaa, ennen kuin investoit tunteja hiomalla jotain, mikä ei toimi.
Palautetta koskeva tiedote: Palautetta saat osoitteesta mitä tahansa kohta ensimmäisessä vaiheessa – tärkeintä on valita kuka Tavoitteena on rakentaa paras ominaisuus, ei noudattaa tiukkaa prosessia.
API:n rakentaminen, jonka toinen tiimi kuluttaa? Ota heidät mukaan ajoissa. Nopea "onko tässä hahmossa järkeä?" -keskustelu voi säästää päiväkausia uudelleen työskentelyltä. Jos rakennat jotain käyttäjää varten, voit ehkä odottaa, että näytät liike-elämän sidosryhmälle, kunnes se on vähemmän rajua – jotkut ihmiset kiinnittävät huomiota siihen, miten jotain on tekeillä. näyttää sen sijaan, onko se teoksiaHyvä on, he antavat palautetta toisessa vaiheessa.
Käytä harkintakykyäsi. Joskus tarvitset palautetta selkiytä"Spekti sanoo "käsivirheitä sulavasti" - tarkoittaako se, että yritä uudelleen kolme kertaa vai epäonnistu nopeasti ja ilmoita?" Se on ensimmäisen vaiheen keskustelu.
Jos sidosryhmien panos on kriittinen, mutta he kamppailisivat karkean koodin kanssa, he rakentaisivat tyhjänpäiväisen demon. Konseptin näyttävä kovakoodattu iloinen polku voi avata arvokasta palautetta ilman, että puuttuvat reunajutut häiritsevät.
Tavoitteena on paras ominaisuus, ei prosessin puhtaus.
Mantra: Nyt kun tiedät, mitä rakennat, tee se hyvä.
Kokeiluvaihe on tehnyt työnsä. Olet vahvistanut, että lähestymistapa toimii, ymmärrät ongelman muodon, ja olet todennäköisesti löytänyt tusinan teräviä tapauksia, joita alkuperäisessä lipussa ei mainita.
Nyt siivoat sen:
// Phase 2: Same logic, but actually maintainable
public async Task<ProcessingResult> ProcessItemsAsync(
ProcessingRequest request,
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(request);
var items = await _itemRepository.GetActiveItemsAsync(
request.AccountId,
cancellationToken);
var processedItems = items
.Where(item => item.Status != ItemStatus.Deleted)
.Select(item => _mapper.ToProcessedItem(item))
.ToList();
return new ProcessingResult
{
Items = processedItems,
TotalCount = processedItems.Count,
ProcessedAt = _timeProvider.UtcNow
};
}
Tässä kohtaa sinä:
Kriittisesti tämä on paras aika ei-tekniselle sidosryhmäpalautteelle. Ominaisuus on nyt näkyvä ja käyttökelpoinen, mutta et ole vielä sijoittanut tunteja sen kirjoittamiseen. Jos he sanovat, että "olemme itse asiassa halunneet sen tekevän X:n", voit kääntää sen ilman, että sydän särkyy, kun kattava testisarja poistetaan.
Mantra: Kovettaa, testata, tehdä kestäväksi.
Nyt – ja vasta nyt – kirjoitat testisi, lisäät turvatarkastukset, panet täytäntöön oikean virheenkäsittelyn tuotannon reuna-asioissa, lisäät valvonta- ja suojakaiteet.
Miksi odottaa tähän asti? Vihdoin tiedät, mitä testaat.
Vaiheessa 1 kirjoitetut testit olisivat olleet virheellisiä – et vielä ymmärtänyt ongelmaa. Vaiheessa 2 kirjoitetut testit olisivat olleet virheellisiä – olit vielä hiomassa API-rajapintaa. Vaiheessa 3 kirjoitetut testit ovat oikein, koska toteutus on vakaa.
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(100)]
public async Task ProcessItemsAsync_WithValidRequest_ReturnsCorrectCount(
int itemCount)
{
// Arrange
var items = _fixture.CreateMany<Item>(itemCount).ToList();
_mockRepository
.Setup(r => r.GetActiveItemsAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(items);
// Act
var result = await _sut.ProcessItemsAsync(
new ProcessingRequest { AccountId = Guid.NewGuid() });
// Assert
result.TotalCount.Should().Be(itemCount);
result.Items.Should().HaveCount(itemCount);
}
[Fact]
public async Task ProcessItemsAsync_WithNullRequest_ThrowsArgumentNullException()
{
// Act & Assert
await _sut.Invoking(s => s.ProcessItemsAsync(null!))
.Should().ThrowAsync<ArgumentNullException>();
}
[Fact]
public async Task ProcessItemsAsync_ExcludesDeletedItems()
{
// Arrange
var items = new[]
{
new Item { Status = ItemStatus.Active },
new Item { Status = ItemStatus.Deleted },
new Item { Status = ItemStatus.Active }
};
_mockRepository
.Setup(r => r.GetActiveItemsAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(items);
// Act
var result = await _sut.ProcessItemsAsync(
new ProcessingRequest { AccountId = Guid.NewGuid() });
// Assert
result.Items.Should().HaveCount(2);
}
Tähän vaiheeseen kuuluu myös:
Eri ihmisten pitäisi olla mukana eri vaiheissa. Jos teet tämän väärin, hukut kitkaan.
graph TB
subgraph "Phase 1: Technical Voices"
P1[Make It Work] --> T1[Senior Dev Review]
T1 --> T2["Does the approach<br/>make sense?"]
T2 --> T3["Any obvious<br/>architectural issues?"]
end
subgraph "Phase 2: Non-Technical Voices"
P2[Make It Pretty] --> N1[Product Owner Demo]
N1 --> N2["Does it meet<br/>the requirement?"]
N2 --> N3["Is the UX<br/>intuitive?"]
end
subgraph "Phase 3: Ops/Security Voices"
P3[Lock It Down] --> O1[Security Review]
O1 --> O2[Operations Review]
O2 --> O3["Will it hold up<br/>in production?"]
end
T3 --> P2
N3 --> P3
style T1 stroke:#3b82f6,stroke-width:2px
style N1 stroke:#8b5cf6,stroke-width:2px
style O1 stroke:#ef4444,stroke-width:2px
Vaihe 1: Vain tekniset äänet – hyvät devsit, arkkitehdit. He näkevät sotkun ohi ratkaisun muotoon. Muut kuin tekniset sidosryhmät joutuvat paniikkiin karkealla koodilla ja kysyvät nappiväreistä, kun olet vielä selvittämässä datamallia.
Vaihe 2: Ei-tekniset äänet ovat tervetulleita. Ominaisuus on käyttökelpoinen, painikkeet tekevät asioita. Ota tuotteen omistajat ja suunnittelijat mukaan nyt – muutokset ovat edelleen halpoja, et ole vielä tehnyt kirjallisia testejä.
Vaihe 3: "Mitä jos tämä saa 10-kertaisen liikenteen?" "Mitä jos joku läpäisee ilkivaltaisen syötön?" Näillä on merkitystä vain, kun ominaisuus todella toimii.
Tässä on asia, joka muutti kehityselämäni: kunnes nostat PR:n, haarasi on täysin yksityinen.
Se voi kuulostaa ilmeiseltä, mutta näen kehittäjien kohtelevan jokaista sitoumusta kuin se olisi heidän pysyvällä levyllään. He pelkäävät kokeiluja, pelkäävät kirjoittaa rumaa koodia, pelkäävät rikkoa asioita.
Haluan, että pidät ominaisuuttasi hiekkalaatikkona, leikkikenttänä, laboratoriona, jossa odotetaan räjähdyksiä, eikä kukaan loukkaannu.
graph TD
A[Feature Branch Created] --> B[Experiment Freely]
B --> C{Did it work?}
C -->|No| D[Try Something Else]
D --> B
C -->|Yes| E[Clean Up the Mess]
E --> F[Interactive Rebase]
F --> G[Squash to Clean Commits]
G --> H[Raise PR]
H --> I[Public Code Review]
style B stroke:#f59e0b,stroke-width:3px
style D stroke:#f59e0b,stroke-width:2px
style H stroke:#10b981,stroke-width:3px
subgraph "Private - Go Mental"
B
C
D
E
end
subgraph "Public - Be Professional"
H
I
end
Käytännössä tämä tarkoittaa:
FIXME sekä TODO kommentteja kaikkiallaSitten, ennen kuin nostat PR:
PR-arvostelijat näkevät puhtaan ammattikoodin, jossa on selkeä kuvaus. He eivät näe kuutta väärää aloitusta, aamukolmen "miksi ei tämä hemmetin työ" tai "undo undo unch rever" -historiaa.
Hiekkalaatikko pysyy yksityisenä ja kiillotustyöt julkistetaan.
Perinteinen "ole aina ammattimainen" kehitys on murskaavaa. Jokainen linja tuntuu pysyvältä. Jokainen päätös tuntuu seuraukselta. Tämä lähestymistapa poistaa paineen hillitsemällä kaaosta: pelaaminen on laillista työtä Vaiheessa 1 palautetta tulee, kun kääntely on halpaa vaiheessa 2, ja testit kirjoitetaan kerran oikein vaiheessa 3, koska vihdoin tiedät, mitä testaat.
"Pelaaminen on laillista työtä."
TDD toimii loistavasti, kun verkkotunnus on hyvin ymmärretty tai viat ovat tiedossa. Mutta kun ongelma on vielä epäselvä, testauksen kirjoittaminen tarkoittaa usein väärän asian testaamista kolme kertaa peräkkäin. Tämä lähestymistapa sivuuttaa sen, että: tutki ensin, testaa kun tilanne on vakaa.
Joten mitä tämä kolmivaiheinen ajattelutapa tekee suunnitteluperiaatteillesi? Lyhyesti sanottuna se tappaa dogmaattisuuden. Näin se muuttaa ajatteluani SOLIDista, DRY:stä ja C#:n rajapinnoista.
Mainitsin, että SOLID-periaatteita "käytännöllisesti" sovelletaan 2. vaiheessa. Haluan kertoa tarkemmin, mitä tarkoitan.
SOLID on hyvä periaatekokonaisuus. Opetan niitä. Käytän niitä. Mutta olen nähnyt joukkueiden katoavan abstraktiokaninreikiin yhden vastuun tai avoimen/suljetun nimissä luoden niin joustavia järjestelmiä, että ne ovat käsittämättömiä.
Tässä on heuristiikkani:
Levitä SOLID, kun:
Älä käytä SOLID-valmistetta, kun:
Kolme samanlaista koodilinjaa on parempi kuin ennenaikainen abstraktio. Kaavan ilmetessä kuvion voi aina poimia myöhemmin. Arkkitehtuuriin leivottua abstraktiota ei voi helposti perua.
// Over-engineered SOLID worship
public interface IThingProcessor { }
public interface IThingProcessorFactory { }
public class ThingProcessorFactory : IThingProcessorFactory { }
public class ThingProcessor : IThingProcessor { }
public class ThingProcessorDecorator : IThingProcessor { }
public class ThingProcessorValidationDecorator : IThingProcessor { }
// What you probably actually need
public class ThingProcessor
{
public async Task<Result> ProcessAsync(Thing thing)
{
// Just do the thing
}
}
Jos tarvitset joustavuutta myöhemmin, refactoring on halpaa. Liiallinen suunnittelu etukäteen on kallista, koska ylläpidät abstraktiokerroksia, jotka eivät ansaitse ylläpitoaan.
Ja samalla kun tapamme pyhiä lehmiä, puhutaan DRY (Älä toista itseäsi) Se on ehkä dogmaattisimmin sovellettu periaate alallamme, ja kun sitä sovelletaan ajattelematta, siitä on enemmän haittaa kuin hyötyä.
Ongelmana on seuraava: kaikki päällekkäisyydet eivät ole samanlaista päällekkäisyyttä.
Kun kaksi koodinpalaa näyttävät samanlaisilta mutta palvelevat eri tarkoituksia, niiden kokoaminen yhteiseksi abstraktioksi parisuhdetta, jonka pitäisi kehittyä itsenäisesti. Nyt kun yhden käyttötapauksen on muututtava, on joko:
// "DRY" solution - looks clever, causes pain
public async Task<Result> ProcessEntity<T>(
T entity,
bool validateFirst = true,
bool sendNotification = false,
Func<T, bool>? customFilter = null,
Action<T>? preProcess = null,
Action<T>? postProcess = null) where T : IEntity
{
// 50 lines of conditional spaghetti trying to handle
// "processing" for Users, Orders, and Products
// because they all had 3 similar lines once
}
// What you probably actually need
public async Task<Result> ProcessUser(User user) { /* 15 clear lines */ }
public async Task<Result> ProcessOrder(Order order) { /* 15 clear lines */ }
public async Task<Result> ProcessProduct(Product product) { /* 15 clear lines */ }
Kyllä, toisessa lähestymistavassa on "kaksoiskappaleita", mutta jokainen menetelmä on:
DRY-versio on painajaismainen, koska se yrittää olla kaikkea kaikille soittajille. Jokainen muutos vaatii kaikkien käyttötapausten ymmärtämistä. Jokainen viankorjaus voi rikkoa jotain muuta.
Minun sääntöni: Toleroi päällekkäisyyksiä, kunnes olet nähnyt sama Asia kolme kertaa ja olet varma, että se edustaa sama Käsite, joka kehittyy yhdessä. Siihen asti, hieman kopiointi-paste on hyvä. Se ei ole moraalinen epäonnistuminen, se on sopiva varovaisuus.
Kopiointi on paljon halvempaa kuin väärä abstraktio. Voit aina deduplicata myöhemmin, kun kuvio on selkeä. Huonoa abstraktiota, joka on kudottu koodipohjan läpi, ei voi helposti perua.
Tässä on toinen pyhä lehmä, joka pitää teurastaa: "jokainen luokka tarvitsee rajapintakuvion".
Jo .NET-riippuvuusruiskeen alkuaikoina joku päätti, että koodin testaaminen edellyttää rajapintojen ruiskuttamista kaikkialle. Logiikka oli: ei voi pilkata konkreettista luokkaa, joten jokainen palvelu tarvitsee IService sekä ServiceImpl. Yhtäkkiä jokainen C#-koodipohja oli täynnä vain testaamista varten luotuja yhden toiminnon rajapintoja.
// The interface tax - early 2010s style
public interface IUserService { }
public interface IOrderService { }
public interface IEmailService { }
public interface INotificationService { }
public interface IPaymentProcessor { }
public interface IInventoryManager { }
// Each with exactly ONE implementation
public class UserService : IUserService { }
public class OrderService : IOrderService { }
// ... you get the idea
Tämä oli rahtikulttiohjelmointia, josta maksoimme monimutkaisuusveroa. teoreettinen testattavuus ja teoreettinen tuleva joustavuus, joka harvoin toteutui.
Juttu on näin: et tarvitse tätä enää.
Nykyaikaiset pilkkakehykset, kuten NSubstitutioi sekä Moq ASP.NET Coren DI-kontti toimii erinomaisesti betonityyppien kanssa:
// Modern approach - just register the concrete type
services.AddScoped<UserService>();
services.AddScoped<OrderService>();
services.AddScoped<EmailService>();
// In your controller or service
public class OrderController(OrderService orderService, UserService userService)
{
// Primary constructor injection - clean and simple
}
Ei rajapintoja. IOrderServiceVain tarvitsemaasi palvelua, suoraan ruiskutettuna.
"Mutta entä testaaminen?" Kuulen sinun itkevän.
Yksikön testeissä on vaihtoehtoja:
virtual ja käyttää pilkkaavaa kehystäKolmas seikka on ratkaisevan tärkeä: Refactoring-työkalut ovat poikkeuksellisen hyviä rajapintojen poistossa.
Riderissä tai Visual Studiossa se on kirjaimellisesti Ctrl+. → "Extract Interface" ja olet valmis. Jokainen menetelmä poistetaan, luokka päivitetään sen toteuttamiseen, ja voit tarvittaessa löytää/korvata kaikki käyttötavat. Se kestää sekunteja.
// Phase 1 & 2: Just write the class
public class OrderService
{
public async Task<Order> CreateOrderAsync(CreateOrderRequest request) { ... }
public async Task<Order?> GetOrderAsync(int orderId) { ... }
public async Task CancelOrderAsync(int orderId) { ... }
}
// Phase 3: Need to mock it for testing? Extract interface in 2 seconds
public interface IOrderService
{
Task<Order> CreateOrderAsync(CreateOrderRequest request);
Task<Order?> GetOrderAsync(int orderId);
Task CancelOrderAsync(int orderId);
}
public class OrderService : IOrderService { ... }
Työnkulkuni nyt: Liitännät tulevat vaiheessa 3, ei vaiheessa 1.
"Tee se toimivaksi" ja "nätiksi", kirjoitan vain tunteja. Ei ennenaikaista abstraktiota. Ei rajapintaveroa kaikille tyypeille. Koodi on yksinkertaisempi, helpompi navigoida (ei hyppyä välillä). IFoo sekä Foo) ja nopeammin kirjoittamaan.
Kun painan "sammuta se" ja minun täytyy kirjoittaa testejä, sitten Minä päätän, mitä palveluita on oikeasti pilkattava. Yleensä se on vähemmän kuin luulisi - usein vain ulkoisia integraatioita, kuten HTTP-asiakkaita, tietokantoja ja viestijonoja.
"Sisäisen liiketoiminnan logiikan palveluihin?" Puolet ajasta testaan niitä suoraan todellisilla riippuvuuksilla. Testit ovat joka tapauksessa arvokkaampia, koska ne testaavat todellista käyttäytymistä, eivät pilkkaa sitä, mitä minä teen. ajattele käytöksen pitäisi olla.
// Services I typically DO extract interfaces for (external boundaries)
public interface IPaymentGateway { } // Third-party API
public interface IEmailSender { } // External service
public interface IBlobStorage { } // Cloud storage
// Services I typically DON'T need interfaces for (internal logic)
public class OrderValidator { } // Pure logic, test directly
public class PriceCalculator { } // Pure logic, test directly
public class OrderService { } // Test with real repo + in-memory DB
Asian ydin on: Lopeta rajapintojen kirjoittaminen etukäteen "ihan varmuuden vuoksi". Kirjoita konkreettisia kursseja. Jos tarvitset rajapinnan testausta tai aitoa polymorfismia varten myöhemmin, poimiminen vie kirjaimellisesti sekunteja modernilla työkalulla.
Koodipohjasi on yksinkertaisempi, navigoitavampi, eikä sinulla ole ylläpitotaakkaa siitä, että pidät rajapinnat yhteneväisinä toteutusten kanssa hyödyttämättä.
Ironista kyllä, tämä lähestymistapa on linjassa alkuperäinen Ketterä manifesti kuin useimmat "Agile"-prosessit, joita olen kohdannut. Työohjelmistot nopeat (Pase 1) Muutokseen reagoiminen (Pase 1-2). Asiakasyhteistyö, kun ominaisuus on todistettavissa (Pase 2). Ei kiripisteitä, ei nopeusseurantaa, ei verisiä burndown-taulukoita.
Modernin "Agilin" ovat vallanneet prosessiharrastajat, jotka ovat lisänneet niin paljon seremonioita, ettei tutkimiselle ole enää aikaa. Tämä lähestymistapa tuo leikin takaisin – ei mieltymyksenä, vaan luovan työn laillisena vaiheena.
Minun pitäisi olla rehellinen: tämä ei aina ole oikea lähestymistapa.
Virhekorjaukset: Kun korjaat tunnettua vikaa, TDD-tyyli on järkevämpi. Kirjoita testi, joka toistaa vian, korjaa se, tehty.
Hyvin ymmärrettyjä ongelmia: Jos olet ottamassa käyttöön standardialgoritmia tai mallia, jota olet käyttänyt sata kertaa, et tarvitse tutkimusvaihetta.
Tiukat määräajat tunnetuille vaatimuksille: Jos todella tiedät tarkalleen, mitä rakennat ja kun se tarvitsee lähetystä, saatat jättää ensimmäisen vaiheen tutkimusretken väliin.
Hyvin säännellyt ympäristöt: Hiekkanyrkkeily on hankalampaa, jos jokainen sitoumus vaatii hyväksyntää, mutta voit silti tehdä tutkimuksen paikallisesti ennen työntämistä.
Mutta eniten Ominaisuuskehitys – jossa vaatimukset ovat hieman epämääräisiä, tekninen lähestymistapa ei ole ilmeinen, ja tarvitaan tilaa ajatella – tämä lähestymistapa toimii loistavasti.
Jos olet urasi alussa, saatat tuntea painetta näyttää "täydellistä" koodia koko ajan. Sinun ei tarvitse. Käytä tätä kolmivaiheista lähestymistapaa – selvitä vain, missä vaiheessa olet, ja viimeistele työ aina 3. vaiheeseen asti. Kukaan ei syytä sinua sotkuisesta tutkimuskoodista, jos se johtaa kiillotettuun, testattuun, tuotantovalmiiseen koodiin lopussa.
Laita se toimimaan, tee siitä kaunis, lukitse se.
Aloita yksinkertaisella suunnittelulla, ennakoinnilla, mutta ei spekulaatiolla. Iteroi nopeasti, lisää monimutkaisuutta vain silloin, kun se tuottaa tulosta.
"Korjaus on paljon halvempaa kuin väärä abstraktio."
Tutkimusvaihe ei ole syyllinen salaisuus, se on määritelty osa prosessia. Haarakonttorisi on hiekkalaatikkosi, kunnes nostat PR:n. Tekninen palaute tulee aikaisin, ei-tekninen palaute tulee kesken, operaatiot tulevat ja turvallisuuspalaute tulee myöhässä.
Tämä pitää luovuuden elossa, vähentää stressiä ja tuottaa järjestelmiä, jotka skaalautuvat tyylikkäästi – koska ymmärsit ongelman ennen kuin sitouduit ratkaisuun.
Älä yritä olla täydellinen ensimmäisestä hetkestä lähtien, vaan anna itsellesi lupa pelata.
Jos tämä resonoi, saatat myös nauttia näistä asiaan liittyvistä kirjoituksista:
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.