0

Say I have a Domain Object, which represents a Customer with a list of Offers.

Say I want to add a collection of Offers. I believe I have two options:

Option 1

Have the Domain Object calculate the offers and then add them:

 public IEnumerable<IProduct> GetEligibleOffers(IOfferCalculator offerCalculator, IList<IProduct> products)
    {
        return offerCalculator.CalculateEligibility(Gender, Expenditure, products);
    }

    //Refactored this method.  
    public void AssignOffers(IList<IProduct> eligibleProducts)
    {
        foreach (var product in products)
        {
            _assignedProducts.Add(product);
        }
    }

Option 2

Have the Application Service calculate the offers and pass them to the Domain Object one by one. Therefore the domain object will look like this:

public IEnumerable<IProduct> GetEligibleOffers(IOfferCalculator offerCalculator, IList<IProduct> products)
        {
            return offerCalculator.CalculateEligibility(Gender, Expenditure, products);
        }

        //Refactored this method to only accept one product
        public void AddOffer(IProduct eligibleProduct)
        {
            _assignedProducts.Add(eligibleProduct);
        }

In this case; the application service gets the eligible offers (using: CalculateEligibility) and then passes them one by one to the domain object (Customer.AssignOffer).

I am trying to decide, which approach to use (I realise both approaches will work). Option one seems like the most appropriate. However, every example I can find online seems to use option 2 e.g. this one and this one. Therefore I wonder if option two is frowned upon for some reason.

6

First and foremost, don't overthink this - this is merely a matter of taste, nothing else. Remember, the generic List in C# offers an AddRange as well as an Add method for convenience (I am actually wondering why you did not use it in your first example), so there is nothing which hinders you to design your domain objects similar, with both methods, one for adding single objects, one for adding a collection. This is actually something I would recommend in case you want to design your domain objects to handle all collections in a uniform manner.

However, if you are not sure if you will ever need both methods, and uniformness is not your goal, just implement the method you need first, and when it later turns out you could use something like an AddRange more than once, you can still refactor and add another method afterwards.

  • Thanks for that. +1 for the reference to AddRange. I will rename the method and remove the for loop. – w0051977 Jan 28 '18 at 20:51
  • I don't need to remove offers at the moment. Therefore I don't have a remove method. Is it normal to leave the Remove method? Again every example I look at online has an add and a remove. – w0051977 Jan 28 '18 at 20:53
  • @w0051977: same as a above - don't overthink this; add "Remove" now if your goal is uniformness; if not, add it when you need it. – Doc Brown Jan 28 '18 at 21:08
  • Thanks. I guess I could add a remove method that accepts an Offer and the clear method, which empties the list? – w0051977 Jan 28 '18 at 21:11
  • 4
    @w0051977: whatever suits your requirements. Did I forget to say "don't overthink this"? ;-) – Doc Brown Jan 28 '18 at 21:57
1

As usual, it depends:-) The key is whether the offer is separated aggregate root. If it is, use Application Service as rule of thumb of aggregate root is not reference another entity directly, but use global id instead. Otherwise, use domain object.

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.