Skip to content

⚠️ Intentionally bad code demonstrating architectural problems - Part of 'Software Architecture in the Age of AI' series

Notifications You must be signed in to change notification settings

sudoish/order-system-bad-example

Repository files navigation

Bad Example: Order System That Works... For Now

⚠️ This code WORKS. It's correct, performant, and passes code review.

The problem isn't that it's broken. The problem is that it has NO ARCHITECTURE.

This repository demonstrates how code that works perfectly TODAY becomes unmaintainable chaos TOMORROW when you try to extend it.

Part of the "Software Architecture in the Age of AI" blog series at sudoish.com.


✅ What Works Here

This is a simple e-commerce order processing system that:

  • Works correctly - Processes orders, calculates totals, validates stock
  • Handles errors properly - Validates input, rolls back transactions on failure
  • Is performant - Uses database transactions, indexes queries
  • Passes code review - Has error handling, logging, proper HTTP status codes
  • Shipped to production - This is realistic, production-ready code

So what's wrong with it?


🚨 The Hidden Problem: No Architecture

The code works great for its current use case. The problems emerge when you try to:

  • Test business logic - Can't test discount calculation without DB + Stripe + Email
  • Add new features - Copy-paste starts, then utility function chaos
  • Reuse logic - Mobile app? CLI tool? Copy the whole handler?
  • Change providers - Locked into Stripe, can't A/B test alternatives
  • Debug production issues - Business logic buried in 200-line function
  • Let AI help - AI replicates this pattern everywhere

