Best Way to Pass Info Between Objects?

N

Novice

Sorry, that's probably not the best of subject lines but I'm having trouble
coming up with a concise one....

I'm trying to reason out the best way to pass information from an
instantiating class to an instantiated class. So, let's say class Foo
invokes class Bar to do something. Bar needs some specific information from
Foo to do its job. What is the best way to pass this information from Foo
to Bar?

For instance, Foo is a class that is used to edit a table of information
presented as a JTable. Bar is a class that is used when a new row needs to
be inserted into the table. The person using Foo right-clicks, chooses
"Insert" on the context menu, and Bar gets instantiated to display a dialog
with input fields so that the user can supply the values for a new row of
the JTable.

Bar needs various things to do its job. Among these are:
- the locale to be used since Bar can display its text in various languages
- the logger to be used for error messages
- a reference to Foo since Bar wants to know the parent JFrame
- the title of the dialog

There are obviously various techniques for passing information from Foo to
Bar. You can put the information in the paramater list. You can use getters
to obtain the information from Foo. You can make values in Foo accessible
to Bar by making the public so that Bar can access them directly. All of
these methods can and do get used in Java.

What are the rules of thumb to use in deciding which techniques to use in
any given case?

Clearly parameter passing is used widely but parameter lists tend to be
short, mostly in the 0 to 4 parameter range. How do you decide which of the
possibly many things needed by class Bar get passed as parameters and which
get passed via getters or accessed directly from Foo?

My strong impression is that it's bad form to access variables directly in
Foo and that getters are preferred, but please correct me if I'm wrong. But
I still don't quite see when you prefer passing something in a parameter
list rather than via a getter.

I'm not sure if there is a generally agreed-upon formula here or whether it
is more a case of individual style and preference. I'd be very interested
in your comments on this subject. Right now, I feel like I'm being pretty
inconsistent in my techniques and would like to standardize them along the
best possible lines.
 
S

Stefan Ram

Novice said:
I'm trying to reason out the best way to pass information from an
instantiating class to an instantiated class.

This derives from the design patterns used. Read, for example:

Craig Larman, Applying UML and Patterns

Martin Fowler, Refactoring: Improving the Design of
Existing Code,

Gamma et al., Design patterns

also

Patterns of Enterprise Application Architecture by Fowler

Object Oriented Software Construction by Bertrand Meyer

Object Oriented Software Engineering by Ivar Jacobson

Grady Booch. "Object-oriented Analysis and Design with
Applications, 3rd edition"

Rebecca Wirfs-Brock, Brian Wilkerson, Lauren Wiener.
Designing Object Oriented Software. Prentice Hall, 1990.

Martin Fowler. Analysis Patterns: Reusable Object
Models.

Brett McLaughlin, Gary Pollice, David West. Head First
Object-Oriented Analysis and Design.

Fundamentals of object oriented design and UML
(Meilir Page-Jones)

Patterns oriented software architecture (Douglas Schmidt)
 
N

Novice

Here is one programming process approach that often simplifies these
questions: Write the Bar unit tests in parallel with designing Bar.

If the Bar design works well for both unit testing and use by a Foo,
it will probably be a reasonably robust module that does not need to
be changed too often because of changes to other modules.

Patricia

Thanks everyone for the suggestions. Obviously, I'm going to need to
increase the size of my Java library and allocate some time for reading all
all of these things....

But in the meantime, are there any general rules I can use to make these
decisions for code I am developing now? Or do I really need to master
several books first?
 
J

Jeff Higgins

Sorry, that's probably not the best of subject lines but I'm having trouble
coming up with a concise one....

I'm trying to reason out the best way to pass information from an
instantiating class to an instantiated class. So, let's say class Foo
invokes class Bar to do something. Bar needs some specific information from
Foo to do its job. What is the best way to pass this information from Foo
to Bar?
Look at the API of an open source project similar to yours. Or even a
dissimilar one. I use Eclipse, others Netbeans, both have an API that
you can study.
 
