Solved

comparing  mutable composite objects (design pattern question)

Posted on 2002-04-16
12
409 Views
Last Modified: 2012-05-04
this must be an already-solved problem.  probably a pattern.

suppose you have a class that is built as a composite (not through
inheritance), that is mutable and whose composite members are
mutable.  e.g.:

public class House {
  private Roof roof;
  private Address address;
  private Set rooms;
...

  public Roof getRoof() { return roof: }  // or a defensive copy of it...
  public void setRoof(Roof r) { roof = r; }  // or a defensive copy of it...
...
}

In what manner can/should instances of House be compared?

1) should equals() and hashCode() be provided?  should equals()
return true only if each recursive equals() returns true down to whatever
level all fields become immutable?

2) should a different method, say hasEqualValues() be provided in
place of equals() so as not to break any HashSet into which a House
has been placed and then mutated?

3) it would seem reasonable to provide a method:
public boolean isSameHouse(House otherHouse) that would return true
if i've only, say, replaced a broken window or painted a room.  How should
such a method be implemented?  should it be implemented?

4) suppose i wish to compare two houses to find where they differ.  i would
be interested in finding, e.g. that a door has been removed between two rooms.
would a method signature such as:
public Set getDifferences(House otherHouse)
fit the bill?  what gets placed in the return Set?  a Door object? how does the
client determine which Door it was?  should the return type be a Map instead
(from the Door object in thisHouse to the Door object in thatHouse)?

5) should the api provide just the equals() (or, hasEqualValues()) at each level
and leave it to the client to worry about how differences are handled?

thoughts?  it's been bugging me for some time....

thanks,

-don.
0
Comment
Question by:dddexter
  • 4
  • 3
  • 3
  • +2
12 Comments
 
LVL 92

Expert Comment

by:objects
ID: 6946688
When two house objects are considered equal is really a design decision that you need to make. And implement an equals accordingly.
If you have additional comparison techniques you wish to use then you'll need to implement these as seperate methods.
0
 
LVL 9

Accepted Solution

by:
Ovi earned 300 total points
ID: 6946871
If you are speacking in design pattern&design principles terms the house is just a house!!! The house cannot know about itself, about her composition, but can be queried from outside about composition, equality and such. The first and basic programming principle is called OCP or OpenClose Principle and states that a object (class) is open for extension and closed for modification. In the case you make your house a "smart one" is ok in first place but you violate this principle first time when you want to make'it much more smarter. And if you do so think a little in how many places are you intend to use such objects, and how hard will be to query them for incomming modification ?

So my suggestion is to live the house as a house and implement some external classes which work with that house. So you can implement patterns like Adapter, Proxy, Bridge, Delegation, and so on, specific to your purposes. The job of that house is only to provide to the interogator all information he needs. If you think further, basically your "main" house class shouyld be infact a abstract one, and derivate from it specific houses. What will be the impact to this derivates if you make them too smart, or the abstract one the same ? Perhaps you will have smart things enabled only for one cathegory of houses, and for others not.

Any way, I believe I've drawn a guidance line here, but if you want more details about programming principles, you can go first to www.objectmentor.com/resources/articleIndex section Design(or Programming) Principles or search the net for extreme programming links.

Good luck in building houses :-)
Ovi
0
 
LVL 1

Expert Comment

by:iartmirko
ID: 6948298
Don,

1. I would provide a equals() method for your house. This is a common Java method for comparing two objects. It should return true, if all fields of your houses are equal. That means that the fields that are not primitive should call there equal() methods recursively.

2. If you want to know if two houses are the same instances, just use the == operator. Use equals() only for comparing at field level.

3. Yes, you could define a method called equalsIgnoreReplacements() to define such a method...but it will be difficult to know, because the only stable attribute should be the address...but even that maybe changed...so how do you know that a house is the same whith changed attributes and not different house...you could keep a history for that...

4. I would't neither return a Set nor a HashMap. I would return a House object that contains only those fields that are different and all equal field set to null...

5. I would say that it depends on what you want to do. Think about sorting houses, where you provide a method like public int compare(House ) that return 0 if it is equal, -1 if it is less and >0 if it is greater than the house on which the method is called. Then you will need the house to handle this functionality...

Hope this helped you a little bit.

Mirko
0
 

Author Comment

by:dddexter
ID: 6954920
ok, since this seems to be all the discussion the question is going to
genererate on the first go-round, i suppose it's time for a response and
additional comments from me.

objects:
yes, i'm aware that i have to design the classes.  my question was "are
there any design patterns for this?" or, alternatively, "what are some
design suggestions?"  

Ovi:
i've been reading the site you mention and it is indeed full of good
advice and patterns.  the visitor pattern may be something like
what i'm after, but i'm still new to thinking in pattern terms...
your line: "The job of that house is only to provide to the interogator
all information he needs. "  is true.  taken at face value, it implies
that the client (or an interogator object) needs to do all the work.
any further thoughts as to how?

iartmirko:
i'm still not fully convinced about adding an equals().  to do so on
an immutable object is certainly a good idea, but mutable objects
yield other concerns (getting things out of hashSets).  (also, though it
isn't particularly difficult, you *must* implement hashValue() when
overriding equals()).  your point #3 is getting toward the heart of the
matter.