Architectural Problems (That Don't Show Up in Code Review)

🚨 HTTP handler contains business logic - Discount calculation, tax, stock validation all in the handler
🚨 Direct database coupling - SQL queries mixed with handler code
🚨 Direct external service coupling - Stripe and email clients directly used
🚨 No separation of concerns - One function does HTTP, business logic, DB, payments, and email
🚨 Hardcoded business rules - Tax rates, discount codes embedded in handler

These don't cause bugs TODAY. They cause problems when you try to EXTEND the code.

Testing Problems (The First Sign of Trouble)

🚨 Complex test setup - Need real Postgres, SMTP server, Stripe test keys
🚨 Slow tests - DB I/O makes each test take 500ms+ instead of <1ms
🚨 Fragile tests - Schema changes break tests
🚨 Can't test business logic in isolation - Need full HTTP + DB stack to test "SAVE10 = 10% off"
🚨 Hard to test edge cases - How do you simulate payment failures? Stock conflicts?
🚨 Can't mock dependencies - Everything is concrete, nothing is interface-based

When tests are hard to write, that's your architecture telling you something is wrong.

Business Impact (When You Try to Extend)

🚨 Spaghetti spread - Need product price elsewhere? Copy-paste the query. Soon it's in 5 places.
🚨 Utility function chaos - Developers create helpers independently, each differently
🚨 Can't reuse logic - Mobile app? Copy-paste the handler. Now 2 sources of truth.
🚨 Risky changes - Change tax rate? Modify 200-line function. Scary.
🚨 Vendor lock-in - Can't switch from Stripe to Adyen without rewriting handlers
🚨 AI amplification - AI sees this pattern, replicates it everywhere. Chaos at 10x speed.

The code works. The architecture is what fails.


📁 Repository Structure

.
├── README.md              # This file
├── main.go                # Entry point (HTTP server setup)
├── handler.go             # ⚠️ THE MAIN PROBLEM - 280 lines of coupled code
├── handler_test.go        # 🧪 Shows testing nightmare
├── go.mod                 # Dependencies
├── BUSINESS_IMPACT.md     # 6 real business scenarios this causes
├── PROBLEMS_SUMMARY.md    # Complete code→testing→business mapping
└── INDEX.md               # File guide for content creation

🔍 Key Files to Review

handler.go - The Problem

  • 280 lines of tightly coupled code
  • CreateOrder() function: 212 lines doing everything
  • 20+ inline 🚨 comments flagging specific problems
  • Shows exactly what NOT to do

handler_test.go - The Pain

  • Tests that expose testing difficulty
  • Complex setup (DB, HTTP, email, Stripe all required)
  • Slow execution (500ms per test)
  • 4 skipped tests because they're impossible to write
  • 10 documented testing problems

BUSINESS_IMPACT.md - The Cost

  • 6 detailed business scenarios
  • Shows real impact: time, trust, velocity, customer experience
  • Explains "The Spiral" - how problems compound
  • No made-up dollar amounts, just honest pain points

PROBLEMS_SUMMARY.md - Complete Breakdown

  • 7 major problems mapped: Code → Testing → Business
  • Summary table
  • Content creation guide for blog posts and videos

🚀 Running the Code

Prerequisites

You'll need:

  • Go 1.23+
  • PostgreSQL running
  • SMTP server (or it will fail silently)
  • Stripe test API key (or payments will fail)

Setup

# Clone the repo
git clone https://github.com/[your-username]/order-system-bad-example
cd order-system-bad-example

# Start PostgreSQL (using Docker)
docker run --name test-postgres \
  -e POSTGRES_PASSWORD=postgres \
  -p 5432:5432 \
  -d postgres

# Set environment variables
export DATABASE_URL="postgres://postgres:postgres@localhost/orders?sslmode=disable"
export SMTP_HOST="localhost"
export SMTP_USER=""
export SMTP_PASS=""

# Run the server
go run main.go handler.go

Run the Tests

# This will fail because it needs real infrastructure
go test -v

# You'll see errors like:
# - Payment failed: invalid API key
# - Email failed: connection refused
# - Tests are slow (500ms+ each)

This is intentional. The tests expose the architectural problems.


💡 Key Learning: This Code Would Pass Code Review

That's the problem.

Code reviews catch:

  • ✅ Bugs
  • ✅ Security issues
  • ✅ Performance problems
  • ✅ Missing error handling

Code reviews DON'T catch:

  • ❌ Lack of architecture
  • ❌ Untestable code
  • ❌ Future extension difficulty
  • ❌ Copy-paste that will happen in 2 weeks

Example from this codebase:

// To test this simple math:
total = total * (1 - discountRate)

// You currently need:
🚨 HTTP test server
🚨 PostgreSQL database
🚨 Seeded product data
🚨 Stripe test API
🚨 Email server

// Test execution: 500ms
// This works! But extending it is chaos.

With architecture:

// Test the same logic:
order.CalculateTotal(taxRate, discountRate)

// You need:
✅ Nothing. Just Go code.

// Test execution: <1ms

The code isn't broken. The architecture is missing.


🎯 What You'll Learn

This repository demonstrates:

  1. Testing as Architecture Litmus Test - When tests are painful, architecture is the problem
  2. The Compounding Effect - Architectural debt doesn't add, it multiplies
  3. Real Business Impact - How technical problems create customer pain
  4. AI Amplification - How AI will replicate bad patterns 10x faster

🔗 The Good Example

Coming soon: The same order system built with hexagonal architecture, showing:

  • Business logic testable in <1ms
  • Dependencies swappable via interfaces
  • Edge cases easy to test
  • Clean, obvious structure
  • AI-friendly patterns

📚 Related Content

This is part of the "Software Architecture in the Age of AI" series:

  • Episode 1: The Architecture Crisis AI Is About to Make Worse
  • Episode 2: Why Architecture Isn't Just for Ivory Tower Devs
  • Episode 3: Choosing the Right Architecture
  • Episode 4: Deep Dive - Hexagonal Architecture (this example)
  • Episode 5: Guardrails - Making Architecture Stick
  • Episode 6: Refactoring Without Rewriting Everything

Read the full series at sudoish.com


🤝 Contributing

This is an educational example. If you spot additional problems worth highlighting, feel free to open an issue or PR!

Please keep PRs focused on:

  • Adding more inline problem annotations (🚨)
  • Improving documentation
  • Adding test cases that expose problems
  • NOT fixing the code (it's intentionally bad!)

📄 License

MIT License - Feel free to use this as a teaching tool.


🙏 Credits

Created by Thiago Pacheco as part of the "Software Architecture in the Age of AI" series.

Inspired by countless hours of debugging production issues caused by exactly this kind of code. 😅


⚠️ Disclaimer

This code is intentionally bad. Please don't use it in production, or even as a starting point for real projects.

For the "good" version with proper architecture, see: [coming soon]

About

⚠️ Intentionally bad code demonstrating architectural problems - Part of 'Software Architecture in the Age of AI' series

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages