4

Please see the code below:

public List<DenominationDTO> CalculateChange(
        decimal cost, 
        decimal paymentReceived, 
        string currencySymbol)
{
    var currency = CurrencyFactory.Create(currencySymbol);
    var denomination = DenominationFactory.Create(0,0);
    DenominationsCalculator = DenominationsCalculatorFactory.Create(
        currency, 
        denomination, 
        cost, 
        paymentReceived);
    return Mapper.Map<List<DenominationDTO>>(
        DenominationsCalculator.GetDenominations().ToList());
}

DenominationFactory is used to create an instance of an immutable value class. Immutable classes should not have a zero argument constructor based on what I have read. If they could have a single valued constructor, then I could just inject the class that is created by DenominationFactory into the constructor of the class that contains CalculateChange.

Can an immutable class have a zero argument constructor? According to this link it should not: https://www.codeproject.com/Articles/1043301/Immutable-objects-in-Csharp

I am talking strictly from a best practice perspective using DDD and a Rich Domain Model.

  • 7
    Yes an immutable class can have a zero-argument constructor. Whether it should is a different question, since it means the class is either empty or fetches the initial value from some static object, which might be considered a bad design. – JacquesB Jun 14 '17 at 13:24
5

The article you link to doesn't say "you should not have a zero argument constructor" it says "provide parameters via constructor."

A zero-argument constructor indicates a few possibilities:

  1. Class has no dependencies
    1. It may only have stateless methods
    2. It may only be contributing a name. I've seen this work with exceptions.
  2. Class has default values
    1. There may be another constructor that allows for overriding those default values
    2. Like enums, there might be other classes that implement the same interface with different default values
    3. The default values are simply hard coded and you're stuck with them

It's 2.3 that causes the real problems. All of these can be immutable.

  • I don't follow the logic of 1.1: if all the methods are stateless, I'd make it a static class. However, 2.1 is a good example and worth +1. Also there are exceptions to 2.3, such as "value singletons" like none for maybe types. Overall though, a good answer IMO. :) – David Arno Jun 14 '17 at 14:20
  • @DavidArno Re 1.1, you sometimes do need an instance to pass around. A C# static class is then not sufficient. One example is the strategy pattern where the you only use the object for dynamic dispatch, and not necessarily to store any data. – amon Jun 14 '17 at 14:52
  • @amon, Really? People still use instances of classes to implement the strategy pattern?!?? Even Java now supports lambdas and method references and C# has offered Func<...> and Action<...> for years. Time to put down that patterns book and write some modern code, methinks. – David Arno Jun 14 '17 at 14:57
  • @DavidArno Good point, lambdas are usually better. But lambdas can't replace a Strategy in all cases: if the it owns associated data, if the it supplies multiple related methods, or if having a particular (named) type is important. All of those reasons also apply to C#. Additionally, languages like Java and C++ have very noticeable restrictions on lambdas. And there are plenty other potentially stateless GoF patterns like Abstract Factories or Visitors for which I'm not aware of language-level alternatives (DI context? C# 7 Switch/case type patterns? Sometimes, but not always suitable.) – amon Jun 14 '17 at 15:28
  • 1
    Of course this doesn't mean I won't dump a bunch of lambdas in a hashset when the mood strikes me. Just don't ask me to use stacks of inheritance. I'm SO over that. – candied_orange Jun 14 '17 at 20:27
2

Yes.

Especially in languages like Java or C#, strategy implementations for example can have nullary constructors because the meat of their implementation is some function that satisfies an interface. Languages without enum support also tend to do this to emulate enums.

It's perhaps debatable if classes with no values should be considered immutable, or if it's good DDD. I'd say it is, since you're following the design goals and get the benefits of immutability while having an empty constructor.

  • The only reason I require an empty constructor is for IOC (Castle Windsor). – w0051977 Jun 14 '17 at 13:40
  • 3
    @w0051977 If your IOC container is injecting through any other means than the constructor, how can they be immutable? – JimmyJames Jun 14 '17 at 13:45
  • @w0051977 Why does Castle Windsor require a parameterless constructor? – Ben Aaronson Jun 14 '17 at 17:21
0

Depends what you mean by "zero argument constructor" (are private non-zero argument constructors allowed or not?) and whether you allow access to static global variables (such as DateTime.UtcNow).

If you really mean no zero argument constructors (including private) and forbid access to static global variables and require immutability, then I claim that your object cannot hold any non-constant data, only behaviour (e.g., strategy pattern, as others mentioned). One could argue, though, whether instances of that class can be called "objects", since their behaviour are just static functions/methods that do not operate on "state".

I'm adding two examples to the list in case any of the other two methods are allowed, because I think it's a very interesting question:

  • A timestamp object that records the time of its creation (say, via accessing some global static time service) but is otherwise immutable.

  • a Pseudo Random Number Generator that starts at a well-defined seed and returns the next number, like this:

public class PRNG {
  public long Value { get; }
  public PRNG() {
    Value = 12345; // seed
  }
  private PRNG(long value) {
    Value = value;
  }
  public PRNG Next() {
    return new PRNG(PRNG_Algorithm_NextVal_For(Value));
  }
}
-3

Some DDD best practices state that a Value object should be immutable but it does not specify how this should be implemented.

How it is implemented depends a lot on the programming language and DDD is language agmostic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.