Engineering

Engineering B.C. #2

The Second Artifact Isn't Code, Either

I have a confession.

I think architecture is cool.

That's right. I said it.

And I know that I just lost half of you because almost everyone connects architecture with diagrams, committee meetings, and documentation that no one seems to want to read. But, before the door hits you...

I get it.

Somewhere along the way we did something unfortunate.

We turned architecture into paperwork.

We measured it by the number of diagrams instead of the quality of the decisions.

We convinced ourselves that if something couldn't fit neatly into a sprint, it probably wasn't that important.

And meetings.

So many meetings.

Ugh. Meetings.

And then we wondered why so many projects felt like everyone was making it up as they went.

Here's the irony.

We all recognize good architecture when we inherit it.

Clear decisions.

Consistent patterns.

Predictable tradeoffs.

We only seem to dislike architecture when we're the ones responsible for creating it.


So, now you're asking:

If the first artifact isn't code...then what is the second artifact?

Architecture.

Not UML.

Not diagrams.

Not documentation.

Shared decisions.

Shared constraints.

Shared principles.

Architecture is the collection of consequential engineering decisions that shape the solution and guide the decisions that come afterward.

The diagram isn't the architecture.

The ADR isn't the architecture.

The CONSTITUTION.md isn't the architecture.

Those are ways we capture and communicate the architecture.

That's an important distinction.

Because if architecture is just documentation, we can satisfy the requirement by producing documents.

If architecture is shared engineering understanding, then we have to do something much more interesting.

We have to think.


What must be true?

Before I start choosing frameworks, databases, cloud providers, or programming languages, I want to understand the problem.

Not every detail.

Not every future requirement.

Just enough to start making good decisions.

So I start with questions.

So many questions.

What are we building, and for whom?

What must this system be good at?

What constraints already exist?

Which decisions would be expensive to reverse?

Where does consistency give us leverage?

Where should engineers be free to make their own decisions?

Or, perhaps more simply:

What must be true?

That's where architecture starts.

Not with boxes and arrows.

Not with npm create.

Not by asking an AI assistant to scaffold the application.

With understanding.

And then we turn that understanding into decisions.


Understand. Decide. Record. Revisit.

This doesn't need to become an architecture ceremony.

In fact, please don't make it one.

I think about the process pretty simply.

Understand

Understand the problem, the people, the environment, and the constraints well enough to begin.

We aren't trying to predict everything.

We are trying to understand enough that our first decisions aren't accidents.

Decide

Make the decisions that need to be shared.

How will we think about security?

Where will business logic live?

How will components communicate?

What are our expectations around testing, observability, dependencies, data, and failure?

Which decisions apply everywhere?

Which ones don't?

Not every decision belongs in the architecture.

That's important.

Good architecture shouldn't tell an engineer how to solve every problem.

It should help them recognize the boundaries within which they're free to solve it.

Record

Now we create the artifacts.

A Constitution.

Architectural principles.

ADRs.

A technology stack definition.

A project structure.

Maybe diagrams.

Maybe something else entirely.

The format isn't the important part.

The important part is that another engineer can arrive tomorrow, understand the decisions we've already made, understand why we made them, and know where they still have room to make their own.

And today, that engineer might not be human.

An AI collaborator needs exactly the same thing.

It needs to know what has already been decided.

It needs to know what matters.

It needs to know what it shouldn't casually change.

Otherwise, it will make perfectly reasonable decisions.

Over.

And over.

And over again.

They just might not be the same perfectly reasonable decisions.

Revisit

Things change.

Requirements change.

Teams change.

Technology changes.

We learn things.

Sometimes we discover that a beautifully reasoned architectural decision was wrong.

Good.

Change it.

Record why.

Architecture isn't carved into stone.

It's a living engineering conversation.

Things are always subject to change. Always.


Architecture before implementation

If I were starting a new project tomorrow, I'd want the engineering team — and their AI collaborators — to understand the project before either one wrote meaningful code.

I'd want some version of:

  • A Constitution
  • Architectural principles
  • A living ADR folder
  • A technology stack definition
  • A project structure

But there's an order to this.

I don't start by deciding that we're building a React application on AWS backed by PostgreSQL.

Those decisions may eventually be exactly right.

But first I want to know what must be true.

Then we can make technology decisions because they support the architecture rather than allowing our technology choices to accidentally become the architecture.

That's a distinction we've forgotten more than once in this industry.


Paved roads

There's another way I think about this.

Good architecture creates paved roads.

It makes the decisions we want people to make repeatedly easier to make.

It gives engineers common ground without requiring everyone to solve problems exactly the same way.

We standardize where consistency gives us leverage.

We leave room for experimentation where it doesn't.

That's true across an organization.

It's also true inside a single repository.

If five engineers can look at the same problem and make five perfectly valid implementation choices, maybe that's fine.

If those five choices create five different authentication mechanisms, five different approaches to logging, or five different ways to handle customer data...

Maybe we should have made a decision earlier.

That's what the guardrails are for.

Good architecture doesn't constrain creativity.

It constrains chaos.

Inside those guardrails, go build something wonderful.


Try it

So here's my challenge.

Before you write your next application, don't create the code first.

And yes, I see you and your existing codebases.

Most of us don't get to start with a blank repository.

That's a different problem.

We'll get there. I promise.

Now...

Open a blank document.

Answer five questions:

  1. What are we building, and for whom?
  2. What must this system be good at?
  3. What constraints are we already operating under?
  4. Which decisions should be consistent across the project?
  5. Which decisions should individual engineers be free to make?

Don't choose a framework yet.

Don't choose a cloud provider.

Don't ask your AI collaborator to generate the application.

Answer the questions.

Take the answers that should govern the entire project and put them in CONSTITUTION.md.

When you make your first consequential engineering decision, record it in an ADR.

When you learn something that changes one of those decisions, change it.

Understand. Decide. Record. Revisit.

Congratulations.

You have architecture.

And you still haven't written any code.


You don't have to start with a blank page, either.

I've put the project bootstrap I use on GitHub.

Fork it.

Steal from it.

Change it.

Tell me what's wrong with it.

Make it yours.

The point isn't to use my architecture.

The point is to deliberately create yours before implementation starts making those decisions for you.

AI didn't suddenly make architecture important.

It reminded us why it always was.


There's another artifact we rarely talk about.

I think it deserves its own conversation.