Modeling value object when fields’ existence depends on state of other fields

I am practicing tactical DDD and having trouble as exemplified below. Fundamentally, whether some fields of the value object should be nullable depends on another field of the same value object. Consider the following value object and enum (C#):

public class AdmissionQuotient
{
    private decimal? _quota1Gpa;
    private decimal? _standbyGpa;
    private Admission _admission;
}

public enum Admission
{
    Limited, // Some applicants were not admitted
    Ao, // All applicants were admitted
    Aolp // All applicants were admitted, and there are open positions 
}

For a particular education and a particular year, the GPAs describe the least GPA at which an applicant was admitted. Naturally, when all applicants were admitted, the GPAs do not make sense, and they will be null in the database. I do not like this design, since it either forces clients to be aware that the GPAs are only not null if _admission is Limited or forces forces clients to check the GPAs for null (when using their getters).

I have considered using inheritance instead of the enum. That is, LimitedAdmissionQuotient would extend AdmissionQuotient with the GPA fields. I have also considered using STATE (GoF) with a Concrete State for each enum value. Still, in both cases, the client would have to consider conceptually whether the admission is Limited, Ao, or Aolp.

Is there a way to model this that would mitigate null check propagation or type/enum check propagation?

3

Yes, but it’s usually not worth it. You need to implement operators for your class. ie add, subtract, isequal, gt, lt etc

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/operator-overloading

Now I don’t need to see the underling nullable decimals and enum, I can just add up/average/do whatever with all the AdmissionQuotient and your +/-/* operators will ignore or otherwise deal with the nulls.

Your example seems super esoteric, so lets use something more easy to understand like a TripleJumpResult.

In the triple jump athletics event contestants do a Hop, Skip and a Jump sequentially to try and travel the furthest. However if they trip of otherwise foul the result is not counted.

TripleJumpResult
{
   decimal? HopDist
   decimal? SkipDist   
   decimal? JumpDist
   JumpType type; //legal/foul enum
}

If a foul occurs any or all of these could be null.

We have a couple of use cases,

  1. given a set of results find who won the event
  2. given a set of results work out the average (legal) distance travelled

The nulls make these tasks hard, but if we implement >, + and divide we can do the calcs without null checks.

public static TripleJumpResult operator >(TripleJumpResult a, TripleJumpResult b)
{
    //check for any nulls in a
    //check for any nulls in b
    if(both null) { return false }
    if(a has nulls) { return false}
    if(b has nulls { return true }

    //alternatively check type enum for foul
    if(both foul) { return false }
    if(a is foul) { return false}
    if(b is foul) { return true }
    return (a.HopDist + a.SkipDist ... ) > (b.HopDist + ...)
}

Now I might expose the properties anyway, but users generally don’t need to look at them. You can say who won or what the average is without checking for fouls/nulls on each property because you can perform operations with the whole object which take these things into account

eg

var longestJump = jumps.First()
foreach(jump in jumps)
{
   if(jump > longestJump) { longestJump = jump} //no need to look at enum or check for nulls on distances
}

The reason I say that its not normally worth it, is that doing this means you need to know the operations you want to perform with the object in avance and assumes that those operations are well defined and work when combined and stuff.

This is great for maths, or areas with clear unchanging specification, but generally isn’t true for business rules.

If say one athletics body decides that foul jumps should have the distance for the legally completed parts count, but an other doesn’t, or the rules change for every season, well now I cant use the operation overloading without two sets of objects. It would be easier just to put the logic in the calling code.

5

Your question is somewhat hard to understand for me, since you talk about GPAs without explaining what that precisely means (I guess “grade point average”), then using the term “GPA” once for the real-world values (I guess), once for the variables _quota1Gpa and standbyGpa. Moreover, you did not explain the difference between _quota1Gpa and standbyGpa.

Still, let me make a guess on my limited understanding. I think the range of possible values for GPAs is the same as the range of possible grades. Where I live, it is usual to have grades from 1 to 6, where 1 is best and 6 is worst. So when you just need these GPA values as a limit which applicants were admitted and which not, set the limit to the lowest possible value. Then make the GPA variables non-nullable. That makes any null check superfluous.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật