Am I breaking the "Law of Demeter"? - oop

I just recently became aware of the Law of Demeter.
Like a lot of things, I realized that it was something that I was already doing but did not have a name for. There are a few places though that I seem to violate it.
For example...
I might have an Address object:
public class Address : IAddress
{
public string StreetAddress { get; set; }
public string City { get; set; }
public int Zip { get; set; }
}
and a Customer object:
public class Customer : ICustomer
{
private IAddress address;
Customer()
{
Address = null;
}
public string Name { get; set; }
public IAddress
{
get
{
if (address == null)
{
address = new Address();
}
return address;
}
set
{
address = value;
}
}
}
Ok, this is fake code so you probably do not have to jump on me to use IoC to eliminate the new Address() or anything but it is pretty much an example of what I am doing. I did not include the interfaces as I am hoping they are obvious.
I would then use it in my code for stuff like int zip = customer.Address.Zip; and customer.Address.City = "Vancouver";
As I understand it, I am violating the Law of Demeter by manipulating details of Address from Customer.
Then again, it seems like the framework does as well. After all, wouldn't address.City.Length be a violation? Should I be adding methods to Address to handle accessing string properties? Probably not. So, why clutter up Address?
I cannot really just add methods to Address that relate only to customer. I have Member, Employee, Dependent, Vendor, Employer, etc. objects that all have addresses too.
Is there a better way to handle this? What kinds of problems am I risking if I use Address the way I am now?
For the Java folks, the Address class might look something more like the following if it helps:
public class Address extends AddressInterface
{
private String m_city;
public String getCity() { return m_city; }
public void setCity(String city) { m_city = city; }
}
I must admit that customer.getAddress().setCity("Vancouver"); rings more alarms than customer.Address.City = "Vancouver"; did for me. Maybe I should switch to Java for a while.

This article: http://haacked.com/archive/2009/07/14/law-of-demeter-dot-counting.aspx has a great explanation of the issues you are discussing.
As he notes it's not a dot counting exercise, it's a coupling issue. Currently your Customer and Address classes are too tightly coupled. For starters, Customer shouldn't be making new addresses, perhaps pass an Address in using a constructor. As to whether you should be using multiple dots to access parts of the address, read the article ...
Martin Fowler: "I'd prefer it to be called the Occasionally Useful Suggestion of Demeter."

Violations of the Law of Demeter are instances of a code smell named Inappropriate Intimacy. To remove this smell, you can refactor your code by hiding the internals of address and implementing methods in Customer that delegate to address. This way, you respect the encapsulation on the address inside the Customer.
Example:
public class Customer extends ICustomer{
private Address address;
....
public void setCity(String city){
address.setCity(city);
}
public String getCity(){
return address.getCity();
}
}
Hope this helps.

The problem here is that Address is a ValueObject. You would never change the city without changing the zip.
public class Customer extends ICustomer{
private Address address;
....
public void setAddress(String street, String city, int zip){
address = Address.new(street, city, zip);
}
// or even better but i'm not sure if it's valid C#
public void setAddress(int zip){
address = Address.lookup(zip);
}
}

Related

How does abstractions help in DRY?

