Skip to content
architecture-reviewer logo

Architecture Reviewer

architecture-reviewer

Review code against PRISM target architecture patterns from REFACTORING_DESIGN_DOCUMENT.md. This skill should be used during refactoring to ensure new Runner and Trainer classes follow AbstractRunner/AbstractTrainer patterns.

mattnigh/skills_collection0installs24stars

SKILL.md

Full skill instructions

Architecture Reviewer

Review code against PRISM's target architecture patterns to ensure consistency with the refactoring design.

Purpose

This skill validates that new and refactored code follows PRISM's architectural patterns, specifically the Template Method pattern for Runners and the Strategy pattern for Trainers.

When to Use

Use this skill when:

  • Creating new Runner classes (PRISMRunner, MoPIERunner)
  • Creating new Trainer classes (ProgressiveTrainer, EpochalTrainer)
  • Refactoring existing procedural code to object-oriented patterns
  • Verifying Template Method pattern implementation
  • Checking Strategy pattern usage
  • Reviewing pull requests that modify core architecture

Target Architecture Patterns

Pattern 1: AbstractRunner (Template Method)

The Template Method pattern defines a skeleton workflow with customizable hooks:

from abc import ABC, abstractmethod
from dataclasses import dataclass
from pathlib import Path
from typing import Optional
import torch
from torch.utils.tensorboard import SummaryWriter

@dataclass
class ExperimentResult:
    """Result of an experiment run."""
    ssims: list[float]
    psnrs: list[float]
    rmses: list[float]
    final_reconstruction: torch.Tensor
    log_dir: Path
    elapsed_time: float

class AbstractRunner(ABC):
    """Abstract base class for experiment runners.

    Implements Template Method pattern: run() defines the workflow,
    subclasses implement hook methods.
    """

    def __init__(self, args):
        self.args = args
        self.config = None
        self.device = None
        self.log_dir = None
        self.writer: Optional[SummaryWriter] = None

    def run(self) -> ExperimentResult:
        """Template method - DO NOT OVERRIDE in subclasses."""
        self.setup()              # Hook 1: Environment setup
        self.load_data()          # Hook 2: Load image/​pattern
        self.create_components()  # Hook 3: Create model/​trainer
        result = self.run_experiment()  # Hook 4: Run training
        self.save_results(result) # Hook 5: Save outputs
        self.cleanup()            # Hook 6: Resource cleanup
        return result

    @abstractmethod
    def setup(self) -> None:
        """Hook 1: Set up device, logging, directories."""
        ...

    @abstractmethod
    def load_data(self) -> None:
        """Hook 2: Load image and generate pattern."""
        ...

    @abstractmethod
    def create_components(self) -> None:
        """Hook 3: Create model, telescope, trainer."""
        ...

    @abstractmethod
    def run_experiment(self) -> ExperimentResult:
        """Hook 4: Run training and return results."""
        ...

    @abstractmethod
    def save_results(self, result: ExperimentResult) -> None:
        """Hook 5: Save checkpoint and visualizations."""
        ...

    def cleanup(self) -> None:
        """Hook 6: Cleanup (default implementation)."""
        if self.writer:
            self.writer.close()

Pattern 2: AbstractTrainer (Strategy Pattern)

The Strategy pattern allows interchangeable training algorithms:

from abc import ABC, abstractmethod
from dataclasses import dataclass
import torch
from torch import nn, Tensor

@dataclass
class TrainingResult:
    """Final training result."""
    ssims: list[float]
    psnrs: list[float]
    rmses: list[float]
    final_reconstruction: Tensor
    total_time: float
    converged: bool

class AbstractTrainer(ABC):
    """Abstract base class for training strategies."""

    def __init__(
        self,
        model: nn.Module,
        device: torch.device,
        config: 'TrainingConfig'
    ):
        self.model = model
        self.device = device
        self.config = config

    @abstractmethod
    def train(self) -> TrainingResult:
        """Main training loop - must be implemented."""
        ...

    @abstractmethod
    def train_step(self, batch_idx: int) -> dict:
        """Single training step - must be implemented."""
        ...

    def compute_metrics(self) -> tuple[float, float, float]:
        """Compute RMSE, SSIM, PSNR (can be overridden)."""
        return self.model.errors()

    def should_stop(self) -> bool:
        """Early stopping check (can be overridden)."""
        return False

    def save_checkpoint(self, path: Path) -> None:
        """Save checkpoint (can be overridden)."""
        torch.save({
            'model_state': self.model.state_dict(),
            'config': self.config,
        }, path)

Pattern 3: Concrete Runner Example

