Enforcing the rules of your dataintermediate
A cart that can hold the same product twice, or a quantity that can go to zero, is a bug you will chase through the UI forever — the rules belong in the data layer.
A subscription service reaches into a payment provider’s JSON — txn_st_v3, ch_ident_key, resp_cd — and decides business outcomes from it. Put an adapter and a domain model between them so swapping provider is a new class, not a rewrite.
See alsoThe vendor’s field names, everywhereThe same boundary in JavaScript, without an interface to hang it on.
A second provider is a second adapter, and no existing business code changes.
Published in full, before you start — every point is one of these and there is nothing else.
A cart that can hold the same product twice, or a quantity that can go to zero, is a bug you will chase through the UI forever — the rules belong in the data layer.
A vertical slice keeps one feature — its endpoint, its validation, its data access — in one folder, so changing checkout means opening one place instead of four layers.