When we search "Don't repeat yourself" on Wikipedia, the first sentence is:
In software engineering, don't repeat yourself (DRY) is a principle of
software development aimed at reducing repetition of software
patterns, replacing them with abstractions...
I know that abstractions in software engineering mean hiding implementation complexity of how the behaviors of an API are realized, but it seems that "abstractions" in this sentence is not what I know before. Could someone explain to me what abstraction means here? It would be better if you could give me an example.
I know that abstractions in software engineering mean hiding
implementation complexity of how the behaviors of an API are realized
Yes it means that (absstraction#wikipedia) and very same concept can also be leveraged to reduce repetitions! Or in other words, it can be used to practice DRY.
Let me try to explain that with an example. First I'll show non DRY code (without abstraction), then with use of abstraction I'd try to reduce repetitions.
Let's assume that you wanted to build an email view model based on application form details filled out by applicant and there is an email view class which consumes this emailViewModel to show all non-null details from application form. You could write it like in below example (first attempt)
public class ApplicationForm
{
public AddressDetail AddressDetail { get; set; }
public CustomerDetail CustomerDetail { get; set; }
public ProductDetail ProductDetail { get; set; }
}
public class EmailViewModel
{
public EmailViewModel(ApplicationForm applicationForm)
{
Address = GetAddressDetail(applicationForm.AddressDetail);
Customer = GetCustomerDetail(applicationForm.CustomerDetail);
Product = GetProductDetail(applicationForm.ProductDetail);
}
public string Address { get; set; }
public string Customer { get; set; }
public string Product { get; set; }
}
//view code assume razor view
#if(Model.Address!=null)
{
// method for showing address
}
#if(Model.Customer!=null)
{
// method for showing customer
}
//and other properties
I've kept above code quite simple; only three properties and haven't showed declaration for conversion methods. What if there were 50 properties! In this first approach it would be cumbersome changes that you'd be making in three places. Now I'll show you second example code of how you could create an interface (a way of abstraction) implement DRY.
interface IFormDetail
{
IFormDetailView GetDetail();
}
interface IFormDetailView
{
string ShowView();
}
public class ApplicationForm
{
public List<IFormDetail> FormDetails {get;set;}
}
public class EmailViewModel
{
public EmailViewModel(ApplicationForm applicationForm)
{
if(applicationForm.FormDetails!=null)
{
FormDetails = new List<IFormDetailView>();
foreach(var detail in applicationForm.FormDetails)
{
FormDetails.Add(detail.GetDetail());
}
}
}
public List<IFormDetailView> FormDetails { get; set; }
}
//view code assume razor view
#f(Model.FormDetails!=null)
{
foreach(var detail in Model.FormDetails){
detail.ShowView();
}
}
In this second code example , when you've a new property, you'll only make one change when a new application form property is created.
So while we are hiding complexity of how detail is presented etc., we are also leveraging it to reduce repetition.

What design choice use in this scenario to avoid violating the LSP?

I'm refactoring a few applications (scrapers) I've created into one single application. There are a few scrapers, like TwitterScraper, FacebookScraper, etc. The names are just for explaining better the problem.
Let's suppose I want to retrieve people using those scrapers. We could search using different ways in each scraper. For example, in Facebook we could search by Name, Age, etc.... or simply get all the users in some specific group, which means we have two ways of searching there. The same can happen to Twitter, and others...
I thought about having the following design:
public interface IScraper {
IEnumerable<User> Search(IParameter parameters);
}
and then have:
public class FacebookGroupsScraper : IScraper {
public IEnumerable<User> Search(IParameter parameters) {
//... search here using the group url, etc.
}
}
public class FacebookOtherScraper : IScraper {
public IEnumerable<User> Search(IParameter parameters) {
//... search here using the name, age, country, or whatever...
}
}
but I'm definitely violating the Liskov Substitution Principle, since I would have to do something like this in each method:
public class FacebookOtherScraper : IScraper {
public IEnumerable<User> Search(IParameter parameters) {
var p = parameters as FacebookOtherParameter;
//We can only work here with the expected parameters
//(FacebookOtherParameter class in this case)
}
}
What would be a good way to design it?
It looks like the difference between implementations are the types of parameters they take.
Therefore, in order to adhere to the LSP I think it is better to change your interface to either have separate methods or to have separate interfaces, each with a different method that take different types of parameters:
//... search here using the group url, etc.
public interface GroupScrapper{
IEnumerable<User> SearchByGroup(IGroupParameter parameters...);
}
//... search here using the name, age, country, or whatever...
public interface UserInfoScrapper{
IEnumerable<User> SearchByInfo(IInfoParameter parameters...);
}
or as a single interface:
public interface IScraper {
IEnumerable<User> SearchByGroup(IGroupParameter parameters...);
IEnumerable<User> SearchByInfo(IInfoParameter parameters...);
}
This way every implementation will meet the contract of one of the methods.
The problem with this approach is you would have to have a pretty static parameter set that is fully known ahead of time. If you have to keep adding new types of parameters then the number of methods and/or interfaces will explode.
I usually do generic for this case. (please note the code below may not compile)
public interface IScraper<T> where T : IParameter
{
IEnumerable<User> Search(T parameters);
}
public class FacebookParameter : IParameter{
public string GroupUrl{ get; set; }
}
public class FacebookGroupsScraper : IScraper<FacebookParameter> {
public IEnumerable<User> Search(FacebookParameter parameters) {
//... search here using the group url, etc.
}
}
However I forgot about how to use it at consumer level though.

Can't fetch certain types of nested objects in Ebean

I'm trying to fetch nested objects in Ebean, but it isn't working. I get the User. It has Addresses. The Addresses each have a House. But the House only has an id. All other properties are null. I read on this other forum that there may be a bug in Ebean, but it was from 2011. Is there a way to make this work?
Note: Address and House have a OneToOne relationship.
Note: I left out #Entity and #Id for simplicity.
public class User {
#OneToMany
public List<Address> addresses;
public static Finder<String, User> find = new Finder(String.class, User.class);
// This is my query
public static Event find(Long id) {
return find.fetch("addresses").fetch("addresses.house").where().eq("id", id).findUnique();
}
}
public class Address {
#OneToOne(cascade = CascadeType.ALL, mappedBy = "address")
public House house;
}
public class House {
#OneToOne
public Address address;
public String somePropertyThatIsNullWhenIUseMyQuery;
}
Ebean.find(User.class).fetch("addresses.house", new FetchConfig().query())
works for me. If you still dont see it, u might want to use
Address.getHouse().getSomeProperty()
Sometimes when u just pass the object to JSON f.e. properties shown as null :(

WCF serialization and Value object pattern in Domain Driven Design

The book Domain Driven Design by Eric Evans describes pattern called value object. One of the important characteristics of a value object is that it is immutable.
As an example I have a value object "Clinic" which must have a name and an id. To make it a value object I do not provide setters on name and id. Also to make sure that there is not invalid instance I take name and id in a constructor and do not provide at parameter less constructor.
public class Clinic
{
public Clinic(string name, string id)
{
Name = name;
Id = id;
}
public string Name{get; private set;}
public string Id{get; private set;}
}
The problem is that when I try to return this object from a WCF Service I get an exception that the object does not have parameter less constructor and the properties do not have public setters. I want to avoid adding parameter less constructor and public setters because then my domain model pattern goes for a toss. How can I get around this problem?
Regards,
Unmesh
I had a similar problem with serializing immutable types before, in the end I decided to implement the ISerializable interface and use the SerializationInfo to store & retrieve the private variables at both ends of the serialization/deserialization process:
http://theburningmonk.com/2010/04/net-tips-making-a-serializable-immutable-struct/
I just built and run a test app using the same technique and it seems to work for me. So in terms of changes to your Clinic class you could change it to:
[Serializable]
public class Clinic : ISerializable
{
public Clinic(string name, string id)
{
Name = name;
Id = id;
}
public Clinic(SerializationInfo info, StreamingContext context)
{
Name= info.GetString("Name");
Id= info.GetString("Id");
}
public string Name{get; private set;}
public string Id{get; private set;}
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Name", Name);
info.AddValue("Id", Id);
}
}
This will solve the problem you're having passing the data back from WCF. But from a design point of view, I agree with what Ladislav is saying and typically you will want to separate your domain objects with objects purely intended for message passing (DataTransferObjects), and in that case here's an example of how you MIGHT approach it:
// the domain object (NOT EXPOSED through the WCF service)
public class Clinic
{
public Clinic(string name, string id)
{
Name = name;
Id = id;
}
public string Name{ get; private set;}
public string Id{ get; private set;}
// other methods encapsulating some business logic, etc.
...
}
// the corresponding DTO object for the domain object Clinic
// this is the type exposed through the WCF layer, that the client knows about
[DataContract]
public class ClinicDTO
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Id { get; set; }
}
// WCF service contract, NOTE it returns ClinicDTO instead of Clinic
[ServiceContract]
public interface IClinicService
{
[OperationContract]
ClinicDTO GetClinicById(string id);
}
To ease the pain of converting from Clinic to ClinicDTO, you could either add a method on Clinic to do this or implement an implicit/explicit converter. I've got an example on how to do this here:
http://theburningmonk.com/2010/02/controlling-type-conversion-in-c/
Hope this helps!
The problem is that your value object is not serializable. How do you plan to use the service? Do you plan to share domain objects / value objects with your clients? If yes than it IMO violates your domain driven desing - only business layer should be able to work with domain objects and call their methods. If you don't want to share objects you will probably create proxy by add service reference which will generate data contrats for the client. These contrats will have public parameterless constructor and all properties settable (and no domain methods).
If you want to have real Domain driven design you should not expose your domain objects in WCF. Instead you should create set of DTO and expose those DTOs. Service layer will be responsible of converting those DTOs to Domain objects / value objects and vice-versa.

