• Post Reply Bookmark Topic Watch Topic
  • New Topic

help sorting out how to apportion responsibilities and organize object creation  RSS feed

 
Jon Swanson
Ranch Hand
Posts: 230
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've been trying to work through an evolving requirement and wonder if I could get some comments as to whether I am thinking about this the right way. Simplifying things the best I can.

I have a couple of objects, which I will call height and width. The latter may depend on the former and I access them through an interface:

I then have something I will call a RectangleMaker, which represents some set of rectangles that can be made. It takes a list of heights and widths and keeps track of which ones have been selected and which ones can still be made. For example, the possible heights might be 2 or 3 and the possible widths 3 or 4. It needs to determine if it can make a rectangle with a specific area and if selected to make that rectangle, disallow any other heights. So if I said, you are in charge of 2 x 3 rectangles, it could still potentially also make 2 x 4 rectangles, but 3 x 3 rectangles would no longer be an option. For the most part I think these details are irrelevant to my question, which is really about organization and assignment of responsibilities.

Now I have a new requirement. The lists of heights now need to be associated with a source, as do the widths. I should keep track of a list of RectangleMakers and pick the 'most appropriate' one for a particular area. The rule is to sort first on the height source and then on the width source and the first one able to handle the area, gets the job. So I created two enums heightSource and widthSource and had RectangleMaker implement Comparable, so I can make an ArrayList<RectangleMaker> and sort it based on the rules. Then I traverse the list and the first one that returns isAreaAvailable() true gets the job. So far, so good (I think).

The final bit is that these sources also imply a specific set of Heights or Widths. How I get that set varies, it may be a fixed value or values, or might be read from a file. So in principle I could have:

and have a lot of specific code that builds each list by whatever method is appropriate. I still need to deal with the fact I might need additional information to build the lists. For example, one source might require a min, max and increment and another might require a file name. So I started working in the direction of more interfaces.

I am not totally comfortable with my enum lists. They solve the sorting problem, but I am not exactly sure which class should define them. Right now they are defined by the RectangleMaker. I would need to update this class every time I added an implementation of HeightList or WidthList.

I was also thinking that since the list is built from a specific source, that source should be associated with the list. That would lead me to make this change:

It seems maybe there should be a factory in here somewhere, but this is where I am having trouble sorting out exactly who has what responsibility.
I can do this sort of thing with my HeightList interface:

Should I be thinking of putting one more layer over all of this? What complicates my thinking are two things: multiple instances may have the same source and some of these instances are dynamic. For example, two SpacedHeight instances may have different ranges, but they are both SpacedHeight and it doesn't matter which gets picked first. Exactly what SpacedHeight instances get created is determined by prompting the user for the values. If the heights come from a file, every instance would be associated with a different source and the file names would be hard-coded.

I think I want to make a HeightFactory and I think then it would make sense to move my enum definitions there. I see how I would do that if I could hard-code a specific instance of a HeightList with a specific enum. I am less clear on how to handle the case where the factory needs different parameters for different HeightList implementations.

I am also thinking I've made this too complicated and am missing a simpler cleaner approach to the problem. So any suggestions, general or specific are welcome.
 
K. Tsang
Bartender
Posts: 3648
16
Firefox Browser Java Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't know about you, but I can't understand what you are trying to do/ build.

This is what I believe you are trying to do. End goal = find out a shape's area or whatever based on their measurements (width, height, etc). Correct or close enough?

 
Jon Swanson
Ranch Hand
Posts: 230
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What I am trying to build has a 16 page list of requirements. So I cannot post code that builds what I am actually putting together. So I tried to provide the skeleton of a simpler application.

What I am really interested in is not implementing the simple example. I am interested in trying to sort out how to define collections of objects in a way that makes sense.

There are several layers in the application-

A set of basic objects that expose methods to get their value through their interface.

An object that takes lists of each of these objects and maintains state information, such as whether the basic objects currently held can meet certain conditions, and whether specific items in the list are considered in use.

An application that takes a list of the latter objects and sets their states, the order in which the objects are examined depending on a set of keys, one key being associated with each list. Though key may be the wrong word, since lists may or may not have the same key value.

I am trying to get a good paradigm for creating the lists of objects and associating with them a key.

There are many methods for creating these lists. Each requires a different set of parameters. The lists may be created on the fly while the program is running or may be read from a file when the program starts.

I suspect the set of keys (which represent the way the list is created- not a specific instance of a list) will change over time.

Right now, the keys are defined as enums in the class that maintains the state information, which also has a custom comparator to make it easy to sort a list of these objects. That allows me to examine them in the correct order.

Right now, I just have a lot of separate classes that make the different kinds of lists. When I create an instance of the object that maintains the state of the lists, I give it the keys and I give it the lists. It's the method instantiating this class that maps the key to the list and so its up to the programmer to enter this correctly.