M

markspace

But in the meantime, are there any general rules I can use to make these
decisions for code I am developing now? Or do I really need to master
several books first?


Loose Coupling is one such general rule.

<http://en.wikipedia.org/wiki/Loose_coupling>

This is basically what Patricia is advocating, as classes that are
loosely coupled tend also to be easier to unit test.

For example, you seem to have a lot of different (and fairly complex)
classes running around your code right now. One way to simplify unit
testing is to use mock objects.

<http://www.ibm.com/developerworks/library/j-mocktest/index.html>

There's some good links in both of those articles to get you started.
 
J

Jeff Higgins

Sorry, that's probably not the best of subject lines but I'm having trouble
coming up with a concise one....

I'm trying to reason out the best way to pass information from an
instantiating class to an instantiated class. So, let's say class Foo
invokes class Bar to do something. Bar needs some specific information from
Foo to do its job. What is the best way to pass this information from Foo
to Bar?

For instance, Foo is a class that is used to edit a table of information
presented as a JTable. Bar is a class that is used when a new row needs to
be inserted into the table. The person using Foo right-clicks, chooses
"Insert" on the context menu, and Bar gets instantiated to display a dialog
with input fields so that the user can supply the values for a new row of
the JTable.

Bar needs various things to do its job. Among these are:
- the locale to be used since Bar can display its text in various languages
- the logger to be used for error messages
- a reference to Foo since Bar wants to know the parent JFrame
- the title of the dialog

There are obviously various techniques for passing information from Foo to
Bar. You can put the information in the paramater list. You can use getters
to obtain the information from Foo. You can make values in Foo accessible
to Bar by making the public so that Bar can access them directly. All of
these methods can and do get used in Java.

What are the rules of thumb to use in deciding which techniques to use in
any given case?

Clearly parameter passing is used widely but parameter lists tend to be
short, mostly in the 0 to 4 parameter range. How do you decide which of the
possibly many things needed by class Bar get passed as parameters and which
get passed via getters or accessed directly from Foo?

My strong impression is that it's bad form to access variables directly in
Foo and that getters are preferred, but please correct me if I'm wrong. But
I still don't quite see when you prefer passing something in a parameter
list rather than via a getter.

I'm not sure if there is a generally agreed-upon formula here or whether it
is more a case of individual style and preference. I'd be very interested
in your comments on this subject. Right now, I feel like I'm being pretty
inconsistent in my techniques and would like to standardize them along the
best possible lines.
From your posts asking for help with your table, one thing hasn’t
become clear to me. What about your 'information'? Surely the be-all and
end-all of your information is not display in a table. Who uses the
information, where do you store it, how do you access it? If you are
very clear on the structure and use of your information the CRUD will be
much easier to visualize.
 
J

Jeff Higgins

From your posts asking for help with your table, one thing hasn’t
become clear to me. What about your 'information'? Surely the be-all and
end-all of your information is not display in a table. Who uses the
information, where do you store it, how do you access it? If you are
very clear on the structure and use of your information the CRUD will be
much easier to visualize.
Often when you are considering a UI widget the best place to start
designing is the widget's data model. The widget's data model is a
temporary store for information coming into your application or out for
display.
 
L

Lew

Novice said:
Parameters.


But in the meantime, are there any general rules I can use to make these
decisions for code I am developing now? Or do I really need to master
several books first?

Mastery can occur in a flash. Knowledge takes longer, but key points will
carry you as far as you need in the short term.

If you read /Effective Java/ as Volker Borchert recommended, you will have
enough to make you competent, provided you understand and practice Joshua
Bloch's suggestions.

What follows is a long and detailed answer that incorporates what others have
told you and provides specific examples. I have not actually compiled these
examples, but I intended them to be compilable.

Summary:

It's all about the model (types, attributes, behaviors).

You should program in terms of interfaces and generics with interface parameters.