class PRISMRunner(AbstractRunner):
    """Runner for PRISM algorithm."""

    def setup(self) -> None:
        self.device = setup_device(self.args)
        self.config = load_config(self.args)
        self.log_dir = Path(self.args.log_dir) / self.args.name
        self.writer = SummaryWriter(self.log_dir)

    def load_data(self) -> None:
        self.image = load_image(self.args.obj_name).to(self.device)
        self.centers = generate_pattern(self.args, self.config)

    def create_components(self) -> None:
        self.telescope = Telescope(...).to(self.device)
        self.model = ProgressiveDecoder(...).to(self.device)
        self.trainer = ProgressiveTrainer(self.model, ...)

    def run_experiment(self) -> ExperimentResult:
        result = self.trainer.train()
        return ExperimentResult(
            ssims=result.ssims,
            psnrs=result.psnrs,
            rmses=result.rmses,
            final_reconstruction=result.final_reconstruction,
            log_dir=self.log_dir,
            elapsed_time=result.total_time
        )

    def save_results(self, result: ExperimentResult) -> None:
        save_checkpoint(self.model, self.log_dir / 'checkpoint.pt')
        create_visualization(result, self.log_dir)

Architecture Review Checklist

For AbstractRunner Subclasses

  • Inheritance: Class inherits from AbstractRunner
  • Constructor: Calls super().__init__(args) first
  • Template Method: Does NOT override run()
  • Hook Implementations:
    • setup(): Sets device, config, log_dir, writer
    • load_data(): Loads image and pattern only
    • create_components(): Creates model, telescope, trainer
    • run_experiment(): Calls trainer.train(), returns ExperimentResult
    • save_results(): Saves checkpoint and visualizations
  • Separation of Concerns: Each hook does one thing
  • Type Hints: All methods have proper annotations
  • Docstrings: All methods documented

For AbstractTrainer Subclasses

  • Inheritance: Class inherits from AbstractTrainer
  • Constructor: Calls super().__init__(model, device, config)
  • Required Methods:
    • train(): Returns TrainingResult
    • train_step(): Single step logic
  • Metrics: Uses SSIM, PSNR, RMSE consistently
  • Checkpointing: Supports save_checkpoint()
  • Type Hints: All methods properly typed

General Code Quality

  • Naming:
    • Runners end with "Runner" (PRISMRunner, MoPIERunner)
    • Trainers end with "Trainer" (ProgressiveTrainer, EpochalTrainer)
    • Methods use snake_case
    • Classes use PascalCase
  • No God Functions: Methods < 50 lines
  • No Hardcoded Values: Use config or parameters
  • Testability: Components can be instantiated independently

Anti-Patterns to Avoid

Anti-Pattern 1: Overriding Template Method

# BAD - Don't override run()
class MyRunner(AbstractRunner):
    def run(self) -> ExperimentResult:  # DON'T DO THIS
        # Custom implementation
        ...

Anti-Pattern 2: Mixing Concerns

# BAD - setup() doing too much
def setup(self) -> None:
    self.device = setup_device(self.args)
    self.image = load_image(...)  # This belongs in load_data()!
    self.model = create_model(...)  # This belongs in create_components()!

Anti-Pattern 3: Trainer Doing Visualization

# BAD - Trainer shouldn't handle visualization
class MyTrainer(AbstractTrainer):
    def train(self) -> TrainingResult:
        result = self._train_loop()
        self._create_plots()  # This belongs in Runner.save_results()!
        return result

Anti-Pattern 4: No Abstraction

# BAD - Doesn't use abstract base
class MoPIERunner:  # Should inherit from AbstractRunner!
    def run(self):
        # Duplicate implementation
        ...

Anti-Pattern 5: Hardcoded Paths

# BAD
def save_results(self, result):
    torch.save(model, '/​tmp/​checkpoint.pth')  # Use self.log_dir!

Review Workflow

Step 1: Check Inheritance

# Verify proper inheritance
assert issubclass(MyRunner, AbstractRunner)
assert issubclass(MyTrainer, AbstractTrainer)

Step 2: Check Hook Implementations

# Verify all abstract methods are implemented
required_runner_methods = ['setup', 'load_data', 'create_components',
                           'run_experiment', 'save_results']
for method in required_runner_methods:
    assert hasattr(MyRunner, method)
    assert callable(getattr(MyRunner, method))

Step 3: Check Method Signatures

# Verify return types
import inspect
sig = inspect.signature(MyRunner.run_experiment)
assert sig.return_annotation == ExperimentResult

