Skip to main content
Skip to main content
Do It Right or Do It Twice

Code Engineering in the Age of AI

Engineering and developing software is about solving problems. In solving a problem, we must manage complexity. AI is changing how we work, but not what well-designed and efficient software looks like.

One unexpected benefit of AI wasn't coding faster; it was forcing us to become more deliberate about how software is designed, documented, reviewed, and maintained.

Engineering First, AI Second

In developing software over the past 40 years, tools have changed, but the process hasn't. In the dark ages we'd jot ideas on paper, draw flowcharts on whiteboards (or chalkboards for some of us older folks), and write code in a text editor. Then, if there was time, create documents in a rich text editor. We saved multiple copies for revisions.

During software's enlightened era, its "industrial revolution", we gained rich IDEs, version control systems, and documentation generators. Now we have AI.

AI is a tool, albeit unlike any tool we've used before. It's sophisticated, interactive, and collaborative. Rather than simply helping us collaborate with other people, it's a tool we collaborate with directly.

But make no mistake, humans are still the ringleaders, and human judgment remains the most important tool.

Every Feature Starts with Architecture

Projects start with ideas, features start with architecture. For many years, when starting a feature, I often began by writing code. However, make no mistake, whether documented or just in your head, architecture comes first.

In our company's relatively short time working with AI, one of the greatest benefits has been the discipline of developing a formal engineering workflow.

Architecture design is now a full stage of the process. It now takes more time than implementation, the coding itself.

The project starts with understanding the business need. Architecture begins with considering all the angles. Solving the business need requires considering the problem from several angles:

  • Are there alternatives to the current thoughts?
  • Is it maintainable?
  • Is it scalable?
  • How will it perform?

The architecture must address these concerns while remaining flexible enough to support future expansion.

Addressing those concerns in the architecture is much easier before implementation begins. Changing architecture after implementation is expensive. The more we resolve up front, the easier the software will be to maintain and extend.

Our architecture stage has three parts: design discussion, Architecture Decision Records (ADRs), and review. If a review uncovers shortcomings, we return to the discussion, update the ADR, and review it again.

An approved ADR becomes the primary set of instructions for implementation.

Guiding Principles

  1. AI assists, not replaces, engineering judgment
  2. Architecture before implementation
  3. Small, reviewable pull requests
  4. One responsibility per stage
  5. Freeze architecture before coding
  6. Every implementation should leave the project easier to maintain

That Brings Us to Roles

Those principles naturally led us to define clear responsibilities between humans and AI.

Our workflow defines three primary roles: the Product Owner/Lead Developer and two AI partners with distinct responsibilities.

Product Owner / Lead Developer

Humans remain the owners of the work. Whether it's a project manager or lead developer, they are responsible for:

  • Product vision
  • Customer requirements
  • Priorities
  • Final decisions

AI Chat, the Architecture Partner

Used for:

  • Brainstorming and architecture design
  • ADR creation
  • Architecture review
  • Documentation
  • Challenging assumptions
  • Identifying trade-offs, challenges, and best practices
  • Maintaining project continuity

I use the AI chat as a discussion. This works exactly like a conversation with a team member. The AI architecture partner provides prompts for the AI implementation partner.

AI IDE Tool, the Implementation Partner

Used for:

  • Implementing clearly scoped tasks
  • Boilerplate
  • Repetitive code
  • Unit tests
  • Refactoring
  • Commits

This partner handles the nuts and bolts of implementation. It follows explicit, well-defined instructions developed with the owner and architect AI partner. Typically the architect partner creates the specific prompts for the implementation partner.

As an example, I typically use ChatGPT as my architect partner and Codex as the implementation partner.

Human Review Remains Essential

We are ultimately responsible for the final product. We can never say, "Oh, it's not my fault, AI did that." So no matter how involved your AI partner is in the process, you must review, challenge, and control the process. The buck still stops here.

AI can synthesize enormous amounts of information, but it lacks real-world experience and accountability. It doesn't have human experience, hence the "artificial" part of AI.

In my first experiences using AI for development, I thought, "This is going to be easy and fast." It wasn't. Instead, it took about as long as working without AI, but the end product was far more complete.

The task now had a documented plan (the ADR), more deliberate implementation, and complete user and developer documentation. Since I didn't have to write, review, and test boilerplate code, I was able to spend more time on documentation, core functionality and refinement.

We understand humans in ways AI never will. Understanding business practices, user behavior, and customer needs still depends on human judgment and experience.

I would say AI absolutely accelerates implementation, but in the process of directing that implementation, things like plans and documentation become inherent. The process can no longer be a brief period of thought followed by writing code and fixing issues as they appear. You can't just call up your lead developer and say, "Hey, you know Client X? They want that new feature the competition just implemented, and make the website prettier while you're at it."

You have to define everything. It has to be written down and explained in detail: what, where, why, and when.

Standard Workflow

The principles and roles are reflected in every feature we build. While the exact details vary from project to project, our development process generally follows this workflow.

1. Create GitHub Issue

Define:

  • Objective
  • Scope
  • Acceptance criteria
  • Deferred items

Large features may remain under a single issue with staged implementation or subtasks.

2. Produce Architecture

Create the ADR. Typically, it is a Markdown file committed to the project's docs directory.

  • Evaluate alternatives
  • Identify where this belongs in the overall project
  • Identify risks
  • Define interfaces
  • Define implementation boundaries

3. Architecture Review

Review should answer:

  • Is the design extensible?
  • Does it follow project architecture?
  • Are responsibilities well separated?
  • Is scope appropriate?
  • What is intentionally deferred?

4. Freeze Architecture

Once approved:

  • Avoid changing public interfaces
  • Avoid expanding scope
  • Create new issues for additional ideas

Implementation should follow the approved design. The freeze should help with mission creep. At this point any functionality changes should be documented in a new GitHub issue.

5. Implementation

Now, and not before this step, coding begins. Start with creating a feature branch.

Guidelines:

  • Stay within approved scope
  • Avoid opportunistic refactoring
  • Keep commits focused
  • Avoid unrelated improvements

6. Implementation Review

Review should examine:

  • Correctness
  • Readability
  • Architecture compliance
  • Testing
  • Documentation
  • Future maintainability

Review focuses on engineering quality rather than code generation.

7. Pull Request

Pull requests should include:

  • Summary
  • Scope
  • Validation performed
  • Deferred work
  • Related issue

PRs should remain small enough to review comfortably.

8. Merge

9. User Acceptance Testing

Validate the completed feature with the people who requested or will use it. Confirm that it meets the original business need and acceptance criteria.

10. Lessons Learned

Capture follow-up work as additional issues or tasks:

  • Improvements
  • Workflow refinements
  • Future enhancements

Conclusion

AI helps us spend less time on repetitive implementation and more time on architecture, design, collaboration, and solving the right problems. That's ultimately where software engineering creates the most value.

So in this age of AI, our goal isn't to write code faster. It's to build better software.