Accessing an invoking class's getters?

R

Rhino

Can someone remind me of the idiom for accessing the getters for a class
that invoked another class?

For example, let's say I have instantiated an instance of class Alpha and it
is called alpha. My alpha instance sets some class variables, say foo and
bar, and invokes a class Beta, creating an instance called beta. Now, beta,
the instance of class Beta, needs to see alpha's variables foo and bar. What
is the idiom for seeing those values?

public class Alpha {

String foo;
int bar;

public Alpha() {

setFoo("Dog");
setBar(1);

}

public void actionPerformed() {

Beta beta = new Beta();

}

public void setFoo(String myFoo) {

foo = myFoo;
}

public void setBar(int myBar) {

bar = myBar;
}

public String getFoo() {

return foo;
}

public int getBar() {

return bar;
}
} //end Alpha

public class Beta {

String foo;
int bar;

public Beta() {

// How do I get the values of foo and bar that were set in the invoking
instance?
this.foo = ??.getFoo();
this.bar = ??.getBar();
} //end Beta()

} //end Beta

I *think* I had to do this at some point in the fairly distant past but I
can't find an example in my source libraries. I don't know the exact
terminology for what I'm trying to do so a Google search or looking through
an FAQ gets tricky. I'm hoping someone can remind me of this idiom.

By the way, is this - using the invoking class's getters - considered a bad
thing to do in OO terms?

I'm trying to reduce the number of parameters that Alpha has to pass to Beta
when Beta is instantiated and, since Alpha has already set those values, it
seems reasonable to simply ask alpha what values those variables have. One
alternative, of course, is that I could simply pass those variables to Beta
when I instantiate it but I'm concerned that I'm passing too many parameters
when I do everything that way; some of my "Betas" are getting almost a dozen
parameters passed to them. I'm thinking of passing important values as
parameters and lesser values via the idiom I am asking about.

Any guidance you have to offer on either the specific idiom I've asked about
or the general issue of the best techniques for passing parameters to a
constructor would be greatly appreciated.
 
B

Bjorn Abelli

...
Can someone remind me of the idiom for accessing the
getters for a class
that invoked another class?
public class Alpha {

....

public void actionPerformed() {

// Beta beta = new Beta();
Beta beta = new Beta(this);

}

-------------------------

public class Beta {

....
public Beta(Alpha a) {

this.foo = a.getFoo();
this.bar = a.getBar();
}

}

....is one way of doing it...

If you need access to the instance of Alpha elsewhere in the Beta instance,
you could also keep the reference...

-------------------------

public class Beta {

....

Alpha a;

public Beta(Alpha a) {
this.a = a;
this.foo = a.getFoo();
this.bar = a.getBar();
}

}


// Bjorn A
 
R

Rhino

Bjorn Abelli said:
...



...

public void actionPerformed() {

// Beta beta = new Beta();
Beta beta = new Beta(this);

}

-------------------------

public class Beta {

...
public Beta(Alpha a) {

this.foo = a.getFoo();
this.bar = a.getBar();
}

}

...is one way of doing it...

If you need access to the instance of Alpha elsewhere in the Beta instance,
you could also keep the reference...

-------------------------

public class Beta {

...

Alpha a;

public Beta(Alpha a) {
this.a = a;
this.foo = a.getFoo();
this.bar = a.getBar();
}

}


// Bjorn A

I finally found an example that did exactly what you describe about 10
minutes after I posted my question. I knew I'd done it before at some point
;-)

So, this is a perfectly valid thing to do, right?

I guess I'm still a bit worried about the bigger design question though. Is
it better to pass a list of values from Alpha to Beta, even a fairly long
list of values, as discrete parameters in the method constructor signature
itself? Or is it better to pass a single reference to the invoking class and
then use getters from the invoking class to determine the different values
needed?

Also, is it bad form to do a mix of the two techniques, i.e. to pass
"important" values as parameters to the constructor and obtain "lesser"
values from a reference to the invoking class?

A rule of thumb to help me decide the appropriate technique would be very
helpful.

Can anyone suggest such a rule?

Rhino
 
C

Chris Uppal

Rhino said:
I *think* I had to do this at some point in the fairly distant past but I
can't find an example in my source libraries.

I don't think it's possible.

By the way, is this - using the invoking class's getters - considered a
bad thing to do in OO terms?

Yup ! Awful ;-)

I'm trying to reduce the number of parameters that Alpha has to pass to
Beta when Beta is instantiated and, since Alpha has already set those
values, it seems reasonable to simply ask alpha what values those
variables have.

There's nothing wrong in having a Beta ask an Alpha for the values of some
settings, nothing at all. What is wrong is that a Beta should even know /that/
it's being created by an Alpha, let alone by which one. Pass /an/ Alpha to the
new Beta in its constructor, and let it ask that Alpha for the data it needs.
If the Alpha wants to provide /itself/ as a parameter, then that's fine, but
it's no business of the Beta to know or care. By the way, that pattern is
doubly good, because it means that Alphas don't have to "know" what data is
needed for setting up a Beta -- so you've got some extra decoupling in there.

