Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #11116

Re: Best Way to Pass Info Between Objects?

From Lew <noone@lewscanon.com>
Newsgroups comp.lang.java.programmer
Subject Re: Best Way to Pass Info Between Objects?
Date 2012-01-08 11:49 -0800
Organization albasani.net
Message-ID <jecrvg$j48$1@news.albasani.net> (permalink)
References <Xns9FD47717636DCjpnasty@94.75.214.39> <4dWdnRF6pOQcUJTSnZ2dnUVZ_vidnZ2d@earthlink.com> <Xns9FD4882D25253jpnasty@94.75.214.39>

Show all headers | View raw


Novice wrote:
> Patricia Shanahan<pats@acm.org>  wrote :
>> Novice wrote:
>>> ...
>>> 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?
>> ...
>>> 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.

Parameters.

 >> 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.
 >
 > 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.

-- 
Lew
Honi soit qui mal y pense.
http://upload.wikimedia.org/wikipedia/commons/c/cf/Friz.jpg

Back to comp.lang.java.programmer | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

Best Way to Pass Info Between Objects? Novice <novice@example..com> - 2012-01-08 16:41 +0000
  Re: Best Way to Pass Info Between Objects? Patricia Shanahan <pats@acm.org> - 2012-01-08 09:08 -0800
    Re: Best Way to Pass Info Between Objects? Novice <novice@example..com> - 2012-01-08 18:22 +0000
      Re: Best Way to Pass Info Between Objects? markspace <-@.> - 2012-01-08 10:45 -0800
      Re: Best Way to Pass Info Between Objects? Lew <noone@lewscanon.com> - 2012-01-08 11:49 -0800
      Re: Best Way to Pass Info Between Objects? Patricia Shanahan <pats@acm.org> - 2012-01-08 14:04 -0800
        Re: Best Way to Pass Info Between Objects? Martin Gregorie <martin@address-in-sig.invalid> - 2012-01-08 22:40 +0000
          Re: Best Way to Pass Info Between Objects? Patricia Shanahan <pats@acm.org> - 2012-01-08 15:56 -0800
            Re: Best Way to Pass Info Between Objects? Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2012-01-09 06:34 -0400
              Re: Best Way to Pass Info Between Objects? Jeff Higgins <jeff@invalid.invalid> - 2012-01-09 12:39 -0500
                Re: Best Way to Pass Info Between Objects? Jeff Higgins <jeff@invalid.invalid> - 2012-01-09 12:42 -0500
                Re: Best Way to Pass Info Between Objects? Lew <lewbloch@gmail.com> - 2012-01-09 13:43 -0800
                Re: Best Way to Pass Info Between Objects? Jeff Higgins <jeff@invalid.invalid> - 2012-01-09 17:26 -0500
                Re: Best Way to Pass Info Between Objects? Lew <noone@lewscanon.com> - 2012-01-10 06:47 -0800
                Re: Best Way to Pass Info Between Objects? Patricia Shanahan <pats@acm.org> - 2012-01-09 14:26 -0800
                Re: Best Way to Pass Info Between Objects? Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2012-01-09 19:06 -0400
                Re: Best Way to Pass Info Between Objects? Jeff Higgins <jeff@invalid.invalid> - 2012-01-09 18:46 -0500
                Re: Best Way to Pass Info Between Objects? Jeff Higgins <jeff@invalid.invalid> - 2012-01-09 19:52 -0500
                Re: Best Way to Pass Info Between Objects? Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2012-01-10 06:43 -0400
              Re: Best Way to Pass Info Between Objects? Martin Gregorie <martin@address-in-sig.invalid> - 2012-01-10 02:11 +0000
              Re: Best Way to Pass Info Between Objects? Gene Wirchenko <genew@ocis.net> - 2012-01-09 20:17 -0800
              Re: Best Way to Pass Info Between Objects? Lew <noone@lewscanon.com> - 2012-01-10 06:43 -0800
                Re: Best Way to Pass Info Between Objects? Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2012-01-10 19:13 -0400
      Re: Best Way to Pass Info Between Objects? Jeff Higgins <jeff@invalid.invalid> - 2012-01-09 14:30 -0500
        Re: Best Way to Pass Info Between Objects? Jeff Higgins <jeff@invalid.invalid> - 2012-01-09 17:28 -0500
          Re: Best Way to Pass Info Between Objects? Martin Gregorie <martin@address-in-sig.invalid> - 2012-01-10 02:24 +0000
            Re: Best Way to Pass Info Between Objects? Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2012-01-10 06:35 -0400
              Re: Best Way to Pass Info Between Objects? Martin Gregorie <martin@address-in-sig.invalid> - 2012-01-10 22:48 +0000
  Re: Best Way to Pass Info Between Objects? v_borchert@despammed.com (Volker Borchert) - 2012-01-08 17:17 +0000
  Re: Best Way to Pass Info Between Objects? Jeff Higgins <jeff@invalid.invalid> - 2012-01-08 13:43 -0500
    Re: Best Way to Pass Info Between Objects? Jeff Higgins <jeff@invalid.invalid> - 2012-01-08 19:01 -0500
  Re: Best Way to Pass Info Between Objects? Jeff Higgins <jeff@invalid.invalid> - 2012-01-08 14:10 -0500
    Re: Best Way to Pass Info Between Objects? Jeff Higgins <jeff@invalid.invalid> - 2012-01-08 14:41 -0500
  Re: Best Way to Pass Info Between Objects? Roedy Green <see_website@mindprod.com.invalid> - 2012-01-09 04:13 -0800

csiph-web