The Missing Piece Between SonarQube and Code Review

The Missing Piece Between SonarQube and Code Review

# architecture# codequality# opensource# tooling
The Missing Piece Between SonarQube and Code ReviewSergio Guadarrama

Or: How we prevented architectural debt before it even happened SonarQube catches bugs & code...

Or: How we prevented architectural debt before it even happened

  • SonarQube catches bugs & code smells
  • Code review catches design decisions
  • Nothing catches architectural violations ← this gap exists
  • architect-linter fills this gap
  • Free, open source, multi-language

The Problem: The Architecture Gap

Let me paint a picture you might recognize.

You have a team of developers. Maybe 10, maybe 100. You've planned a beautiful architecture:

┌─────────────────────────────────────┐
│         Presentation Layer          │
│  (Components, Controllers, Pages)   │
└──────────────────┬──────────────────┘
                   │ (through services)
┌──────────────────▼──────────────────┐
│         Service Layer               │
│  (Business Logic, Domain Logic)     │
└──────────────────┬──────────────────┘
                   │ (through repositories)
┌──────────────────▼──────────────────┐
│         Data Access Layer           │
│  (Repositories, Queries, DB)        │
└─────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Beautiful. Clean. Maintainable.

Then month 2 happens.

A component directly imports from the database layer "just this once."
A service calls another service that hasn't been created yet.
A utility function imports from the presentation layer.

Month 3? You don't have an architecture anymore. You have... spaghetti.

Why This Happens

SonarQube catches:

  • ✅ Code smells (naming, complexity, duplicates)
  • ✅ Bugs (null references, logic errors)
  • ✅ Security issues (SQL injection, XSS)
  • ❌ Architectural violations (layers crossed, bad imports)

Code Review catches:

  • ✅ Design decisions
  • ✅ Algorithm choice
  • ✅ Function complexity
  • ❌ Systematic architectural patterns (too slow to enforce manually)

The Gap:

  • 100 imports per PR
  • You check... maybe 5?
  • 95 could violate architecture
  • Human reviewer can't check them all

The Solution: architect-linter

Enter architect-linter. A linter specifically for architecture.

Think ESLint (which catches code style), but for your system design.

$ architect-linter-pro --check

❌ src/components/Button.tsx imports from src/api/user.ts
   Rule violation: Presentation layer cannot import from API layer
   Suggestion: Use src/services/UserService instead

❌ src/services/Auth.ts imports from src/components/LoginForm.tsx
   Rule violation: Service layer cannot import from Presentation layer

✅ Rest of architecture is clean
Enter fullscreen mode Exit fullscreen mode

How It Works

  1. Define rules in architect.json:
{
  "architecture_pattern": "Hexagonal",
  "forbidden_imports": [
    {
      "from": "src/presentation/**",
      "to": "src/infrastructure/**",
      "reason": "Presentation shouldn't depend on infrastructure details"
    },
    {
      "from": "src/application/**",
      "to": "src/infrastructure/**",
      "reason": "Application layer is infrastructure-agnostic"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode
  1. Run in CI/CD:
# .github/workflows/architecture.yml
- name: Check Architecture
  run: architect --check
Enter fullscreen mode Exit fullscreen mode
  1. Get violations before merge:
❌ PR blocked: Architecture violations detected
   - 2 violations found
   - Fix before merging
Enter fullscreen mode Exit fullscreen mode

Multi-Language Magic

Unlike ESLint (JS only) or Pylint (Python only), architect-linter works across 4 languages:

  • TypeScript/JavaScript (ES6 imports)
  • Python (import/from syntax)
  • PHP (use statements)
  • All in the same codebase

Perfect for monorepos with mixed stacks:

frontend/          (TypeScript + React)
backend/           (Python + FastAPI)
services/          (PHP + Laravel)
                   ↓
architect-linter enforces SAME rules across all 3
Enter fullscreen mode Exit fullscreen mode

Real Results

Before architect-linter:

  • ⚠️ 40% of PRs rejected for architecture
  • ⚠️ Code review took 30 minutes per PR
  • ⚠️ Junior devs didn't understand implicit rules
  • ⚠️ Architecture debt accumulated slowly

After architect-linter (2 months):

  • ✅ 5% of PRs rejected (mostly legitimate design changes)
  • ✅ Code review takes 5 minutes (humans focus on logic)
  • ✅ New devs self-correct with CI feedback
  • ✅ Zero new architectural violations

When to Use Each Tool

Need Tool Why
Catch bugs SonarQube Finds logic errors, security issues
Review logic Code Review Humans are best here
Enforce architecture architect-linter Automatic, systematic, consistent
All together All 3 SonarQube + architect-linter in CI, code review for design

Getting Started

Install

cargo install architect-linter-pro
Enter fullscreen mode Exit fullscreen mode

Initialize

architect-linter-pro --init
# Interactive wizard creates architect.json
Enter fullscreen mode Exit fullscreen mode

Run

architect-linter-pro --check
Enter fullscreen mode Exit fullscreen mode

CI/CD Integration

# GitHub Actions
- run: architect-linter-pro --check

# GitLab CI
script:
  - architect-linter-pro --check

# Pre-commit hook
# .pre-commit-config.yaml
- repo: https://github.com/sergiogswv/architect-linter-pro
  rev: v5.0.0
  hooks:
    - id: architect-linter-pro
Enter fullscreen mode Exit fullscreen mode

Comparison: architect-linter vs Alternatives

Feature architect-linter ESLint SonarQube Manual Review
Multi-language ✅ Yes ❌ JS only ✅ Yes ✅ Yes
Architecture rules ✅ Yes ❌ No ⚠️ Limited ✅ Yes
Fast ✅ Rust, parallel ✅ JS ❌ Slow ❌ Very slow
Free ✅ Open source ✅ Open source ❌ $10k+/year ✅ Yes
Easy setup ✅ 5 min ✅ 5 min ❌ 2 hours N/A
Automation level ✅ 100% ✅ 100% ✅ 90% ❌ 0%

Try It Now

cargo install architect-linter-pro
architect-linter-pro --init
architect-linter-pro --check
Enter fullscreen mode Exit fullscreen mode

Takes 5 minutes. Your architecture will thank you.


Questions?

Let me know what you think!