(As an aside, I think that you should try to avoid using the word "class" when
you mean object, and in general to try to distinguish clearly between, say, the
class Alpha and its instances. I wouldn't have mentioned it -- it's a bit of
terminological laxness that everyone indulges in from time to time -- except
that you seem to be confusing yourself with it. I suspect that if you had
thought in terms of which /objects/ were doing what, then you would probably
have seen the point I made in the previous paragraph by yourself.)

-- chris
 
B

Bjorn Abelli

...

So, this is a perfectly valid thing to do, right?
Yes.

I guess I'm still a bit worried about the bigger design
question though. Is it better to pass a list of values
from Alpha to Beta, even a fairly long list of values,
as discrete parameters in the method constructor signature
itself?

If there's no other relation between an instance of an Alpha and a Beta,
this would be the prefered method, as you then decouple the dependence to
Alpha from a Betas point of view.

If there's a need to have a very long list of values, there are patterns to
deal with this.

One is to encapsulate the needed values into one single object, and to pass
that instead...
Or is it better to pass a single reference to the invoking
class and then use getters from the invoking class to
determine the different values needed?

If the Beta instance *anyway* have a dependency of some sort towards an
instance of Alpha (e.g. if it at some point needs to invoke some method on
the Alpha instance), this would be the prefered method, and simplifies
much...
Also, is it bad form to do a mix of the two techniques,
i.e. to pass "important" values as parameters to the
constructor and obtain "lesser" values from a reference
to the invoking class?

IMHO I would consider it "ugly", and not thoroughly pondered upon...

// Bjorn A
 
R

Rhino

Chris Uppal said:
I don't think it's possible.
Bjorn's initial reply to my question demonstrates that it is possible; his
approach exactly matched the approach I had used when I finally found that
old example. The code works fine.
Yup ! Awful ;-)
You're being facetious, right?


There's nothing wrong in having a Beta ask an Alpha for the values of some
settings, nothing at all. What is wrong is that a Beta should even know /that/
it's being created by an Alpha, let alone by which one. Pass /an/ Alpha to the
new Beta in its constructor, and let it ask that Alpha for the data it needs.
If the Alpha wants to provide /itself/ as a parameter, then that's fine, but
it's no business of the Beta to know or care.

Yes, that's exactly what Bjorn's reply called for; the specific instance of
Alpha which was invoking this instance of Beta was passed in Beta's
constructor via a 'this' reference.
By the way, that pattern is
doubly good, because it means that Alphas don't have to "know" what data is
needed for setting up a Beta -- so you've got some extra decoupling in there.
Okay, that sounds good :) In Bjorn's reply, he simply passes a specific
instance of Alpha to the new instance of Beta via the 'this' reference and
leaves the Beta instance to get what it needs via Alpha's getters. I
couldn't see any real problem with that but I wanted to make sure it was not
a violation of design "best practices". I'd like to do things the "best" way
if I can.
(As an aside, I think that you should try to avoid using the word "class" when
you mean object, and in general to try to distinguish clearly between, say, the
class Alpha and its instances. I wouldn't have mentioned it -- it's a bit of
terminological laxness that everyone indulges in from time to time -- except
that you seem to be confusing yourself with it. I suspect that if you had
thought in terms of which /objects/ were doing what, then you would probably
have seen the point I made in the previous paragraph by yourself.)
I was trying to make the distinction clear by using 'Alpha' to designate the
class and 'alpha' to designate the instance but I probably got sloppy and
starting mixing them up at some point....

And you're right; I DO confuse myself sometimes with OO terminology. That's
why I drop in and ask this kind of question on the comp.lang.java.*
newsgroups occasionally; replies like yours help me get back in the habit of
using the right term for the right thing.

Thanks for verifying that I'm not committing a major design blunder by
passing the 'this' reference to instances of Beta :)

Rhino
 
R

Rhino

Bjorn Abelli said:
...

If there's no other relation between an instance of an Alpha and a Beta,
this would be the prefered method, as you then decouple the dependence to
Alpha from a Betas point of view.

If there's a need to have a very long list of values, there are patterns to
deal with this.

One is to encapsulate the needed values into one single object, and to pass
that instead...
I was starting to think along exactly those lines but wasn't sure if that
was good design.

But now that I know it is not bad design to pass an instance of Alpha to a
new instance of Beta via it's constructor, my list of parameters is much
smaller and much more manageable so I don't think I need to pass the
remaining parameters via a single Object.
If the Beta instance *anyway* have a dependency of some sort towards an
instance of Alpha (e.g. if it at some point needs to invoke some method on
the Alpha instance), this would be the prefered method, and simplifies
much...


IMHO I would consider it "ugly", and not thoroughly pondered upon...
Let me explain myself a bit better with more concrete parameters.

The Beta in my scenario is actually a preferences dialog for Alpha and
should probably be called AlphaPreferences, not Beta. Many of the values
AlphaPreferences needs are things that it is sharing with Alpha, such as a
logger and a locale. But some of the values that AlphaPreferences needs are
to know whether it is modal and what its title should be so that the correct
title is placed in its GUI. The logger and locale seem like things that I
should be obtaining from the alpha instance that is passed to
AlphaPreferences via the 'this' reference. But the modal boolean and the
dialog title "feel" different somehow so I am inclined to pass them as
explicit separate parameters.

I'm not sure I can explain why the logger and locale are different than the
modal boolean and the title though. Maybe it is an unimportant distinction.

