Take the example below:
Suppose I want to create an instance from the Client class and that clients must have a name and an address (there may be more information but lets stay with those two data for simplification purposes).
So, this could be instantiated like: (C# code)
// Open database connection (and Begin Transaction)
SessionManager.Open( );
: : :
// Parameters are: name, zipcode, adress number, address complement, country
Client client = new Client(“New Client”,”12500”,12,“Room 14”,Country.US);
: : :
// Close database connection (and Commit Transaction)
SessionManager.Close( );
Although simple, the line above hides many steps such as:
- Check if client name is valid
- Check if zipcode exists in the county US
- Check if address number is correct
- Check if addres complement id correct
- Check if there are clients with the same name and address
- Proceed with the client creation
Reference: http://www.martinfowler.com/eaaCatalog/repository.html
In order to make it possible the code line above, an Address and Client class must be implemented.
See full code listing below:
// Address is a value object used by Client class
public class Address
{
public Address(string zipCodeNumber,int number,string addrComplement)
{
// Check if zipcode number exists in the country (ZipCode Repository uses SessionManager inside it)
IZipCodeRepository zipCodeRepository = RepositoryManager.GetRepository( );
ZipCode zipCode = zipCodeRepository.Get(zipCodeNumber,country);
if (zipCode == null) { throw new NonExistentZipCodeException(zipCodeNumber,country);
// Check if address number is correct
if (number <= 0) { throw new InvalidAddressNumberException(number); }
// Check if address complement is correct
if (complement.Trim( ) == string.Empty) { throw new InvalidAddressComplementException(addrComplement)); }
// Sets values
this._zipCode = zipCode;
this._number = number;
this._complement = complement;
}
private ZipCode _zipCode = null;
public ZipCode ZipCode get { return _zipCode; }
private int _number = 0;
public int Number { get { return _number; } }
private string _complement = string.Empty;
public string Complement { get { return _complement; } }
}
// Now the Client class
public class Client
{
private long _id;
public long Id { get { return id; } set { this.id = value; } }
private string _name = string.Empty;
public Name
{
get { return _name; }
// Check if name is valid
set
{
if (name.Trim( ) == string.Empty) { throw new InvalidNameException(); }
// Check if there are Clients with same name and address
IClientRepository clientRepository = RepositoryManager.GetRepository();
bool exists = clientRepository.ClientExists(name,zipCodeNumber,number,addrComplement,country);
if (exists) { throw new ClientExistsException( ); }
this._name = value;
}
}
private Address _address;
public Address { get { return _address; } }
public Client(string name,string zipCodeNumber,int number,string addrComplement,Country country)
{
// Creates a Client
this.Address = new Address(zipCodeNumber,number,addrComplement,country);
this.Name = name;
}
}
Repositories have at least two advantages:
- It removes data specific code from the domain classes which are concerned only about business logic
- It allows unit tests since repositories are referred as interfaces in domain classes and thus fake repositories can be created without depend on database connection
1 comment:
You know that Bob Martin has been talking about the "S.O.L.I.D." principles of OO? The S stands for "Single Responsibility Principle" in which a class should do a single task, not more than that. You should perhaps rephrase your first paragraph...
Post a Comment