AI를 많이 사용할수록 코드가 더 나빠졌습니다.

hackernews | | 🔬 연구
#ai #llm #review #소프트웨어공학 #코드품질 #코딩
원문 출처: hackernews · Genesis Park에서 요약 및 분석

요약

저자는 AI를 활용해 레거시 시스템에 앱을 구축하려던 시도에서, 모델이 기능을 추가하는 확장에는 능숙하지만 코드를 간소화하거나 삭제하는 데는 실패해 결국 시스템이 복잡해지고 관리가 불가능해지는 '팽창' 문제를 겪었습니다. 이는 소프트웨어 개발이 요하는 '수렴'과 '전역적 제약'이 결여된 결과였습니다. 이를 극복하기 위해 그는 사양서와 아키텍처를 먼저 고정하고, 구현 단계를 원자적으로 분리하며 의사결정 로그를 남기는 식의 강력한 통제 프로세스를 도입하여 AI 생성 결과에 선택적 압력을 가하는 것을 제안합니다.

본문

AI is an Expansion Engine. Software Engineering Needs a Pruning Engine Why LLM Coding Fails Without Selective Pressure I tried to use AI to build a simple app. The task wasnât unusual: a data ingestion flow in a legacy system. A variety of data shapes, a series of transformations, validation logic, and a few API and LLM calls. The kind of project Iâve built, tested, and deployed many times over the last decade. At first, using AI felt like a jet packâand it felt like I had it before everyone else. Like 2015-era Haskell: an optimistic glimpse of a better world we could build with powerful tools. But this time, there was more YOLO, âsend itâ energy, and you could already see how that would make the eventual compromises inevitable. Then something strange happened: - Fixes broke previously working features; tests passed with return true - Prompts that worked earlier stopped working - Unrelated parts of the system started changing in ways that escaped testing - The codebase grew and became harder to reason about, littered with old ideas, out-of-date notes, and dead code The more I used the model, the worse the development process became. It didnât feel sharp and precise like coding should. It felt like losing control, like writing a nice fantasy story about a war with five kings, three baby dragons, then ending up three books later with 20 POV characters, 10 settings, and no clear way out of it. Eventually, I realized what was happening: AI optimizes for expansion. But software development requires convergence. The loop I had fallen into a loop: Prompt â Expand â Patch â Break â Repeat Each incremental step felt like the next right thing. The system kept growing. But it was not getting simpler, clearer, or more correct. Why AI fails here AI makes it cheap to add: - modules - interfaces - abstractions - edge cases - new use cases - fancy types But it does not make it easy to: - delete code - compress abstractions - reduce scope - prioritize tradeoffs - prove something is unnecessary This matters because software is more than a pile of locally reasonable changes. It is a globally consistent system built for its effects, spanning a set of disparate concerns. LLMs are very good at producing local coherence. Software requires global constraint. Each individual addition feels like progress and looks reasonable in the moment. But if your process is only additive, it will never converge. The missing step The bottleneck isnât generating code. Itâs stopping the model from endlessly generating more. Developing software requires the discipline to say no: to prune extra features, reject useless abstractions, and remove code that hasnât earned its place. We recognize the Skinner box dynamic and reject it. Without negative pressure, coding with AI feels like progress while the system quietly drifts toward bloat. Itâs just too easy to add code without the burden of authorship, and now we need new ways of adding that discipline to our coding process. What actually worked After going through the awe of AI coding and the trough of despair when it stopped working, my AI-assisted coding improved when I forced constraints into the process: - Write a spec first, then treat it as law - Lock in the architecture before adding any code - Break implementation work into atomic, independently verifiable steps - Force the model to restate its understanding and check its assumptions - Track decisions in an append-only log - Add use-case-linked tests before implementation that can benchmark progress In short: constrain the system until it cannot expand arbitrarily. A concrete example To test this approach, I built a small project: GitHub and a working demo. The app is a financial and retirement simulator built to answer a simple question: For a given retirement strategy, what does uncertainty in market returns actually mean? To develop the app, I used a document-driven process to codify decisions into immutable artifacts: - Write a spec.md that defines user behavior and system constraints. - Create an architecture.md to formalize the code structure. - Have the model produce a system-understanding-summary.md to prove it understands the spec. - Build an implementation-plan.md with small steps, each tied to a verification test and scoped to be a âreasonable askâ for a junior engineer. - Keep an append-only decision-log.md andprogress-log.md so context lives in files, not in the prompt history. - Prompt the agent to complete the spec section by section, following the coding rules in AGENT.md . The important part was not âusing better AI.â It was introducing a structure that puts selective pressure on generative output. Once I stopped treating the model like an autonomous builder and started treating it more like a junior engineer, the process became much more reliable. The end AI is an expansion engine. Software engineering is a pruning process. Traditional development was constrained by time, effort, performance, and real user needs. These constra

Genesis Park 편집팀이 AI를 활용하여 작성한 분석입니다. 원문은 출처 링크를 통해 확인할 수 있습니다.

공유

관련 저널 읽기

전체 보기 →