For what it's worth, AlphaPreferences subclasses JDialog and shares an
interface of constants with Alpha. I don't expect that anyone is ever going
to subclass AlphaPreferences or that any other class but Alpha is ever going
to instantiate AlphaPreferences. (Maybe I should make AlphaPreferences final
to emphasize that; what do you think?)

Should the fact that no class other than Alpha is ever going to instantiate
AlphaPreferences and that no one is ever going to subclass AlphaPreferences
change anything in how I am going to invoke it?

Rhino
 
C

Chris Uppal

Rhino said:
The Beta in my scenario is actually a preferences dialog for Alpha and
should probably be called AlphaPreferences, not Beta. Many of the values
AlphaPreferences needs are things that it is sharing with Alpha, such as a
logger and a locale. But some of the values that AlphaPreferences needs
are to know whether it is modal and what its title should be so that the
correct title is placed in its GUI. The logger and locale seem like
things that I should be obtaining from the alpha instance that is passed
to AlphaPreferences via the 'this' reference. But the modal boolean and
the dialog title "feel" different somehow so I am inclined to pass them as
explicit separate parameters.

I'm not sure I can explain why the logger and locale are different than
the modal boolean and the title though. Maybe it is an unimportant
distinction.

One way to think about it is:

The logger and locale are information that the AlphaPreferences needs in order
to do its job, but it's not an Alpha's business to know exactly what it needs,
only the AlphaPreferences knows that (or should know that). The title and
modal-ness, on the other hand, are part of the definition of the job, and
should -- must -- be provided explicitly from outside.

Try an analogy: Imagine I happen to visit you, and offer to help out with some
redecoration that you are doing. You ask me to hang a picture on a wall. OK,
hanging the picture is my job, it's not /my/ responsibility to decide /which/
picture, nor (probably) on which wall -- that is part of the job definition.
But once I've been given that info, I'll still have to decide how to hang the
picture; if I decide to use a nail and a bit of string, then I'll have to find
them (and a hammer, and possibly a chair to stand on). Finding these things is
also part of my job, it's not for you to tell me where they are -- although I
/may/ decide to come back and ask you "where's a hammer ?" I don't /have/ to.
OTOH, you may decide to make that kind of thing part of the job definition too:
"If you need anything, come and ask me, please don't bother these other people
or go wandering around unattended". You have then set the limits on /where/ I
can look for any resources that I may decide I need, but you haven't tried to
tell me /what/ resources I should use. If instead you had said, "here, take
/this/ hammer, /this/ nail, /this/ length of string, and hang /this/ picture on
/that/ wall" I would probably hit you over the head with the hammer -- or
possibly the picture ;-)

-- chris
 
C

Chris Uppal

Rhino said:
Bjorn's initial reply to my question demonstrates that it is possible; his
approach exactly matched the approach I had used when I finally found that
old example. The code works fine.

I had (mis)understood you to be looking for a "magic" way of finding the caller
without having its identity passed in as a parameter. (Remember that you were
asking about how to get a stack backtrace only a day or two ago.)

You're being facetious, right?

No, not at all, but remember that was under the impression that you were
looking for something much "dirtier" than was actually the case.

But...
Yes, that's exactly what Bjorn's reply called for; the specific instance
of Alpha which was invoking this instance of Beta was passed in Beta's
constructor via a 'this' reference.

At the risk of repeating myself: it isn't part of the contract that the
instance of Alpha that is passed to the Beta constructor /has/ to be the
caller. If that /is/ a requirement, then the design is just as dirty as if you
were using the "magic" I mentioned earlier. But I don't think that it is a
requirement. The new Beta doesn't care /what/ is creating it, it /does/ care
about where it should get necessary information (the Alpha), but it has no
reason to care, or even think, about whether that Alpha is in any way related
to the object that constructed it.

BTW. I'm not trying to tell you that you are doing anything wrong -- I don't
think you are -- just attempting to clarify the issues. You seem to have
pretty good design intuition, but maybe have not yet reached the point where
you entirely trust it, or are able to express /why/ your intuition is right.

-- chris
 
B

Bjorn Abelli

...
The Beta in my scenario is actually a preferences dialog
for Alpha and should probably be called AlphaPreferences,
not Beta. Many of the values AlphaPreferences needs are
things that it is sharing with Alpha, such as a logger and
a locale. But some of the values that AlphaPreferences needs
are to know whether it is modal and what its title should
be so that the correct title is placed in its GUI. The logger
and locale seem like things that I should be obtaining from
the alpha instance that is passed to AlphaPreferences via the
'this' reference. But the modal boolean and the
dialog title "feel" different somehow so I am inclined
to pass them as explicit separate parameters.

To me, this rather sounds that you haven't considered that you possibly
violate the rule of high cohesion...

To me it now sounds like both Alpha and AlphaPreferences is doing "too
much"...

In very small projects, everything can done be within just a few classes,
but with just a slightly more complexity in the application, you just "have"
to separate the "presentation layer" from the "logic".