Express your model in terms of experiments to try to break it. Those are tests.
Write an interface for each type you're modeling. Too much in the interface?
Refactor. A type should be cohesive.
Write a test class for the interface. You can write it one test method at a
time, but the test class will eventually cover all public (and protected)
methods of the implementation.
Write the minimum compilable implementation of the interface so you can run
the tests.
Observe the test failures.
Fix it.
Often fixing the test failure means a modification to the test class, just as
we added the explicit test for the constructor failure in the example.
Repeat until the whole type passes all tests.

That cycle applies any time the type or an implementation of it changes. A
smart developer uses a continuous-integration tool like Hudson or many others
to rerun a test suite any time changes are checked in to version control.

One last thing - be pretty familiar with the classes in the java.lang.* and
java.util.* packages, especially the collections framework.

Long answer:

You have to map out the behaviors correctly, then the methods and constructors
make sense. Don't send a person's name, address, favorite color, medical
history and descriptions of pets as discrete parameters, but as properly
modeled objects:

register(Person person, Collection<Pet> pets)

The signature is concise and easy to read, yet the parameters can manipulate
quite a lot of data. Constructors can be a little hairier because they
assemble such disparate particles, but even those should be modeled:

public Person(Name name, Calendar dob,
Collection<Relationship> relationships)

Where you absolutely must specify lots of teeny little things to build an
object, use a builder that ultimately returns the desired type, preferably as
an immutable target.

String message = new StringBuilder("This is the ").append(count)
.append("th inference since ").append(formatter.format(rememberWhen))
.append('.').toString();

Programming is as much or more a way of thinking about problems as it is
coding. Anyone can write code, but you still need the right code.

This comes from how you model the scenario or process or whatever you seek to
express in a program. As you model your problem space, look for patterns as
Stefan Ram recommended, not just the formal ones in the literature but in
general terms. I call it "nouns and verbs" - what are the actors (nouns) and
their attributes (adjectives) and their behaviors (action verbs). Nouns are
types, attributes are getters (accessor methods) and setters (mutator
methods), and action verbs are behavioral methods.

Here's a Person type (noun) with just one attribute (adjective), how it's named:

public interface Person
{
String getName();
}

Without a very good reason otherwise, all attributes should be 'getX()' only,
not 'setX(X x)'. Then you make the underlying variable 'final' and immutable
as well.

Now express your model as experiments, or tests - "if I return a person's name
(attribute 'getName()') I will never get a 'null'." For this you'll need an
interface to express the type:

and a unit test:

import static org.junit.Assert.assertNotNull;
import org.junit.Before;
import org.junit.Test;

public class PersonTest
{
Person person;
@Before public void initialize()
{
person = new PersonImpl();
}

@Test public void testGetName()
{
assertNotNull("null name", person.getName());
}
}

Oh, that means you need a 'PersonImpl'. Go barebones at first; let the test
fail with the very minimum code needed to compile.

public class PersonImpl implements Person
{
@Override
public String getName()
{
return null;
}
}

Gosh, how can you make the test pass? Guess you'd better give that Person a
name. Better make it read-only!

public class PersonImpl implements Person
{
private static final String name;

public Person(String name)
{
this.name = name;
}

@Override
public String getName()
{
return name;
}
}

That forces a change to the test:

public class PersonTest
{
Person person;
@Before public void initialize()
{
person = new PersonImpl();
}

@Test public void testGetName()
{
Person person = new Person(null);
assertNotNull("null name", person.getName());
}
}

Oh, we really should expect an exception if you try to instantiate a 'null'
name. Write the test first.

public class PersonTest
{
private static final String TEST_NAME = "Jan Doe";

Person person;

@Test(expected=IllegalArgumentException.class)
public void testGetNameNull()
{
Person person = new Person(null);
}

@Test public void testGetName()
{
Person person;
try
{
person = new Person(TEST_NAME);
}
catch (Exception exception)
{
fail("unexpected exception. " + exception.getLocalizedMessage());
}
assertNotNull("null name", person.getName());
}
}

