adam bien's blog

A Package per Feature 📎

A feature request never arrives as "change all DTOs", it arrives as "implement support for NVIDIA Nemotron". Such a requirement lands in one main responsibility, with minor adjustments rippling into a few neighboring ones. Code organized by responsibility makes this visible: the package names tell you where the work happens and what gets touched as collateral. This is the idea behind the Business Component (BC): a package named after a responsibility, not a technology.

lightmetal, a zero-dependency Java 25 CLI application for GPU LLM inference on Apple Silicon, is structured this way. Every direct child of the lm package is a BC:

lm
├── catalog
├── configuration
├── generation
├── prompting
├── sampling
└── tokenization

Reading the package names tells you what the application does. No services, no utils, no helpers.

Inside, every BC follows the same convention from the BCE (Boundary-Control-Entity) pattern: up to three layers named boundary, control, and entity. The pattern goes back to Ivar Jacobson's use-case-driven OOSE from 1992, and the layer names have stayed stable for over three decades, while the industry cycled through DAOs, DTOs, Managers, Services, and Repositories.

See bce.design for the pattern and sbce.dev for the spec-driven workflow built on it.