I sounds to me that you possibly should solve this by doing just that.
I'm not sure I can explain why the logger and locale
are different than the modal boolean and the title though.
Maybe it is an unimportant distinction.
For what it's worth, AlphaPreferences subclasses JDialog and shares an
interface of constants with Alpha. I don't expect that anyone is ever
going
to subclass AlphaPreferences or that any other class but Alpha is ever
going
to instantiate AlphaPreferences. (Maybe I should make AlphaPreferences
final
to emphasize that; what do you think?)

A totally personal opinion of mine is that I'm a bit allergic to final
classes... ;-)

That would inhibit several evolution strategies of an application that
otherwise could be possible in the future...
Should the fact that no class other than Alpha is ever going to
instantiate
AlphaPreferences and that no one is ever going to subclass
AlphaPreferences
change anything in how I am going to invoke it?

I think Chris made a point in the difference between the concepts of class
and object. If there really is that a specific instance of Alpha controls
the behaviour of a specific instance of AlphaPreferences, and that instance
of AlphaPreferences is truly depending on some values of that specific
instance of Alpha...

....then it possibly isn't something else than different "views" on the
*same* object, that it logically isn't different objects...

Maybe you should look over the design to see whether you can separate the
actual logic from the GUI, and see what happens...

// Bjorn A
 
R

Rhino

Chris Uppal said:
I had (mis)understood you to be looking for a "magic" way of finding the caller
without having its identity passed in as a parameter. (Remember that you were
asking about how to get a stack backtrace only a day or two ago.)
Oh, I see! I didn't realize anyone would assume that the two posts were
related but I can see why you'd think they might be. In fact, the problems
are unrelated. [I've solved the stackTrace thing quite simply by generating
a new Exception whenever one didn't exist; that Exception is passed to the
Logger via logp(..., Throwable) and the Logger classes magically create a
stackTrace for the fake exception.]
No, not at all, but remember that was under the impression that you were
looking for something much "dirtier" than was actually the case.

But...


At the risk of repeating myself: it isn't part of the contract that the
instance of Alpha that is passed to the Beta constructor /has/ to be the
caller. If that /is/ a requirement, then the design is just as dirty as if you
were using the "magic" I mentioned earlier. But I don't think that it is a
requirement. The new Beta doesn't care /what/ is creating it, it /does/ care
about where it should get necessary information (the Alpha), but it has no
reason to care, or even think, about whether that Alpha is in any way related
to the object that constructed it.
I'm not sure I understand you. As I mentioned in the other subthread, Alpha
is actually instantiating AlphaPreferences and some of the information that
AlphaPreferences needs is the Logger and Locale instances that the specific
instance of Alpha is using. I want AlphaPreferences to write log messages to
the same physical file and to display text in the same language as it used
in Alpha. I recognize that those are just *my* desires for this particular
case though. It would certainly be possible that some other program invoking
AlphaPreferences might want to direct it to use a different Logger and
Locale or prompt the user for a Logger and Locale that it should use
(although I don't expect anyone other than Alpha to ever want to invoke
AlphaPreferences). Is that what you mean when you say that the Logger and
Locale are - or are not - a requirement?

So where do we stand? Is the solution Bjorn suggested a good one for me to
use? Or should I be doing things differently?

Maybe more to the point, WHY is his solution good or bad for me and why is
an alternative better or worse?

BTW. I'm not trying to tell you that you are doing anything wrong -- I don't
think you are -- just attempting to clarify the issues. You seem to have
pretty good design intuition, but maybe have not yet reached the point where
you entirely trust it, or are able to express /why/ your intuition is right.
I think you're right on the money; I sometimes/often feel that I'm on the
right track but I'm definitely NOT confident that I am thinking of things
correctly. I just took an hour or so to read in the Java Design Patterns
website - http://www.patterndepot.com/put/8/JavaPatterns.htm - but found
myself getting slightly dizzy (metaphorically speaking) as I tried to digest
what Cooper was saying. All indepth OO conversations cause the same
'dizziness' for me, even when they are relatively well written like Cooper's
stuff. :)
 
R

Rhino

Chris Uppal said:
One way to think about it is:

The logger and locale are information that the AlphaPreferences needs in order
to do its job, but it's not an Alpha's business to know exactly what it needs,
only the AlphaPreferences knows that (or should know that). The title and
modal-ness, on the other hand, are part of the definition of the job, and
should -- must -- be provided explicitly from outside.
I'm tempted to phrase that as follows: Alpha insists that AlphaPreferences
uses a specific name and modal-ness and provides it explicitly but doesn't
much care where AlphaPreferences gets a Logger or Locale as long as it gets
one. But that doesn't really work either, at least to me. Logger and Locale
are getting derived from the instance of Alpha that was passed to
AlphaPreferences; that instance is being passed for SOME reason, presumably
so that AlphaPreferences can do its thing.

The design aspect here has me confused; if I'm the guy writing the specs for
AlphaPreferences, I'd probably say _something_ about where it should get its
Locale and Logger. Wouldn't I say that it should use the same Logger and
Locale as Alpha, as opposed to using a default that might not be appropriate
or prompting the user for his choices of Locale and Logger? I might not say
that this information had to be passed via explicit separate parameters and
simply leave it up to the developer to decide if he wanted to pass separate
parameters or just pass the entire Alpha instance which he could then
interrogate for the Logger and Locale. Or maybe pass ALL of the values
needed by the constructor in a separate class?

See this is why my head hurts (metaphorically) when I try to decide what I
should be doing ;-)