all:
suppose you have a GUI in which you can display houses.  in addition
to the obvious functionality of rotating them and the like, the GUI can
also add rooms, move walls, change doors, etc.   over time, a set of
plans would accumulate.  it may be desireable to ensure that no two
identical sets of plans can be saved.  it may be desireable to pull up
a house and display it "vs. another house"...a wall has been removed,
so a faint red wall is shown, a window added is also shown in red.  etc.
the client is (obviously) doing the display, but who is finding those
differences?  how?

thoughts?

-don.
0
 
LVL 92

Expert Comment

by:objects
ID: 6955138
> it may be desireable to ensure that no two
> identical sets of plans can be saved.

If this is desirable then you should be overriding equals to define what an 'identical' plan is.
0
 
LVL 9

Expert Comment

by:Ovi
ID: 6959301
I believe you are really try to create a house manipulation GUI. That's not a easy job and require a carefull design. Beginning with the top, I will create such thing splitting as much as possible the GUI from the logic and the model. First of all I would think on how to implement the basic functionalities of a HouseDesigner. I usually use the MVC pattern (Model-View-Controller) and for your case should look like this :

The model :
    - should use AbstractHouse - abstract class defining general house properties.
    - AbstractHouseFactory - factory for creating a specific kind of house, using Factory Method or Abstract Factory patterns.By specific kind I understand predefined type, or already saved type of houses.
    - HouseDesignerModel - a class which represent the model of a drawed house. Should provide methods for querying the global state of a house (visual state stored by this model and house state, stored by a AbstractHouse derivated object).

The controller : can be embed in the same class as the view (following swing MVC concept) or separate. Anyway you should keep in mind that a controller is associated to a specific view.
    - HouseDesignerController - a class which caries the logic of user interaction with the dispolayed oject in the associated view. Should communicate to the model any change of state.

The View :
    - HouseDesignerView - a observer class used to represent the visual state of a house. It should be maded as Observer of the model, and should have a Controller class registered.

So you have solved in the design terms the problem of display/manipulation of a house. The used MVC pattern give you the possibillity to have AT LEAST ONE view associated with the model, so you can virtualy represent a model content in a infinity of synchronized views.

About the GUI this should be simple like a window, a menubar, perhaps a popup menu. For this GUI to be easy to maintain (today you want 3 things to be implemented, tomorrow you will want another new 10), I suggest you to really take into consideration a plugin enabled framework. The plugins would query the basic GUI that you provide for ading menu options for example, or the HouseDesigner component holded by the GUI, and do the necesary things by querying the model of it...

About your last question, thinking in plugin terms, the queries for a allready existant saved planes collection could be impleented in a special save plugin. or a plugin which does the comparation of a saved house properties file (XML like) to a on fly generated one for the editing house.
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:dddexter
ID: 6959829
sorry...
i didn't intend to be taken literally about the house designer gui.
i agree, such a task would be extensive.  i was providing it as an
example only to demonstrate the manner in which these object
comparisons needed to take place.  the actual project i'm working
on (though it does involve a gui) doesn't even involve houses.  all
of that was for illustration purposes only - to give us a framework
for our conversation.

if we're to recast the conversation to MVC terms, i have the model
(the house class that stores all the info...the house "state"), the
controller/view (they are wrapped up in one package, called, for
our purposes, HouseGUI).  the question would then be "does the
comparision functionality belong in 1) the House class (model),
2) the HouseGUI class (view or controller), or 3) somewhere else?"

-don.
0
 

Author Comment

by:dddexter
ID: 6959845
sorry...
i didn't intend to be taken literally about the house designer gui.
i agree, such a task would be extensive.  i was providing it as an
example only to demonstrate the manner in which these object
comparisons needed to take place.  the actual project i'm working
on (though it does involve a gui) doesn't even involve houses.  all
of that was for illustration purposes only - to give us a framework
for our conversation.

if we're to recast the conversation to MVC terms, i have the model
(the house class that stores all the info...the house "state"), the
controller/view (they are wrapped up in one package, called, for
our purposes, HouseGUI).  the question would then be "does the
comparision functionality belong in 1) the House class (model),
2) the HouseGUI class (view or controller), or 3) somewhere else?"

-don.
0
 
LVL 92

Expert Comment

by:objects
ID: 6961175
Comment
From: objects  Date: 04/19/2002 04:04PM PST  

> it may be desireable to ensure that no two
> identical sets of plans can be saved.

If this is desirable then you should be overriding equals to define what an 'identical' plan is.
 
This is analagous to how the String class equals works.
0
 
LVL 9

Expert Comment

by:Ovi
ID: 6961949
In my opinion point 3. The responsability of comparisation should go somwhere else, in a Comparator object. I use equals only for primitive classes (nonmutable).
0
 
LVL 9

Expert Comment

by:Venci75
ID: 7972287
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:
Answered by: objects
Please leave any comments here within the next seven days.
 
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
 
Venci75
EE Cleanup Volunteer
0
 

Author Comment

by:dddexter
ID: 7987668
never did really solve the problem as stated - ended up
deciding that two _different_ houses can't be compared, you
can only compare one house to itself for changes made.  instead of actually performing the comparison, i simply log all changes as they happen and can therefore go back and forth (graphically) through a change log.

i suspect that recasting the problem is the proper answer and that comparisons of the sort i was after don't make much sense.

thanks all,

-don.
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Suggested Solutions

For customizing the look of your lightweight component and making it look opaque like it was made of plastic.  This tip assumes your component to be of rectangular shape and completely opaque.   (CODE)
Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now