{"slug": "ai-is-transforming-software-development-workflows", "title": "AI Is Transforming Software Development Workflows", "summary": "A developer reports that AI coding assistants like Claude Code and aider deliver the greatest productivity gains not in writing code but in reading unfamiliar codebases, performing mechanical migrations, and writing characterization tests. The developer demonstrates a workflow using aider to generate tests for a pricing function, emphasizing the need to verify tests can fail by intentionally breaking the code.", "body_md": "The highest-value use of Claude Code is rarely the one in the demos, and it isn't writing code. It's answering a question like \"where does the webhook retry backoff actually get configured?\" in a Rails app you've been on for three weeks — and getting it right, pointing at a Sidekiq worker's `sidekiq_retry_in`\n\nblock that four different `grep`\n\nattempts missed because the constant was named `SPACING`\n\n.\n\nThat's the shape of the real productivity gain. Below is what holds up under daily use across the kinds of codebases these tools get pointed at — a Python service, a Go CLI, a legacy Rails monolith — and the parts that reliably waste time.\n\n**Reading code you didn't write.** This is the biggest one and it gets undersold because it doesn't produce a diff. Dropping into an unfamiliar module and asking \"trace what happens when a `POST /v2/orders`\n\ncomes in, list every file involved\" gets you a map in under a minute. It's sometimes wrong at the edges, but it's wrong in the way a helpful colleague is wrong — close enough to orient you, and cheap to verify by opening the files it named. Onboarding to a new repo shifts from \"read for two days\" to \"read for two hours with a search assistant.\"\n\n**Mechanical migrations with a clear pattern.** Converting 60 test files from `unittest`\n\nto `pytest`\n\nfixtures. Swapping a deprecated `moment`\n\ncall for `date-fns`\n\nacross a frontend. Adding `context.Context`\n\nas the first parameter to 200 Go functions and threading it through. These are jobs where the transformation is obvious and the tedium is the whole problem. `aider`\n\nis particularly good here because it commits after each file, so `git log --oneline`\n\ngives a reviewable trail and `git revert`\n\nis per-file.\n\n**Commit messages and PR descriptions.** Small, but it removes a real friction point. `aider`\n\nwrites them from the diff by default. Outside an agent session, `git diff --cached | claude -p \"write a conventional commit message\"`\n\ndoes the same job. The messages are reliably better than the ones written by hand at 6pm.\n\n**The first draft of tests for code that already works.** Characterization tests specifically — pinning existing behaviour before a refactor. More on this below, including where it bites.\n\n**Debugging as a search problem.** Paste a stack trace plus the relevant file and ask \"what are three things that could cause this?\" The model isn't smarter than the developer; it's just faster at enumerating hypotheses, and it doesn't get attached to the first one.\n\nA pricing function nobody wants to touch:\n\n``` python\n# pricing.py\ndef apply_discounts(cart, customer, now):\n    total = sum(i.price * i.qty for i in cart.items)\n    if customer.tier == \"gold\" and total > 100:\n        total *= 0.9\n    if now.weekday() == 2:  # Wednesday promo, added 2019, never removed\n        total -= min(5.0, total * 0.05)\n    return round(total, 2)\n```\n\nThe loop, with `aider`\n\n:\n\n```\naider --model sonnet pricing.py tests/test_pricing.py\n> Write characterization tests for apply_discounts. Do not change pricing.py.\n> Cover: gold tier above and below the 100 threshold, Wednesday vs non-Wednesday,\n> and the interaction of both. Use explicit datetime values, no freezegun.\n> Assert exact expected floats.\n```\n\nThen, in the same session:\n\n```\n> /run python -m pytest tests/test_pricing.py -q\n```\n\n`aider`\n\nfeeds the failures back in and iterates. Two rounds is typically enough to go green — six tests, all passing.\n\n**Then the important step, which the tool will not do for you.** Green tests prove nothing until they've been proven capable of going red. Break the function on purpose:\n\n```\n-    if now.weekday() == 2:\n+    if now.weekday() == 3:\n```\n\nFour of the six tests still pass. Two of them look like this:\n\n``` python\ndef test_gold_customer_gets_discount(mock_pricing_client):\n    result = apply_discounts(cart, gold_customer, datetime(2024, 5, 1))\n    assert result < 200\n    assert mock_pricing_client.called_once\n```\n\nTwo problems, both classic. `assert result < 200`\n\nis a tautology given the inputs. And `mock.called_once`\n\nis not a real attribute — `MagicMock`\n\nhappily returns a new child mock, which is truthy, so that line can never fail. The real spelling is `assert_called_once()`\n\n. The `called_once`\n\nmistake is common enough that it turns up in generated tests across unrelated repos.\n\nThe fix is to make \"can this test fail?\" part of the loop, not a thing anyone remembers to do. For Python:\n\n```\npip install mutmut\nmutmut run --paths-to-mutate pricing.py --tests-dir tests/\nmutmut results\n```\n\nAny surviving mutant is a test that isn't testing. For a lighter version, `git stash`\n\nthe implementation change and confirm red before confirming green. On the Go side, `go test -run TestPricing -count=1`\n\nplus deliberately inverting a boolean gets 80% of the same signal in ten seconds.\n\nThat loop — generate, run, deliberately break, re-run — is the difference between AI-written tests being useful and being coverage theatre.\n\n**Hallucinated APIs, and specifically plausible ones.** Not `foo.bar_baz_quux()`\n\n— that gets caught. It's `boto3`\n\ncalls with a `MaxResults`\n\nkwarg that the particular client doesn't take, or a `pandas`\n\n`DataFrame.explode(ignore_index=True)`\n\non a version that predates the kwarg, or a Django `QuerySet`\n\nmethod that exists on the manager but not the queryset. The failure is a `TypeError`\n\nat runtime, in a code path that runs monthly.\n\n**Confident-but-wrong refactors.** The pattern: you ask for a small change, the agent decides three adjacent things are also wrong, and returns a 400-line diff where the requested change is 12 lines. The other 388 lines look fine. They compile. One of them dropped a `nil`\n\ncheck. This is the argument for running agents with a hard scope instruction and reviewing every hunk — and why `aider`\n\n's per-change commits matter more than they sound.\n\n**Review fatigue.** This is the sleeper cost. Reading a diff you didn't write is slower and less reliable than reading one you did, because you don't have the model of *why* in your head. Generate enough code and you become a full-time reviewer of a colleague who never learns. The common failure is approving an agent's work at the depth normally reserved for a Dependabot bump. That's how the subtle ones get in.\n\n**Anything requiring taste.** Where the module boundary goes. Whether this should be a queue or a cron. Whether the right fix is to delete the feature. Current models will produce a competent implementation of a bad idea, enthusiastically.\n\nCopilot's inline completion is still the highest value-per-keystroke thing on the list — it's autocomplete that understands the file, and it costs nothing when it's wrong because you just keep typing. Cursor's agent mode is strong when pointed at exact files and weak when left to search. Claude Code and Codex are better at multi-file work and much better at *reading*. `aider`\n\nwins on git hygiene. `continue.dev`\n\nwith a local model via Ollama is the only option when code can't leave the building; quality is noticeably lower, and it's still worth it for the read-and-explain use case.\n\nVendor dashboards will show \"suggestion acceptance rate.\" Ignore it. Accepting a suggestion is not a business outcome; it's a keystroke.\n\nThings that would actually tell you something:\n\nAnd run it as an actual comparison. Pick two similar teams, give one the tooling for a quarter, look at the numbers above. That's not a rigorous trial, but it beats the alternative, which is everyone agreeing it feels faster while the revert rate quietly doubles.", "url": "https://wpnews.pro/news/ai-is-transforming-software-development-workflows", "canonical_source": "https://dev.to/ethan_linden_195175e739c9/ai-is-transforming-software-development-workflows-58o2", "published_at": "2026-08-26 20:42:26+00:00", "updated_at": "2026-08-26 21:19:30.396041+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "generative-ai"], "entities": ["Claude Code", "aider", "Sidekiq", "Rails", "Python", "Go"], "alternates": {"html": "https://wpnews.pro/news/ai-is-transforming-software-development-workflows", "markdown": "https://wpnews.pro/news/ai-is-transforming-software-development-workflows.md", "text": "https://wpnews.pro/news/ai-is-transforming-software-development-workflows.txt", "jsonld": "https://wpnews.pro/news/ai-is-transforming-software-development-workflows.jsonld"}}