If data storage could be a concern, then split the tables:
You can perform access either via a view (definition of the data location in the db) or via changing the ORM definition.
This is not the most performant (a join is involved), but it can present any combination of A/B/C/D over time without changing the underlying storage & depending on your real access patterns it may be sufficient.
You may not be fortunate with the ability to take downtime, restructure tables etc. in a production system.
Performing the access via the view allows you to switch from A/B/C to A/B/C/D to A/B/D in the underlying table with minimal change and no data movement.
A view will be transparent to the read logic and if your dbms supports either functions or updateable views then transparent to the write logic as well.
Really I think your decision will reflect lots of the real-world concerns:
1) what are datatypes C & D
2) the relative data volumes collected for C/D
3) Relative overlap of C/D data compared to purely C or D entries
4) Downtime/maintenance window availability and duration
5) DBMS Support for updateable views
6) Desirability of keeping db physical structure details in the ORM vs making it transparent by presenting via views/functions in the db (where it is the same for all accessing applications, not just the current one)
My answer preferred for large/complex datatypes for (1), little overlap for (3) and minimal downtime for (4), ideally with good dbms support in (5) and multiple applications accessing the data in (6)
But there is no right/wrong for lots of alternativeS:
- start with A/B/C, later add D, adjusting ORM, still later drop column C
- start with A/B/C/D & ignore nulls
I think, consider your solution & what you know of its intended purpose/lifecycle, do some size/volume modelling & expect to change things later as not everything will turn our as expected.