Jump to content

Loose coupling and parents/children/related

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
4 replies to this topic

#1
RedShift

RedShift

    Newbie

  • Members
  • Pip
  • 2 posts
Hello


I'm trying to achieve loose coupling between two objects that don't know about
each other, but in reality have a relation with each other.


I'm going to illustrate my attempt using a DNS example. Say that I have a
DnsZone and a DnsRecord class.


Ok, so why do I need the loose coupling? Because I'm writing an application that has
interchangeable backends. If a sysadmin isn't satisfied how this application
stores its information, he should be able to quickly change it the way he likes
it. A key element in making this possible is limiting the code that sysadmin
would have to write to construct his own implementation. Therefore, the interface
only specifies a very limited set of methods to implement, :
interface dnszone {
	public function getAll();
	public function save();
	public function add();
	public function del();
	// This is the DNS zone interface, get the name of the zone, example.com
	public function getName();
	// Get the type of the zone, for example "master"
	public function getType();
}

Another aspect of this application is seperation of powers. The application is
split up into three aspects:
* Lowlevel backends. One of these lowlevel backends like above. The only
control we have here is that these backends must implement a specific interface
and those methods must return a certain datatype.
* Business logic. This layer processes the information retrieved from the
lowlevel backends and definition files, to allow the information to be passed
to the presentation layer and the other way around, such as command a backend
to delete a specific entry.
* Presentation layer. This layer converts the supplied data by the business logic
into something humans can use.


Each class has a getAll() function they must implement.
* DnsZone will fetch all the DNS zones with information like zone name
(exampledotcom) getName(), type (master||slave) getType(), etc...
* The DnsRecord class getAll() will get all the possible DNS records, like
record name (wwwexampledotcom) getName(), record type (A||MX||AAAA...) getType(),
result (1.2.3.4) getContent(), etc...


Now how do I achieve loose coupling in this model? Obviously a DnsZone has
DnsRecords, I'm searching for a proper way to allow the business logic layer
to know that a DnsZone has DnsRecords below it and a DnsRecord has a DnsZone
above it. Note that it doesn't always have to be a parent/child relation
(many-to-one), more like a possible many-to-many. It just is a parent/child
relation in this example.


There are a few options I've considered:

* Observer/parent/child style. The DnsRecord class is registered to the DnsZone
class as a child upon runtime. So when getAll() is done on DnsZone, it will
automatically call DnsRecord with an appropriate function to get all the records
belonging to that zone.

The drawback to this solution is that both classes become intertwined. The
DnsZone knows it has children and needs to reserve room for storing DnsRecords.
The DnsRecord in that regard needs to especially equipped to fetch DnsRecords
for a specific DnsZone. And the observer pattern itself is one-way communication
only, making it two-way is messy.


* DnsRecord extends the DnsZone object.

This is a probable solution, but it makes the DnsRecord object dependant of the
DnsZone object and causes a name conflict since both have to implement getAll().
Making the DnsRecord ignore getAll() and force to write for example getAllChilds()
then that would mean the DnsRecord actually is a child of the DnsZone, again
losing loose coupling.


Both of the above solutions are not acceptable since the sysadmin must write
functions to allow the relation to work. Since we consider the sysadmin a very
unreliable source, we must keep control over this ourselves.


Right now I'm kind of stuck in this brainteaser. Any tips/suggestions/coding
practices/related situations/etc... would be welcome.

Edited by WingedPanther, 02 December 2008 - 05:47 AM.
add code tags (the # button)


#2
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
I have a feeling you are thinking about this incorrectly, if this is a real-world problem and not an assignment. Most programmers I deal with do NOT thinking in terms of strong/weak coupling in situations like this. They think in terms of how things will communicate, dependencies and requirements.

Usually, a module will provide an interface that is well defined. It doesn't care what calls its interface, just responds to calls. Similarly, another module knows that there is a module that is supposed to be able to provide it certain information based on the exposed interface. If you have two modules, each will have an interface that can be called by other modules (possibly even each other).

In this case, it looks like you are talking about two classes that, among other things, need a container of pointers to members of the other class to provide data. Having something like a register()/deregister() method could handle populating the container.

One thing I've discovered is that, despite all the benefits of loose coupling, there are MANY programs written with strong coupling. A program with several forms is a common example, as weak coupling just makes it harder to get information passed out of a child form that will never be reused. It's always worth asking: how much benefit am I getting out of loose coupling?
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#3
RedShift

RedShift

    Newbie

  • Members
  • Pip
  • 2 posts

WingedPanther said:

I have a feeling you are thinking about this incorrectly, if this is a real-world problem and not an assignment. Most programmers I deal with do NOT thinking in terms of strong/weak coupling in situations like this. They think in terms of how things will communicate, dependencies and requirements.

Usually, a module will provide an interface that is well defined. It doesn't care what calls its interface, just responds to calls. Similarly, another module knows that there is a module that is supposed to be able to provide it certain information based on the exposed interface. If you have two modules, each will have an interface that can be called by other modules (possibly even each other).

In this case, it looks like you are talking about two classes that, among other things, need a container of pointers to members of the other class to provide data. Having something like a register()/deregister() method could handle populating the container.

One thing I've discovered is that, despite all the benefits of loose coupling, there are MANY programs written with strong coupling. A program with several forms is a common example, as weak coupling just makes it harder to get information passed out of a child form that will never be reused. It's always worth asking: how much benefit am I getting out of loose coupling?

Thanks for the detailed thought experiment. I think I've found a solution. I'll have the interface specify you must supply a getCommonName() function. For all concrete instances that share some relation, that name can be used to link them together.

The only drawback there is that it doesn't define how that CommonName should look like, so there needs to be a convention what that method should return specifically.

Right now in my DNS example it returns the upper domain name (so DnsZone has multiple DnsRecords because they share the same CommonName).

#4
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
When you specify a function, it includes the parameters it accepts as well as the return type. You can take advantage of that. You can even have a specification exposed (via header files or documentation) that indicates what the CommonName should look like. Ideally it will be extensible for new features.
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#5
tecktalk

tecktalk

    Programmer

  • Members
  • PipPipPipPip
  • 175 posts
hmmm... its nice. that you got your problem solved.. I was soo confused with ur question even...
_______________________
Growth Stock Tools Free Credit Report Online