Try an analogy: Imagine I happen to visit you, and offer to help out with some
redecoration that you are doing. You ask me to hang a picture on a wall. OK,
hanging the picture is my job, it's not /my/ responsibility to decide /which/
picture, nor (probably) on which wall -- that is part of the job definition.
But once I've been given that info, I'll still have to decide how to hang the
picture; if I decide to use a nail and a bit of string, then I'll have to find
them (and a hammer, and possibly a chair to stand on). Finding these things is
also part of my job, it's not for you to tell me where they are -- although I
/may/ decide to come back and ask you "where's a hammer ?" I don't /have/ to.
OTOH, you may decide to make that kind of thing part of the job definition too:
"If you need anything, come and ask me, please don't bother these other people
or go wandering around unattended". You have then set the limits on /where/ I
can look for any resources that I may decide I need, but you haven't tried to
tell me /what/ resources I should use. If instead you had said, "here, take
/this/ hammer, /this/ nail, /this/ length of string, and hang /this/ picture on
/that/ wall" I would probably hit you over the head with the hammer -- or
possibly the picture ;-)
You're not a trainer by any chance, are you? You certainly have a ready gift
for devising good, clear metaphors ;-)

Rhino
 
R

Rhino

Bjorn Abelli said:
...


To me, this rather sounds that you haven't considered that you possibly
violate the rule of high cohesion...
Sorry, I don't know that rule. Can you possibly state it (briefly)?
To me it now sounds like both Alpha and AlphaPreferences is doing "too
much"...
That's possible. I first learned programming and design back in the
structured programming days and I probably still think that way more than I
think in OO. How can I tell if a class is doing too much? There must be some
kind of rule of thumb, like more than 10 methods or more than 20 class
variables or more than 500 lines of code....
In very small projects, everything can done be within just a few classes,
but with just a slightly more complexity in the application, you just "have"
to separate the "presentation layer" from the "logic".

I sounds to me that you possibly should solve this by doing just that.
Perhaps. The existing design "feels" right to me but I don't necessarily
have the right instincts. To me, it makes sense that all of the code needed
to change the preferences in Alpha be put into a separate class called
AlphaPreferences. AlphaPreferences instantiates several smaller classes to
do some of its job, like panels to change text preferences or choice box
options or images used in Alpha's GUI. There doesn't seem to be much
duplication or overlap between Alpha and AlphaPreferences so it feels like
the code is organized properly. I'm just struggling with the best ways to
get information from one to the other.
A totally personal opinion of mine is that I'm a bit allergic to final
classes... ;-)
Fair enough; I just mentioned the 'final' bit on the theory that it's
probably a big no-no to omit 'final' if you don't want that class to be
extended at some point.
That would inhibit several evolution strategies of an application that
otherwise could be possible in the future...
But I can see that 'final' does prevent extending the class if I do decide
to subclass at some point in the future.
I think Chris made a point in the difference between the concepts of class
and object. If there really is that a specific instance of Alpha controls
the behaviour of a specific instance of AlphaPreferences, and that instance
of AlphaPreferences is truly depending on some values of that specific
instance of Alpha...

...then it possibly isn't something else than different "views" on the
*same* object, that it logically isn't different objects...

Maybe you should look over the design to see whether you can separate the
actual logic from the GUI, and see what happens...
So I should think of rolling the code from AlphaPreferences back into
Alpha??

I have to say that "feels" wrong: Alpha and AlphaPreferences each have their
own GUIs and, by the nature of preferences, the AlphaPreferences GUI is much
more complex than the Alpha GUI. Whereas Alpha's GUI is pretty simple,
AlphaPreferences is a JTabbedPane with 7 panes on it where each of those
tabs has its own kind of preferences on it. For example, one tab let's you
enable or disable features via checkboxes; another tab lets you choose
different images to use in Alpha; another tab lets you choose different
background Colors for the components shown in Alpha, etc.

My gut hunch says that each GUI should have its own class to control what
its doing.

Or have I misunderstood you?

I know it must be hard for you to discuss this without actually seeing any
code. My simplifications and generalizations may not be giving you a really
good sense of what the code actually does.

Maybe I need to read the MVC theory again to see if I'm putting the right
code in the right places. I don't really *THINK* in terms of Models, Views
and Controllers when I right Java - except when I use JFC components like
JList, which use them - so maybe I've made some fairly big mistakes in
splitting the code into different classes.

As I said, the code "feels" right but that might be my structured design
instincts approving what I've done, not good OO theory.

Rhino
 
B

Bjorn Abelli

...
Sorry, I don't know that rule. Can you possibly state it (briefly)?

Shortest possible:

An instance of a specific class should do what
it should do, and nothing else...

;-)

The concept of "high cohesion" simply states that a single class shouldn't
have too much responsibilities.

It's rather easier to contrast that with the concept of "low cohesion",
where the worst form is "coincidental cohesion", where parts of a module are
grouped arbitrarily.

http://en.wikipedia.org/wiki/Cohesion
That's possible. I first learned programming and design back in the
structured programming days and I probably still think that way
more than I think in OO. How can I tell if a class is doing too much?
There must be some kind of rule of thumb, like more than
10 methods or more than 20 class
variables or more than 500 lines of code....

