BlogJourney Notes

Modular Approaches in Software Architecture

Practical architecture notes for a sustainable codebase in large-scale industrial projects — module boundaries, data contracts, decision records, and test discipline.

  • 5 min read
Modular Approaches in Software Architecture
In This Article

In engineering software projects, a modular architecture raises both development speed and field reliability by making domain boundaries explicit. In CAD/CAM and automation products especially, the "one big monolith" approach looks fast in the short term but drives up maintenance cost over the medium term.

Modüler yazılım mimarisini temsil eden illüstrasyon
Modular components and dependency boundaries
01 / 07

Domain to software boundary

In fields such as prefab manufacturing, roll-form lines, or SolidWorks automation, software modules should be split along manufacturing reality: geometry processing, rule validation, output generation, licensing, and the user interface must be able to evolve independently of each other.

Domain knowledge sets the software boundary; AI tools are used as accelerators inside those boundaries.
02 / 07

Suggested module groups

  • Core: Geometry, parameter model, rule engine
  • Integration: CAD API, file I/O, ERP/MES bridges
  • Output: Drawings, DXF/DWG, production data
  • Platform: Licensing, logging, configuration, UI
03 / 07

Boundaries: where to cut

Cut modules by rate of change, not by technology. Things that change for the same reason at the same time belong together; things that change for different reasons come apart. On the CAD/CAM side, that produces a table like this:

ModuleWhen it changesWhat it may depend on
Geometry coreRarely — the maths does not moveNothing
Rule engineOften — as production standards shiftOnly the geometry core
CAD integrationAs the CAD version movesThe rule engine's output
Output generatorOn customer or line demandThe rule engine
Platform (licensing, logging)IndependentlyNo business module

The one-way rule here matters: no business module may call the platform module, and the platform must not know the business modules. The moment a licence check leaks into geometry code, testing that code requires a licence server — and the tests never get written.

04 / 07

Data contracts and versioning

The boundary between modules is a data contract, not a function signature. Keep the contract in an explicit type and version that type:

// Output of the rule engine — the CAD layer knows only this.
public sealed record PanelSpec(
    int SchemaVersion,          // incremented on a breaking change
    double WidthMm,
    double HeightMm,
    ProfileType Profile,
    IReadOnlyList<Opening> Openings);

Put the SchemaVersion field in from the start, even if it sits at 1 for the first release. Adding a field is not breaking; removing a field or changing its meaning is. On a breaking change, bumping the version and writing a converter for the old one is cheaper than having to update every consumer on the same day.

Keep the contract writable to disk (JSON/XML). A readable intermediate format is the most powerful debugging tool you have: a customer's "this job doesn't work" message reduces to a single file.
Teknik ekip iş akışını temsil eden illüstrasyon
Team workflow and module ownership
05 / 07

Decision records: don't bury the why

The most expensive knowledge loss in engineering software is forgetting the reasoning behind a decision. A team that cannot answer "why is this profile calculation like this?" six months later will either leave the code untouched or fix it wrongly.

No heavy process is needed. Short notes under docs/decisions/ in the repository, one page per decision, are enough:

  1. Context — which constraint forced this decision (line tolerance, CAD API limit, customer standard)
  2. Decision — what was decided
  3. Consequence — what it makes easier, what it makes harder
  4. Rejected alternatives — and why they were rejected

The fourth item is the most valuable; it stops the same alternative being proposed again a year later.

Test discipline: what gets tested where

  • Geometry core — pure unit tests. With no dependencies, these are the cheapest and fastest tests; coverage should be highest here.
  • Rule engine — scenario tests. Freeze real production cases as input/expected-output pairs; when a standard changes you see immediately which cases moved.
  • CAD integration — a small number of smoke tests against a real CAD session. Expensive, hence few — but never zero.
  • Output generator — snapshot tests. The produced DXF need not be byte-identical, but layer names and dimensions must stay fixed.
Kod inceleme ve kalite sürecini temsil eden illüstrasyon
Code review and quality gates
06 / 07

Module ownership in AI-assisted development

AI tools work markedly better in a modular architecture, for a simple reason: a module with a clear boundary fits in the model's context window. In return I set two rules:

  • Boundaries stay human. I decide what a module will and will not do, the shape of the contract, and the direction of dependency. If those decisions are wrong, fast-generated code multiplies the mistake quickly.
  • No AI in a module without a contract test. If there is no mechanism to verify the generated code, the speed you gain comes straight back as risk.

In practice I get the best results in modules whose inputs and outputs are pure, such as the geometry core; the worst in layers that talk to the CAD API and carry state.

07 / 07

Measure when moving to production

In a pilot → limited users → full roll-out flow, record the same three numbers at every stage: preparation time, error rate, and output consistency. Numerical claims should be supported only by that record — "it got much faster" is not an engineering claim.

İlgili projeHafif Çelik CAD/CAMHafif çelik yapı sistemleri için CAD/CAM, üretim otomasyonu ve modern C#/.NET mimarisini birleştiren bağımsız mühendislik yazılımı projesi.