'Static/Constant' business objects

I don't quite know how to ask this question, so I'll phrase it as an example instead:
Imagine in an application you have a Country object. There are two properties of this object: Name, and a 'Bordering Countries' collection. More properties might be added later, but it will be the kind of information that would change very rarely (e.g. changes of country names/borders)
Lets say this application needs to know about all of the countries in the world. Where would you store these object's state? How would you new them up? It seems silly to store all this state in the DB, since it won't change very often.
One option might be to have an abstract 'country' base object, and have a class for each country inheriting from this with the details of each country. But this doesn't seem quite right to me.
What is the proper way of dealing with these kinds of objects?
UPDATES:
Someone asked about language: C#
Also, I'm coming at this from a web application perspective, so there wouldn't be multiple client installations where I'd have to worry about updating hard coded values.
Most people have suggested not hardcoding the data, but using the DB or XML files to store the data. Could anyone provide an example of how this kind of object would be 'newed up' (from e.g. an XML file)? Would you use some kind of helper or factory method to obtain instance of a particular country?
Definatly in the DB. Load them up once (refresh periodically) and use them from there.
I say definatly DB, as you will most likely be extracting data for reporting purposes, and if structured correctly, you can reuse the country data for other applications too.
enumerations are quite useful for that kind of thing. you don't mention the language you're using, but in java, they're stored quite efficiently as an ordinal index (integer) and you can always add new values to the end of the enumeration list.
I don't think that create a class hierachy would be a good design for your problem. Instead I'd store the values at the database and have a generic Country class what retrieve the country state from database.
It won't change very often, you say, but in that you indicate that it may change at one point. In such cases, you should put it in a datastore of some sorts, as the others have indicated - be it a database, text file, or otherwise.
Keep in mind that, if you put it in an enum or a static class or some other part of your actual application, the end-user will not be able to change it easily. So if by some natural disaster or world war 3 some countries disappear, merge, separate, get a new government type or name, you need to be able to update your country list.
You could just have the application read the country list on startup, and leave it in memory. It'll auto-refresh when the application restarts. Another option would be to have it check for updated countries every X period and update the internal list, if it's an application that runs for a long time.
As oedo said, enumumerations should do the job, but if you need more than an index, you could use an xml file. it would be dynamic, no need compilation
You've got a variety of answers, so I thought I'd add my $0.02 worth.
Personally I alway hard code fixed lists like this (same with postcodes). That being said, when I'm at your position, I'll always optimize for readability. ie What will make sense in 6 months time, when you've forgotten about this project and have to do some maintenance?
If I had to do it with a database:
public class Country
{
public string Name { get; set; }
public Country[] BorderingCountries { get; set; }
public Country(iDB db, string name)
{
BorderingCountries = db.BorderingCountriesGet(name);
}
}
Your unit test:
public UnitTest1()
{
iDB db = new DB();
Country c = new Country(db, "Spain");
Assert.AreEqual(2, c.BorderingCountries.Count());
Assert.AreEqual(1, c.BorderingCountries.Count(b => b.Name == "France"));
Assert.AreEqual(1, c.BorderingCountries.Count(b => b.Name == "Portugal"));
}
Oops! You probably want to populate the whole list (not one at a time!)
DB:
static void Main(string[] args)
{
Countries countries = new Countries(new DB());
}
public class Countries
{
public List<Country> Items { get; set; }
public Countries(iDB db)
{
tblCountry[] countries = db.BorderingCountries();
Items = new List<Country>();
Country country = null;
foreach (var c in countries)
{
if (country == null || country.Name != c.Name)
{
country = new Country(c.Name);
Items.Add(country);
}
country.BorderingCountries.Add(new Country(c.BorderingCountry));
}
}
}
public class Country
{
public string Name { get; set; }
public List<Country> BorderingCountries { get; set; }
public Country(string name)
{
this.Name = name;
BorderingCountries = new List<Country>();
}
}
public interface iDB
{
tblCountry[] BorderingCountries();
}
public class DB : iDB
{
public tblCountry[] BorderingCountries()
{
using (DataClassesDataContext dc = new DataClassesDataContext())
{
return dc.tblCountries.ToArray();
}
}
}
If I was hardcoding it:
public class Countries
{
public List<Country> Items { get; set; }
public Countries()
{
Items = new List<Country>();
Items.Add(new Country { Name = "Spain", BorderingCountries = new string[] { "France", "Portugal" }});
Items.Add(new Country { Name = "France", BorderingCountries = new string[] {"Spain","Belgium"});
}
}