1.7 KiB
Property is the aggregate root, not EpcPropertyData
The Ara modelling pipeline produces nine slices of per-property data (EPC, geospatial, solar, baseline performance, recommendations, optimised package, etc.). We considered making EpcPropertyData — the rich RdSAP-21-style EPC schema — the centrepiece, with other data hanging off it. We rejected that and introduced a new Property aggregate root that holds identity, all source data (EPC, Site Notes, Landlord Overrides), enrichments, and modelling outputs as named fields. Services take Property (or Properties) and return them with one slice populated.
Two reasons drove this:
- Geospatial, solar, recommendations, and overrides are peers to the EPC, not properties of it. Putting them on
EpcPropertyDataconflates physical-state schema with modelling-run state. - A typed
ModellingContextdict-bag (the obvious alternative) is exactly what the current legacyPropertyclass became — 1259 lines of accumulated stuff, hard to read, hard to test, hard to extend. Named fields on a dataclass force the type system to keep us honest.
The cost is more domain types up front (Property, Properties, PropertyIdentity, BaselinePerformance, OptimisedPackage, etc.) and the discipline of one service writing one slice. The benefit is that every service has a single job and every test injects fake repos against a small, named structure.
Consequences
- Every service signature accepts or returns
Property/Properties. Refactoring later means touching all of them. EpcPropertyDatastays a pure physical-state schema (defined in datatypes/epc/domain/epc_property_data.py) — no modelling outputs or run state on it.