What is an accepted pattern for adding information to immutable types?

Viewed 49

I'm writing some code which works on a collection and adds more information to it. It starts with A, and then adds some more information, say it calculates the "expiry" of A and returns that. Then I calculate the allowed permissions based on the current user, and A and B, - and add this, call it C.

I started off using Tuples, but by the time I got to (E) the type definitions were unwieldy, and difficult to understand.

  1. Using Tuples:

     IEnumerable<A> CreateA();   
     IEnumerable<Tuple<A,B>> AddB(IEnumerable<A>);  
     IEnumerable<Tuple<A,B,C>> AddC(IEnumerable<A,B>);  
     etc..
    

I'm considering two options, creating types which represent the Tuples (option 2 below) which means you can't create C without having done A and B at compile time, or use a mutable object with a runtime check (option 3 below)

  1. Replace Tubles with distinct types

     class AB { ctor(A, B), A A{get;}, B B{get;} }  
     class ABC { ctor(A, B, C), A A{get;}, B B{get;}, C C{get;} }  
    
     IEnumerable<A> CreateA();  
     IEnumerable<AB> AddB(IEnumerable <A>)  
     IEnumerable<ABC> AddC(IEnumerable <AB>)  
     etc..
    
  2. Have a mutable type (with some runtime checks, eg B is null then throw...).

     class ABC { ctor(A), A A{get;}, B B{get;set;}, C C{get;set;} }
    
     IEnumerable<ABC>  CreateA();  
     IEnumerable<ABC>  AddB(IEnumerable<ABC>); //Sets B  
     IEnumerable<ABC>  AddC(IEnumerable<ABC>); //If B is null throw, set C  
    

Option 2 it looks a little alien, and creating and naming the types gets almost as unwieldy as option A. I'm getting the feeling I've wandered a bit off the beaten track.
I think more programmers would understand option 3.

Is there a standard accepted pattern for option 2 with a standardised naming strategy - or should I just give up on this and settle on option 3.

0 Answers
Related