Nope, the key to the division lies not in number of methods or lines of
code, but in the *purpose* of those methods and lines...

This is discovered when doing a thorough OO analysis, and OO design...
So I should think of rolling the code from
AlphaPreferences back into Alpha??

No, no, no...

Well, maybe *parts* of it...

But I couldn't really say without taking a look on *all* of the code, which
I don't have any intention to do... ;-)
I have to say that "feels" wrong: Alpha and AlphaPreferences each have
their
own GUIs and, by the nature of preferences, the AlphaPreferences GUI is
much
more complex than the Alpha GUI. Whereas Alpha's GUI is pretty simple,
AlphaPreferences is a JTabbedPane with 7 panes on it where each of those
tabs has its own kind of preferences on it. For example, one tab let's you
enable or disable features via checkboxes; another tab lets you choose
different images to use in Alpha; another tab lets you choose different
background Colors for the components shown in Alpha, etc.

My gut hunch says that each GUI should have its own class
to control what its doing.

Absolutely! It might even be the case that a single GUI itself should be
composed of instances of *several* classes, each specialized on its own
task.
Or have I misunderstood you?

Possibly.

To me it rather sounds that what you call Alpha should be split into at
least an Alpha and an AlphaGui, where Alpha is used by both an AlphaGui and
an AlphaPreferences!

It could even be possible that AlphaPreferences should be split into
AlphaPreferences and AlphaPreferencesGUI, where AlphaPreferences have an
association to an Alpha, or vice versa...

Or, in the latter scenario, that you end up with an Alpha, an AlphaGUI, and
an AlphaPreferencesGUI.
I know it must be hard for you to discuss this without
actually seeing any code. My simplifications and
generalizations may not be giving you a really
good sense of what the code actually does.

You're absolutely right there... ;-)
Maybe I need to read the MVC theory again to see if I'm
putting the right code in the right places. I don't
really *THINK* in terms of Models, Views and Controllers
when I right Java - except when I use JFC components like
JList, which use them - so maybe I've made some fairly
big mistakes in splitting the code into different classes.

Well, MVC is only a tiny, tiny part of OO, it's more of a theory used for
implementation of just a specific kind of pattern used in OO. There's much
more to OO than MVC...

And as I said above, I rather suspect that you're using too *few* classes...
;-)

// Bjorn A
 
J

John C. Bollinger

Rhino said:
if you


I'm not sure I understand you. As I mentioned in the other subthread, Alpha
is actually instantiating AlphaPreferences and some of the information that
AlphaPreferences needs is the Logger and Locale instances that the specific
instance of Alpha is using. I want AlphaPreferences to write log messages to
the same physical file and to display text in the same language as it used
in Alpha. I recognize that those are just *my* desires for this particular
case though. It would certainly be possible that some other program invoking
AlphaPreferences might want to direct it to use a different Logger and
Locale or prompt the user for a Logger and Locale that it should use
(although I don't expect anyone other than Alpha to ever want to invoke
AlphaPreferences). Is that what you mean when you say that the Logger and
Locale are - or are not - a requirement?

Chris' point is perhaps a bit subtle. It is not directly about the
approach you propose, but rather about the assumptions that the code you
write should be allowed to make. In particular, I believe Chris is
saying that AlphaPreferrences should not assume that the Alpha passed to
its constructor is in any way related to the object that triggered the
constructor. It should be equally valid for any object of any class to
construct an AlphaPreferrences, passing any old Alpha that it happens to
take a liking to. Such behavior may turn out to not be useful, but it
is a design error for AlphaPreferrences to assume that it will not happen.
 
C

Chris Uppal

Rhino said:
I think you're right on the money; I sometimes/often feel that I'm on the
right track but I'm definitely NOT confident that I am thinking of things
correctly. I just took an hour or so to read in the Java Design Patterns
website - http://www.patterndepot.com/put/8/JavaPatterns.htm - but found
myself getting slightly dizzy (metaphorically speaking) as I tried to
digest what Cooper was saying. All indepth OO conversations cause the
same 'dizziness' for me, even when they are relatively well written like
Cooper's stuff. :)

If you want my advice, then don't get too hung up on it. OO is supposed to be
simple and natural, if someone is puzzling you then there's a good chance that
it's /their/ fault.

For me, it's all about objects. Each object has a job to do. It is allowed to
call in its friends to help it. The friends will also be given jobs to do, and
may in turn call in /their/ friends. And so on... I find that it helps to
think about jobs and the objects that do them in /very/ anthropomorphic
terms -- as if they were real people, or at least characters in a favourite
story. If you do that then your focus is on what objects are needed, and on
what jobs they do, and on what information they pass between them, and when.
You are not thinking about "classes" (which are an implementation technology
/for/ objects). You are not thinking about code (which is just how you talk to
the compiler). You are not worrying about Design Patterns. Nor about whether
you are producing a "proper" OO design (since you are thinking only, or mostly,
about /objects/ your design /must/ be proper OO ;-)