It seems like there should be a better way to handle the list creation/key mapping. I am getting hung up as to where the enums should actually be defined and how to create some encompassing class that can build lists and associate keys with them because the arguments to the methods for making lists are different for every list (though in the end, the created lists are all ArrayList<Item>). If the lists were never created dynamically and never shared keys, I would just have a switch on the key and hard code the arguments. Its unclear how to handle the case where I need to pass arguments and might reuse the key.
 
Knute Snortum
Sheriff
Posts: 4274
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My opinion is that when you want to create a bunch of similar/related objects, you should use a factory. All objects created by the factory should have the same interface.
 
Jon Swanson
Ranch Hand
Posts: 230
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I use a factory when I am creating related objects that have the same signature for the constructor. I've always been at a bit of a loss when that is not the case. I'll try again to produce an example.



How do you collect these classes into a factory?

The real constructors have more arguments. I am having trouble getting my head around how to make a factory where the product is always the same, but the method of construction differs, versus a factory where the method of construction is the same, but the product differs. I'm not sure there isn't a better pattern for this problem, but I don't know what it would be.
 
K. Tsang
Bartender
Posts: 3648
16
Firefox Browser Java Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maybe you can give the Builder pattern a try.
 
Rico Felix
Ranch Hand
Posts: 411
5
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As K.Tsang suggested, this sounds like a case that can be solved using the Builder Pattern
 
Jon Swanson
Ranch Hand
Posts: 230
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have maybe too simplistic notion of the builder pattern. What I use as the builder pattern is something like this:



which to me implies the components are the same. Versus



I see how each implementation of my HeightList interface could be written as a builder, rather than passing the arguments in the constructor. I am less clear on how that would help me wrap the different approaches to getting the list into one larger class that manages the work.

I am beginning to think the situation is like this-



That is, I have objects that share the same interface, but may not be similar enough to reasonably make a class that returns the desired type of Food. Though it still seems if I think about factories, builders and decorators in the right way, what seems complicated now will seem simple. And I still like the idea of collecting my Food making in one place.
 
Knute Snortum
Sheriff
Posts: 4274
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If the Builder Pattern is implemented correctly, you should be able to do this:



But if you need different methods to construct the objects correctly, you shouldn't use a factory.
 
Jon Swanson
Ranch Hand
Posts: 230
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Unfortunately, I do need different methods to construct the objects. The class that uses the objects does not care about this, since the objects all implement the same interface. I care, because I was hoping to find a way to collect the object construction in one place. The fact that the objects that implement the interface are constructed by different methods has been the hang-up.

I guess I could create a class that simply overloads the constructor. I THINK the signatures for the different construction methods are all different. That gets everything in one place and it would still implement the interface. I've been trying to come up with something sexier, as I was hoping to make it very obvious what you where making, i.e.,



seems more readable than



though in the former case, the code is spread around a bunch of classes and in the latter, all contained in one place.

Is one or the other of these options generally favored?
 
Knute Snortum
Sheriff
Posts: 4274
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The general rule is, everything an object does should be in that object. I don't see anything wrong with the first code example.
 
Jon Swanson
Ranch Hand
Posts: 230
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That brings us all the way back to the start of the discussion.

The classes need to have an enum associated with them. So if you looked inside one of the classes implementing the HeightList interface, it would look like:



I've got that enum source that I need to set and if I implement another version of the interface, I need to find where the enum is defined and possibly add another entry.

If I could have worked out a factory implementation, for example, I'd put the enum definition in the factory class. If I just have a bunch of separate implementations of HeightList, I would guess the place for the enum is in the interface definition itself. That just seemed to be an odd place to put it.
 
Knute Snortum
Sheriff
Posts: 4274
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You know, you don't have to put an enum "in" anything. It's just a specialized class.


 
Jon Swanson
Ranch Hand
Posts: 230
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I suspect once I write this stuff, I won't look at it again for six months and it might be someone else that adds new implementations of the interface. More or less I have


where XXX is wherever the enum gets defined, which could be in BigThing or ThingInterface, or its own separate class or many other places. If I need to make a new implementation of ThingInterface, I may need to change the enum, so I want it to be obvious where to go six months later to find it. Actually, BigThing requires two different objects, each with there own interface and each with their own enum definition. So if I went with separate enum classes, there would be two enum classes, one for each interface.

Opinions on what is going to produce the least maintenance hassles? At this stage, I am not against refactoring the whole scheme if some other approach seemed more logical.
 
Knute Snortum
Sheriff
Posts: 4274
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In order to refactor (or know whether to refactor) I would need to know what this program is really doing. I know you have a 16-page requirements document, but you should still be able to sum up what is going on in two or three sentences.

Secondly, I don't understand why you're using Enums as types.



The first XXX is a Java type and the second XXX is an enum. They can't be the same.

Don't worry that people won't be able to find the Enum file. it will be just as easy to find as any other class file.

I think there's some confusion over the word "type". If getType() isn't returning a Java type, but rather "some sort" of Thing, maybe you can think of another word for "some sort". "Kind" maybe.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!