2 added 171 characters in body
source | link

OK So! here is my understanding of your approach

  1. In your domain you have a special value type eg. Currency In Denominations
  2. You want to prevent the construction of a value type that would be impossible by definition, ie half a 10p piece.
  3. You are modeling value types as immutable reference types. rather than using value types. Because of reasons.
  4. Some of the information required to validate the 'value type' is contained in another class. eg the possible denominations of a particular currency.

Bad things:

  1. Throwing in constructors is generally bad. The exception to the rule is impossible value types eg 31st of Feb
  2. All of your examples could be refactored to do the validation in a method rather than a constructor.

If you are married to your way of doing things, then you have no alternative to your current solution. Yes it seems slightly odd, but it is functional.

If you want a solution where you don't have that particular combination of validation, why not get rid of the constructor exceptions completely?

public class ImmutableListOfCoins 
{
    private IEnumerable<KeyValuePair<decimal, int>>uint>> listOfCoins {get; private set;}
    public ImmutableListOfCoins(IEnumerable<KeyValuePair<decimal, int>>uint>> listOfCoins) 
    {
         ....
    }
}

public static ImmutableListOfCoins CalculateDenominations(decimal cost)
    {
        var target = _cost;
        if (decimal.Round(cost, currency.DecimalPlaces) != cost)
        {
            throw new ArgumentException("Cost has too many decimal places.");
        }
        var loc = new Dictionary<decimal,int>uint>();

        foreach (var denomination in _currency.AvailableDenominations)
        {
            var numberRequired = target / denomination;
            if (numberRequired >= 1)
            {
                intvar quantity = (intuint)Math.Floor(numberRequired);
                loc.Add(new KeyValuePair<decimal, int>uint>(denomination, quantity));
                target = target - (quantity * denomination);
            }
        }
        return new ImmutableListOfCoins(loc);
    }

OK So! here is my understanding of your approach

  1. In your domain you have a special value type eg. Currency In Denominations
  2. You want to prevent the construction of a value type that would be impossible by definition, ie half a 10p piece.
  3. You are modeling value types as immutable reference types. rather than using value types. Because of reasons.
  4. Some of the information required to validate the 'value type' is contained in another class. eg the possible denominations of a particular currency.

Bad things:

  1. Throwing in constructors is generally bad. The exception to the rule is impossible value types eg 31st of Feb
  2. All of your examples could be refactored to do the validation in a method rather than a constructor.

If you are married to your way of doing things, then you have no alternative to your current solution. Yes it seems slightly odd, but it is functional.

If you want a solution where you don't have that particular combination of validation, why not get rid of the constructor exceptions completely?

public class ImmutableListOfCoins 
{
    private IEnumerable<KeyValuePair<decimal, int>> listOfCoins {get; private set;}
    public ImmutableListOfCoins(IEnumerable<KeyValuePair<decimal, int>> listOfCoins) {...}
}

public static ImmutableListOfCoins CalculateDenominations(decimal cost)
    {
        var target = _cost;
        if (decimal.Round(cost, currency.DecimalPlaces) != cost)
        {
            throw new ArgumentException("Cost has too many decimal places.");
        }
        var loc = new Dictionary<decimal,int>();

        foreach (var denomination in _currency.AvailableDenominations)
        {
            var numberRequired = target / denomination;
            if (numberRequired >= 1)
            {
                int quantity = (int)Math.Floor(numberRequired);
                loc.Add(new KeyValuePair<decimal, int>(denomination, quantity));
                target = target - (quantity * denomination);
            }
        }
        return new ImmutableListOfCoins(loc);
    }

OK So! here is my understanding of your approach

  1. In your domain you have a special value type eg. Currency In Denominations
  2. You want to prevent the construction of a value type that would be impossible by definition, ie half a 10p piece.
  3. You are modeling value types as immutable reference types. rather than using value types. Because of reasons.
  4. Some of the information required to validate the 'value type' is contained in another class. eg the possible denominations of a particular currency.

Bad things:

  1. Throwing in constructors is generally bad. The exception to the rule is impossible value types eg 31st of Feb
  2. All of your examples could be refactored to do the validation in a method rather than a constructor.

If you are married to your way of doing things, then you have no alternative to your current solution. Yes it seems slightly odd, but it is functional.

If you want a solution where you don't have that particular combination of validation, why not get rid of the constructor exceptions completely?

public class ImmutableListOfCoins 
{
    private IEnumerable<KeyValuePair<decimal, uint>> listOfCoins {get; private set;}
    public ImmutableListOfCoins(IEnumerable<KeyValuePair<decimal, uint>> listOfCoins) 
    {
         ....
    }
}

public static ImmutableListOfCoins CalculateDenominations(decimal cost)
    {
        var target = _cost;
        if (decimal.Round(cost, currency.DecimalPlaces) != cost)
        {
            throw new ArgumentException("Cost has too many decimal places.");
        }
        var loc = new Dictionary<decimal,uint>();

        foreach (var denomination in _currency.AvailableDenominations)
        {
            var numberRequired = target / denomination;
            if (numberRequired >= 1)
            {
                var quantity = (uint)Math.Floor(numberRequired);
                loc.Add(new KeyValuePair<decimal, uint>(denomination, quantity));
                target = target - (quantity * denomination);
            }
        }
        return new ImmutableListOfCoins(loc);
    }
1
source | link

OK So! here is my understanding of your approach

  1. In your domain you have a special value type eg. Currency In Denominations
  2. You want to prevent the construction of a value type that would be impossible by definition, ie half a 10p piece.
  3. You are modeling value types as immutable reference types. rather than using value types. Because of reasons.
  4. Some of the information required to validate the 'value type' is contained in another class. eg the possible denominations of a particular currency.

Bad things:

  1. Throwing in constructors is generally bad. The exception to the rule is impossible value types eg 31st of Feb
  2. All of your examples could be refactored to do the validation in a method rather than a constructor.

If you are married to your way of doing things, then you have no alternative to your current solution. Yes it seems slightly odd, but it is functional.

If you want a solution where you don't have that particular combination of validation, why not get rid of the constructor exceptions completely?

public class ImmutableListOfCoins 
{
    private IEnumerable<KeyValuePair<decimal, int>> listOfCoins {get; private set;}
    public ImmutableListOfCoins(IEnumerable<KeyValuePair<decimal, int>> listOfCoins) {...}
}

public static ImmutableListOfCoins CalculateDenominations(decimal cost)
    {
        var target = _cost;
        if (decimal.Round(cost, currency.DecimalPlaces) != cost)
        {
            throw new ArgumentException("Cost has too many decimal places.");
        }
        var loc = new Dictionary<decimal,int>();

        foreach (var denomination in _currency.AvailableDenominations)
        {
            var numberRequired = target / denomination;
            if (numberRequired >= 1)
            {
                int quantity = (int)Math.Floor(numberRequired);
                loc.Add(new KeyValuePair<decimal, int>(denomination, quantity));
                target = target - (quantity * denomination);
            }
        }
        return new ImmutableListOfCoins(loc);
    }