It may turn out not to be a very good design, but it won't be bad because it's
"not OO", it'll be bad because you forgot something, or because requirements
changed in a way you hadn't planned for. And even if it /does/ turn out to
need changing, then there's still a good chance that, because you've been
thinking in terms of the jobs that need doing (rather than, say, "what Design
Pattern should I use") that the changes to the design will be simple and
localised -- because it's not likely that the /jobs/ will change much.

Of course, I'm pushing my own theory of OO programming here. If you find my
viewpoint puzzling or worrying, then heed the advice in my first paragraph and
just ignore me...

BTW. I hadn't read the book you mentioned above. I've had a look at the
Background chapter, and am not immediately impressed. For instance the
paragraph:

First, you accept the premise that design patterns are important in
your work. Then, you recognize that you need to read about design
patterns in order to know when you might use them. Finally, you
internalize the patterns in sufficient detail that you know which ones
might help you solve a given design problem.

is prescriptivist nonsense. It's perfectly possible to be a good designer, or
a great designer, or even a great /OO/ designer, without ever thinking about
Patterns. That's where patterns /come from/. Patterns are useful tools for
working programmers, no question. But IMO what they provide is a shared
vocabulary for talking /about/ designs. You don't start with a Pattern and
then apply it to a design, you start with a design and then ask what common
patterns are present in it. If you want to tell someone about your design,
your can tell them about the patterns -- it'll be easier for you to describe,
and easier for them to understand. Or if someone is suggesting a modification
to a design, they may describe it terms of named patterns.

But when some "authority" claims that you need to learn the patterns ("/which/
patterns?" I demand in exasperation) in order to be a good designer, then they
are talking dangerous poppycock. It may be true, for some programmers, that
having a "toolkit" of patterns helps them to think about designs, but even then
you don't just sit down and learn the patterns. I mean, imagine if learning
carpentry were like that: first you learn about hammers, then about saws, then
about planes, then chisels, then... And finally, having leaned about all the
tools (and got a certificate to hang on your workshop wall), you are at last
allowed to touch some real wood.

I'm not saying there's anything wrong with the book's presentation of the
patterns themselves. I haven't looked that far yet, it may be -- probably
is -- perfectly fine. But don't let the book sucker you into thinking that the
act of design consists, even in part, of choosing between available patterns.
That would make /anyone/ dizzy.

Just tell the objects what jobs you want 'em to do, and then let 'em get on
with it...

<end of rant>

-- chris
 
C

Chris Smith

Hmm... Hope you don't mind if I jump in.

Chris said:
It's perfectly possible to be a good designer, or
a great designer, or even a great /OO/ designer, without ever thinking about
Patterns. That's where patterns /come from/.

Yes! Completely in agreement so far, and it's refreshing to hear
someone else say that...
Patterns are useful tools for
working programmers, no question. But IMO what they provide is a shared
vocabulary for talking /about/ designs.

Whoops, now I think you're entirely wrong. Oh well, it was good while
it lasted! :) It's become one of my pet peeves to hear people talk
about patterns names in design discussions. There are a few reasons for
this.

First, with a few notable exceptions, the names aren't all that
standardized. Although GoF is a hugely popular book, there are still
other fairly well-established books (e.g., PLoPD) that provide different
names for many of the same basic ideas.

Second, and far worse, books often provide the same name for patterns
but show different low-level choices, and it's easy for anyone but the
pattern expert to confuse the name with this book's irrelevant
implementation choices. Invariably, this causes confusion as someone
thinks that the team just agreed on a bad design... and then implements
it that way!

Third, even if the books do happen to agree about the details of a
pattern, trying to use pattern names ends up being COUNTER-productive by
blinding developers to possible design choices. Any one of the smart
people who started this whole "patterns" idea will tell you that a
design pattern balances good and bad aspects of a design, and that each
different circumstance may merit a somewhat different balance. The
popularization of the idea seems to have lost that, and the "oh, this
just uses the Abstract Factory pattern" phenomenon seems to be a big
part of the problem.

#3 is especially bad when the pattern name was previously used for a
more general concept (for example, "proxy" and "factory"). I've seen
environments where developers are berated for using the word "proxy" to
apply to anything that doesn't fit the GoF book's description. It get's
silly and demoralizing.

If you ask me, here's what you should do with any design patterns book.

1. Read it. Focus especially on the discussion of WHY the pattern is a
good idea, not just what it looks like.

2. Try it out. Write some test code in a concrete situation that
implements the patterns. Try to REALLY understand the pattern and what
it provides you. Try some different implementations, if possible.

3. Forget it. Now pretend you haven't read the book. Go about design
by looking at problems and finding problem-specific solutions. If the
book was any good, you may be better at finding solutions... but don't
use them because you recognize them from the book. Use them because
they solve your problems.

Incidentally, this is the same advice I have regarding Martin Fowler's
book Refactoring (at least, the catalog section of it), and to a lesser
extent Joshua Bloch's book Effective Java.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
T

Tony O'Bryan

Chris said:
Yes! Completely in agreement so far, and it's refreshing to hear
someone else say that...

I've been programming for 20 years in a variety of languages, and never
really paid much attention to my own programming style. It's only been in
the last two years or so that I've even thought about it.

In the last couple years, much ado has been made about Extreme Programming,
Agile Programming, and Patterns. When I started reading about them, I was
amazed to find that they were all defining how I've been programming all
along.

It was amusing because I had been putting off reading about them since I
thought it was going to take too much time away from actually doing stuff.
It turns out that the techniques I came up with on my own out of necessity
are the very same techniques that are so buzzword friendly today.

It's eerie to hear my coworker describe a pattern from TGoF and get excited
about the "new" possibilities being uncovered. I have to force myself,
time and again, to not repeat what has become my mantra at work: "That's
the way I've always done it."
 
C

Chris Uppal

Chris said:
Whoops, now I think you're entirely wrong. Oh well, it was good while
it lasted! :)