Step 4: Check for Anti-Patterns

  • Search for def run(self) in Runner subclasses (shouldn't exist)
  • Check that hooks don't overlap in functionality
  • Verify no visualization code in Trainers

Example Review Comments

Good Implementation

✅ Excellent! PRISMRunner correctly implements AbstractRunner pattern. All hooks are focused and follow single responsibility. Type hints and docstrings are complete.

Needs Improvement

❌ Issues found in MoPIERunner:

  1. Doesn't inherit from AbstractRunner
  2. setup() loads data (should be in load_data())
  3. Missing type hints on run_experiment()

Recommendation: Refactor to follow AbstractRunner pattern.

Quick Reference

Runner Template

AbstractRunner.run():
  1. setup()           → Device, config, logging
  2. load_data()       → Image, pattern
  3. create_components() → Model, telescope, trainer
  4. run_experiment()  → Training loop
  5. save_results()    → Checkpoint, visualization
  6. cleanup()         → Resource cleanup

Trainer Template

AbstractTrainer.train():
  Loop:
    1. train_step()      → Process batch
    2. compute_metrics() → RMSE, SSIM, PSNR
    3. should_stop()     → Early stopping
  Return TrainingResult

Related Skills

  • type-hint-adder: Add type hints to Runner/​Trainer classes
  • unit-test-generator: Create architecture compliance tests
  • docstring-formatter: Document patterns in code

Checklist Before Merge

  • All checklist items verified
  • No anti-patterns detected
  • Follows naming conventions
  • Properly typed and documented
  • Consistent with existing patterns
  • Tests pass

More skills from mattnigh

spring-framework-patterns logo
mattnigh/skills_collection

spring-framework-patterns

Comprehensive Spring Framework and Spring Boot best practices including dependency injection patterns, bean lifecycle and scopes, REST API development, Spring Data JPA, service layer design, Spring Security, testing strategies, caching, AOP, async processing, error handling, and common anti-patte...

24 0
View

TypeScript厳格モードによる型安全性設計を専門とするスキル。 📖 参照書籍: - 『Effective TypeScript』(Dan Vanderkam): 型設計 📚 リソース参照: - `resources/Level1_basics.md`: レベル1の基礎ガイド - `resources/Level2_intermediate.md`: レベル2の実務ガイド - `resources/Level3_advanced.md`: レベル3の応用ガイド - `resources/Level4_expert.md`: レベル4の専門ガイド - `resources/di...

24 0
View
deploying-cloud-k8s logo
mattnigh/skills_collection

deploying-cloud-k8s

Deploys applications to cloud Kubernetes (AKS/GKE/DOKS) with CI/CD pipelines. Use when deploying to production, setting up GitHub Actions, troubleshooting deployments. Covers build-time vs runtime vars, architecture matching, and battle-tested debugging.

24 0
View
moai-alfred-agent-guide logo
mattnigh/skills_collection

moai-alfred-agent-guide

19-agent team structure, decision trees for agent selection, Haiku vs Sonnet model selection, and agent collaboration principles. Use when deciding which sub-agent to invoke, understanding team responsibilities, or learning multi-agent orchestration.

24 0
View
mermaid-diagram-generator logo
mattnigh/skills_collection

mermaid-diagram-generator

Converts architecture descriptions, module specs, or workflow docs into Mermaid diagrams. Use when visualizing brick module relationships, workflows (DDD, investigation), or system architecture. Supports: flowcharts, sequence diagrams, class diagrams, state machines, entity relationship diagrams,...

24 0
View
pre-flight-check logo
mattnigh/skills_collection

pre-flight-check

INVOKE FIRST before any code work. Validates git workflow (branch, issue, worklog) and checks approach. Use at START of every task and END before completing. Prevents skipped steps.

24 0
View
browser-dev-tools logo
mattnigh/skills_collection

browser-dev-tools

This skill should be used when working with browser-rendered artifacts (i.e. Bun, React/React Native) to proactively validate that development work on localhost is being built appropriately and to support debugging browser-rendered content. Use this skill after making frontend changes to verify t...

24 0
View
lead-dev logo
mattnigh/skills_collection

lead-dev

Lead Développeur - Coordination technique opérationnelle, code review, mentoring et livraison. Pair de web-dev-process au niveau OPÉRATIONS.

24 0
View
worker-monitor logo
mattnigh/skills_collection

worker-monitor

Monitor Docker workers, RQ queue health, and auto-scale workers (max 4). Use when: checking job progress, monitoring queue depth, scaling workers up/down, diagnosing slow processing, or waiting for jobs to complete. Referenced by data-quality skill during reprocessing.

24 0
View
quality-advisor logo
mattnigh/skills_collection

quality-advisor

Proactive quality guidance system that monitors artifact creation and provides real-time feedback on documentation quality

24 0
View
bump-version logo
mattnigh/skills_collection

bump-version

This skill should be used when the user wants to bump the version number in the workspace. It updates versions across all pyproject.toml files (root, tde, and tda packages) and the CHANGELOG.md to keep them synchronized.

24 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View