title: DDD validation without throwing exceptions
body: <p>I am attempting my first foray into DDD, and I asked a question about bulk imports <a href="https://stackoverflow.com/questions/43640256/importing-data-and-event-sourcing">here</a>, but I am going in circles trying to apply the validation for my domain model. </p>
  
  <p>Essentially I want to run through all the validation without throwing exceptions so that I can reject the command with all the validation errors via a list of CommandResult objects inside the Command object. Whilst some are just mandatory field checks which are configurable and so will be handled outside the aggregate, there are also business rules, so I don't want to duplicate the validation logic and don't want to fall into an anaemic model by moving everything outside the aggregate to maintain the always-valid mantra of entities.</p>
  
  <p>I am at a bit of a loss, so thought it be best I ask the experts if this I am going about things correctly before I start muddying the waters further! </p>
  
  <p>To try and demonstrate:</p>
  
  <p>Take the below, we have fairly simple UserProfile aggregate, the constructor takes the minimum information required for a profile to exist. </p>
  
  <pre><code> public class UserProfile : AggregateRoot
      {
          public Guid Id {get; private set; }
          public Name Name {get private set;}
          public CardDetail PaymentInformation {get; private set;}
  
  
  
        public UserProfile(Guid id, Name name, CardDetail paymentInformation)
          {
              Name = name;
              PaymentInformation = paymentInformation;
          }
  
      }
  
  public class CardDetail : ValueObject
  {
      public string Number {get; private set;}
      public string CVC {get; private set; }
      public DateTime? IssueDate {get; private set;}
      public DateTime ExpiryDate {get;private set;}
  
      public CardDetail(string number, string cvc, DateTime? issueDate, DateTime expiryDate)
      {
          if(!IsValidCardNumber(number))
          {
              /*Do something to say details invalid, but not throw exception, possibly?*/
          }
          Number = number;
          CVC = cvc;
          IssueDate = issueDate
  
  
  
          ExpiryDate = expiryDate;
  
      }
  
      private bool IsValidCardNumber(string number)
      {
          return Regex.IsMatch(/*regex for card number*/);
      }
  }
  </code></pre>
  
  <p>I then have a method which accepts a command object, which will construct a UserProfile and save to the database, but I want to validate before saving</p>
  
  <pre><code>public void CreateProfile(CreateProfileCommand command)
  {
      var paymentInformation = new CardDetail(command.CardNumber, command.CardCVC, command.CardIssueDate, command.CardExpiryDate)
  
      var errors = /* list of errors added to from card detail validation, possibly? */
  
      var profile = new UserProfile(/* pass args, add to errors? */
  
      if(errors.Any())
      {
          command.Results.Add(errors.Select(x =&gt; new CommandResult { Severity = Severity.Error, Message = x.Message });
          return;
      }
  
      /* no errors, so continue to save */
  
  }
  </code></pre>
  
  <p>Now, I could handle exceptions and add them to the command result, but that seems expensive and surely violates the rule of allowing exceptions to control flow? but on the other hand I want to keep entities and value object valid, so I find myself in a bit of a rut!</p>
  
  <p>Also, in the example above, the profile could be imported or done manually from a creation screen, but the user should get all error messages rather than each one in the order they occur. In the application I am working on, the rules applied are a bit more complex, but the idea is the same. I am aware that I shouldn't let a UI concern impact the domain as such, but I don't want to have to duplicate all validation twice more so that I can make sure the command won't fail as that will cause maintainability issues further down the line (the situation I find myself in and trying to resolve!)</p>