Well, we're obviously not in complete agreement, but I don't think the
/dis/agreement is all that complete either...

First, [...]

Second, and far worse, [...]

Third, [...]

And fourth: the GoF pattern names are often poorly chosen. Also the selection
of design idioms to name as "top level" Patterns seems pretty arbitrary. E.g.
the whole raft of proxy/adaptor/facade/etc seem to me to be fairly trivial
variations on a theme -- giving them separate names might have academic
value[*], but in practice is more confusing than helpful. In fact I rarely
bother to remember which is which.

([*] But as a purely academic classification I'd rather see a fully
hierarchical scheme than an almost flat list.)

But going back over your points:

First, with a few notable exceptions, the names aren't all that
standardized. Although GoF is a hugely popular book, there are still
other fairly well-established books (e.g., PLoPD) that provide different
names for many of the same basic ideas.

Well, as I've said, I think that the value of patterns is as a vocabulary (the
above criticism of the names notwithstanding), and in the Darwinian world of
competing jargon it seems (to me, anyway) that the "other" pattern sources are
stillborn. I hear people using GoF-names, but not names from other books.
Which is at it should be -- the idea is to have as /few/ pattern names as
possible, not to try to find names for every possible combination of ideas. We
are not attempting a complete classification of design-space, just (trying to)
make it easier to communicate amongst ourselves.

BTW, I don't think there are many good sources of pattern names (even ignoring
the previous paragraph). I have certainly not read all the books with
"pattern" in the title, nor followed the pattern community's efforts, but from
the small sample of pattern writings I have seen, the breakdown seems to be:
a) Useful and popular[**] catalogues of patterns. This set has only one
member.
b) Language-specific rehashes of members of (a).
c) Books which, while being good books about design and/or implementation
issues, don't contribute much to the pattern vocabulary. (PoSA2 is a good
example of this. Read as a discussion of the issues and options in the design
of TAO it is good; read as a pattern catalogue it is distinctly unimpressive).
d) Texts which use the expression "pattern language". These are widely (and
correctly, IMO) ignored.

([**] Note that being popular is a necessary precondition for being useful)

Second, and far worse, books often provide the same name for patterns
but show different low-level choices, and it's easy for anyone but the
pattern expert to confuse the name with this book's irrelevant
implementation choices. Invariably, this causes confusion as someone
thinks that the team just agreed on a bad design... and then implements
it that way!

Agreed. I use pattern names myself, since I think they are useful, but only
(and deliberately) rather loosely. E..g. I'll talk of Singleton, even though I
don't prohibit creating other instances (a better name would be "distinguished
instance", but no language is much use if you make it up yourself ;-)

A few years ago I worked with an experience and quite competent programmer who
liked to keep a copy of GoF on his desk so that he could "get the method names
right"...

#3 is especially bad when the pattern name was previously used for a
more general concept (for example, "proxy" and "factory"). I've seen
environments where developers are berated for using the word "proxy" to
apply to anything that doesn't fit the GoF book's description. It get's
silly and demoralizing.


Yes, that is a problem. Or rather, I'm willing to believe that such problems
occur -- I haven't experienced that situation myself (yet -- touch wood).

If you ask me, here's what you should do with any design patterns book.
1. [...]

My take:

1) Skim it. Slow down and read more carefully if anything grabs your
attention. Ignore diagrams and discussions of implementation techniques unless
they /actually/ help you understand the pattern. Try to think of occasions
where you have already used or seen the design idiom that the pattern names.
Chances are that unless you are a complete beginner to programming (not just to
OO) you will have seen a lot of them before in some guise or other. Pay closer
attention to such cases -- /this/ is where you may start to feel the value of
abstracting the pattern (as a concept in its own right) away from the detailed
context(s).

2) Put the book on a shelf. Display it prominently if you feel so inclined.
Leave it there.

3) Use any pattern names that happen to stick in your memory, especially if
they are names for design idioms that you like to use, or if they are just
plain catchy.

4) When someone else uses a pattern name, sneak off somewhere and re-skim the
relevant section of the book. Or ask them to explain -- much better, if you
have the confidence.

In due course you will converge to a loose consensus of vocabulary with the
people you work with. Patterns will now start to work for you. (Or not, if
your experience is more like Chris's than mine.)

Incidentally, this is the same advice I have regarding Martin Fowler's
book Refactoring (at least, the catalogue section of it),

Ugh yes (with the same caveat). The only reason to /identify/ a refactoring,
let alone name it, is so that tools like Eclipse can have long menus of
refactoring operations (which I never use[***]).

([***] I have always been a dedicated and enthusiastic code-shuffler, but when
I'm bending code from <this> shape to <that> shape, the last thing I want is to
have to express the new design as a delta from old to new, especially not in
the more-or-less impoverished language of established refactorings. I just
change the code.)

-- chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top