views:

84

answers:

1

In the system I'm currently working on, I'm following SRP (I think!) by separating the validation of domain business rules vs persistence constraints. Let's employ the overused customer example. Say a customer must have a valid zip code, street address and name to satisfy the system's business rules. Let's further say that the customer's selected user name must be unique across all customers, which I define as a persistence constraint. Please consider the following "not ready for production" pseudo code:

public interface IPersistenceValidator<T>
{
    bool IsValidForPersistence(T domainObj, IList<ValidationError> validationErrors);
}

public interface IValidatable
{
    bool IsValid(IList<ValidationError> validationErrors);
}

public class Customer : IValidatable
{
    public bool IsValid(IList<ValidationError> validationErrors)
    {
        //check for business rule compliance
    }
}

public class CustomerDao : IPersistenceValidator<Customer>
{
    public bool IsValidForPersistence(Customer domainObj, IList<ValidationError> validationErrors)
    {
        //check for persistence constraint compliance (user name is unique)
    }

    public bool SaveCustomer(Customer customer)
    {
        //save customer
    }
}

The classes defined above might get wired up into a service class as follows:

   public class SaveCustomerService
    {
        private CustomerDao _customerDao;

        public SaveCustomerService(CustomerDao customerDao)
        {
            _customerDao = customerDao;
        }

        public bool SaveCustomer(Customer customer)
        {
            IList<ValidationError> validationErrors = new List<ValidationError>();
            if (customer.IsValid(validationErrors))
            {
                if (_customerDao.IsValidForPersistence(customer, validationErrors))
                {
                    return _customerDao.SaveCustomer(customer);
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
    }

My primary concern with this approach is that future consumers of CustomerDao must know to call IsValidForPersistence() before SaveCustomer(), otherwise invalid data gets persisted. I could create DB constraints to guard against this at the SQL levels, but that feels like a kludge.

It seems like IsValidForPersistence() should be moved into CustomerDao.SaveCustomer() but then I have to refactor the signature of SaveCustomer() to include references to the ValidationErrors class. Before I dive into that big of a refactoring, I wanted to get some feedback from others on common/preffered patterns for dealing with these issues.

Thanks

A: 
  • first check HERE if you want to solve your validation problem like;

    public class Address {
    
    
    
    @NotNull private String line1;
    private String line2;
    private String zip;
    private String state;
    
    
    @Length(max = 20)
    @NotNull
    private String country;
    
    
    @Range(min = -2, max = 50, message = "Floor out of range")
    public int floor;
    
    
        ...
    

    }

    anyway you must check username in database. You can customize your validation (like go and check DB for that is unique). Look at another links to detail.

  • Check hibernate validator
  • Check Using the Validator framework from jboss
  • You can read Validation In The Domain Layer partI, partII, this is not java but logic is important.
javaloper