Now change the implementation to pass the test:

public class PersonImpl implements Person
{
private static final String name;

public Person(String name)
{
if (name == null)
{
throw new IllegalArgumentException("null name");
}
this.name = name;
assert this.name != null
}

@Override
public String getName()
{
assert this.name != null
return name;
}
}

The 'assert' keyword marks where the algorithm depends on certain facts, in
this case the non-nullity of the 'name' attribute. It's a postcondition of
the constructor and a precondition of the getter.

It's a lot of frakkin boilerplate in the implementation, or concrete class. I
prefer to think of it as armor plate. Anyway, once you've set all the castle
guards at the concrete class, you use the interface for general programming:

public class CountryClub
{
private final Set<Person> members = new HashSet<Person>();

public boolean addMember(Person person)
{
if (isUnqualified(person))
{
throw new SnobException("We do not find " + person + " suitable.");
}
return members.add(person);
}

public String showMembers()
{
return members.toString();
}

private boolean isUnqualifed(person)
{
return person.getName().equals("Lew");
}
}

By the way, that SnobException message and 'showMembers()' show us the need
for a 'Person#toString()' method, and if you read /Effective Java/ you see
that that goes hand-in-glove with 'equals(Object other)', 'hashCode()' and
'compareTo(Person other)' (if the type is 'Comparable'). All four (or three
if not 'Comparable') methods must agree on what makes one 'Person' different
from another. (Hint: In this simple model the name attribute should be
unique, so equality and hash will be based entirely on the name, and
'toString()' will return the name.)

You can write a test for that.

There you go, mastery in a flash.
 
M

Martin Gregorie

That is why I suggested unit test during design, as a complement to the
book recommendations. I have no problem with the books that have been
proposed, but it will take time to read, absorb, and apply them. You can
apply unit test during design immediately.
+1

...but don't forget that the unit tests *must* be written from the
specifications and *NEVER* from looking at the code. A good half-way
house, which I use a lot, is to write what's effectively an abstract
class with the entire class specification spelled out in the class- and
method-level comments, with just enough meat in the methods, i.e. return
statements, to allow the resulting source file to be compiled. Then I
generate the javadocs and use only these as the basis for writing the
unit tests.

Actually, I've usually completed and compiled the class before I write
the unit tests, but I'd suggest you write the tests first until you get
into the required 'no peeking' frame of mind needed for writing the tests
from the specifications and only the specifications. There are two
additional benefits: (1) you get into the habit of writing worth-while
class and method documentation and (2) this forces you to think about how
your new class will actually be used. This will probably improve both the
design and documentation if you alter the design to overcome usability
problems as you find them.
 
J

Jeff Higgins

Look at the API of an open source project similar to yours. Or even a
dissimilar one. I use Eclipse, others Netbeans, both have an API that
you can study.
For instance in the Eclipse API: Resources have Markers, Markers are
displayed in many Views including Tasks view, Problems view, to name two
table views. In these cases the IMarkers are displayed as records(rows).
Notice the editing interface exposed on these views.
org.eclipse.core.resources.IResource
org.eclipse.core.resources.IMarker
org.eclipse.ui.views.tasklist
org.eclipse.ui.views.markers
 
A

Arved Sandstrom

[ SNIP ]
+1

I actually typed a paragraph along these lines, but decided to stick to
the idea of unit tests as a way of encouraging good module design.

Patricia

I will also point out, neutrally, that what has been advocated here for
unit tests in support of software component design is test driven
development (TDD), or *close to it*. Lew and Martin both describe a
process very close to it; I don't have enough information to say whether
they are _requiring_ that all of the first tests fail (which is
necessary in classic TDD), or simply assuming that many/most will.

In any case the OP could read up on TDD to get more background on what's
being described here. A salient point is that these are unit tests that
support software component design; they are not unit tests for defect
detection [1].

AHS

