Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How do I capture a hierarchy of control in OOP?

Status
Not open for further replies.

xixax

Programmer
Jun 24, 2010
3
AR
I have a set of objects that represent different levels in a hierarchical organizational structure, in this instance a statewide school system.

At the bottom of the hierarchy is the school. It is administered by a town, which is administered by a disctrict, and so forth, like this:

State
Region
County
District
Town
School

Now if this were all there were to it, it would be easy. My School object would have an "administeredBy" property that pointed to a Town, and the Town would have an administeredBy property that pointed to a District. Similarly, a State would have a "administers" property that was a List of Regions, etc.

The problem is that steps can be skipped. For example, some schools are regionally administered. So the "administeredBy" property has to allow a Town, District, etc.

Obviously, the solution is an AdministrativeUnit class (interface, trait) from which all the above classes (except School) extend. (And an AdministeredUnit for everything below State.)

This allows me to have a School administeredBy Region and a Region that administers Schools.

The problem is that it also allows me to have a Region administeredBy a Town and a District that administers Counties.

Is this clear?

So is there any way for me to set this up in OOP to prevent the above problem? If it helps, I am working in Scala (or Java).
 
sounds like a composite design is a good starting point for this model. i wouldn't worry too much about regions administering towns. you can use a facade object to encapsulate the relationship management. to prevent this.

Jason Meckley
Programmer
Specialty Bakers, Inc.

faq855-7190
faq732-7259
 
Here's one somewhat verbose solution I've found. Basically, the relationships of "administers" and "administeredBy" are captured in traits and then each type of organization incorporates the applicable traits. (This is Scala.) It's wordy, but it does ensure that only the correct relationships are possible.

Is there a better way?

trait AdministeredByRegion
trait AdministeredByCounty
trait AdministeredByDistrict
trait AdministeredByTown

trait AdministersCounty
trait AdministersDistrict
trait AdministersTown
trait AdministersSchool

abstract class Organization(name: String) {}

case class Region(name: String) extends
Organization(name: String) with
AdministersCounty with
AdministersDistrict with
AdministersTown with
AdministersSchool {
var administers: List[AdministeredByRegion] = Nil
}

case class County(name: String) extends
Organization(name: String) with
AdministeredByRegion with
AdministersDistrict with
AdministersTown with
AdministersSchool {
var administers: List[AdministeredByCounty] = Nil
var administeredBy: Option[AdministersCounty] = None
}

case class District(name: String) extends
Organization(name: String) with
AdministeredByRegion with
AdministeredByCounty with
AdministersTown with
AdministersSchool {
var administers: List[AdministeredByDistrict] = Nil
var administeredBy: Option[AdministersDistrict] = None
}

case class Town(name: String) extends
Organization(name: String) with
AdministeredByRegion with
AdministeredByCounty with
AdministeredByDistrict with
AdministersSchool {
var administers: List[AdministeredByTown] = Nil
var administeredBy: Option[AdministersTown] = None
}

case class School(name: String) extends
Organization(name: String) with
AdministeredByRegion with
AdministeredByCounty with
AdministeredByDistrict with
AdministeredByTown {
var administeredBy: Option[AdministersSchool] = None
}
 
i'm not familiar with the scala syntax so I can't say whether is "wordy" or not. it seams sound. I would say the test is do you need alot of "if" or "case" statements to manage adding entities to one another. if not than the code "should" be clean and maintainable. otherwise it would become tedious if/when the structure of the organizations and relationships change.


Jason Meckley
Programmer
Specialty Bakers, Inc.

faq855-7190
faq732-7259
 
I would design it so that each object is an admin unit. Each unit has a higher echelon and a collection of lower echelons so you can navigate the structure in both directions. The topmost echelon would be assigned a null higher, and the lowest would all have 0 length collections. Include any other common properties and actions into this class also. Inherit/Extend the more specific levels from this class.
 
Here is my solution. It's cleaned up a bit and uses subtypes. I think that this is probably the most straightforward way to do this.

trait RegionUpperBound
trait CountyUpperBound extends RegionUpperBound
trait DistrictUpperBound extends CountyUpperBound
trait TownUpperBound extends DistrictUpperBound
trait SchoolUpperBound extends TownUpperBound

trait SchoolLowerBound
trait TownLowerBound extends SchoolLowerBound
trait DistrictLowerBound extends TownLowerBound
trait CountyLowerBound extends DistrictLowerBound
trait RegionLowerBound extends CountyLowerBound

abstract class Organization(name: String) {}

case class Region(name) extends
Organization(name) with RegionUpperBound with RegionLowerBound {
var administers: List[CountyUpperBound] = Nil
}

case class County(name) extends
Organization(name) with CountyUpperBound with CountyLowerBound {
var administers: List[DistrictUpperBound] = Nil
var administeredBy: List[RegionLowerBound] = Nil
}

case class District(name) extends
Organization(name) with DistrictUpperBound with DistrictLowerBound {
var administers: List[TownUpperBound] = Nil
var administeredBy: List[CountyLowerBound] = Nil
}

case class Town(name) extends
Organization(name) with TownUpperBound with TownLowerBound {
var administers: List[SchoolUpperBound] = Nil
var administeredBy: List[DistrictLowerBound] = Nil
}

case class School(name) extends
Organization(name) with SchoolUpperBound with SchoolLowerBound {
var administeredBy: List[TownLowerBound] = Nil
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top