1. And how much of one's time one should devote to writing unit tests
for _testing_, as opposed to higher-level tests, is a different discussion.
 
S

Stefan Ram

Arved Sandstrom said:
1. And how much of one's time one should devote to writing unit tests
for _testing_, as opposed to higher-level tests, is a different discussion.

Once I was giving a C++ class for engine construction
students, and I gave them an assignment that requires to
write a client (caller) before the service (callee) is
written, but (my memory might distort this to some degree)
no one was able to understand what they were supposed to do.
And so, there was no correct solution to that assignment (or
only very few, I am not sure).

Of course, the blame is one me. I should have prepared the
road towards this in a better way, so that the students can
grasp this easier. But this was the first time that I tried
this, and I did not already know that it was so difficult
for them. So, I was not aware yet of the need for a more
careful preparation.

That is, without preparation it does not seem to be easy to
do for every novice. I was teaching to students who actually
were studying engine construction, I might have gotten other
results if I were teaching to computer science students. Try
it yourself the next time you have an average beginning
programming student to teach. Maybe the »Novize« of this
newsgroup might report one day how he gets along with TDD.

TDD is not the only methodology, where one writes the calls
before one write the callee. In the 70s we already had
something called »top-down programming« where one writes the
upper-level methods first and then implements the operations
they call.
 
S

Stefan Ram

TDD is not the only methodology, where one writes the calls
before one write the callee. In the 70s we already had
something called »top-down programming« where one writes the
upper-level methods first and then implements the operations
they call.

For example, I assume that the task is given to plot a sine
curve. How do I do this in TDP (top-down programming)? Well,

public static void main( final java.lang.String[] args )
{ final Plotter plotter = new Plotter();
final Sine sine = new Sine();
for( double x = -sine.start(); x < sine.end(); x += sine.step( x ))
plotter.set( x, sine.val( x ));
plotter.pack();
plotter.setVisible(); }

(untested)

Now, I still need to implement »Plotter« and »Sine«. I wrote
the code intentionally as if I was not aware of the
complications of the EDT and »paintComponent«, I wrote it in
a problem-oriented manner, in terms of the application
domain, ignoring the details of Java and Swing. To be aware
of such implementation details is left to the lower level
classes.

Another example. How do I write a recursive directory
listing? I intionally do *not* read the documentation of
java.io nor java.nio! I try to forget the little what I
already know about them. I start to code as if I just knew
the JLS, but not the rest of the Java SE library:

public class Main
{ public static void main( final java.lang.String[] args )
{ final Entry entry = Entry.from( args[ 0 ]);
entry.print(); }}

interface Printer
{ public void print(); }

public abstract class Entry implements Printer
{ /* factory method */
public static Entry from( final java.lang.String path )
{ ... } }

public class Invalid extends Entry
{ public void print()
{ java.lang.System.out.println( "invalid." ); }
... }

public class File extends Entry
{ public void print()
{ java.lang.System.out.println( this.path() ); }
... }

public class Directory extends Entry
{ public void print()
{ java.lang.System.out.println( this.path() );
for( final Entry entry : this.iterable() )
entry.print(); }
... }

(untested)

Only then, I start to look up the given file operations
in order to implement the details »...«, which then
will be partially »bottom-up«.

There once was a language »Elan« that had special support
for TDD (by which I mean »top-down design«, here) using
»stepwise refinement«

http://en.wikipedia.org/wiki/ELAN_(programming_language)
 
J

Jeff Higgins

Thanks everyone for the suggestions. Obviously, I'm going to need to
increase the size of my Java library and allocate some time for reading all
all of these things....

But in the meantime, are there any general rules I can use to make these
decisions for code I am developing now? Or do I really need to master
several books first?
Now that you are sufficiently interested in data modelling and software
design methodologies: here is a good, fast, cheap jumping in point.
<http://www.vogella.de/articles/EclipseEMF/article.html>
It will even do Swing databinding with some extra work (I gather).
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top