javaclassobjectoopinstance-variables

MOOC Java Part 5 How would one know when to use an object as a reference variable in another class?


In Part 5 Primitive and Reference variables section, there is a Person class defined and then another class called TimeMachine which has a reference variable defined for type Person.

public class TimeMachine {

    private Person traveler;

    public TimeMachine(Person person) {
        this.traveler = person;
    }

    public void travelInTime(int years) {
        this.traveler.setYear(this.traveler.getYear() + years);
    }
}

Driver class:

public class TimeMachineMain {

    public static void main(String[] args){

        Person lorraine = new Person();
        TimeMachine tardis = new TimeMachine(lorraine);
        tardis.travelInTime(6);
        System.out.println(lorraine.getYear());

    }
}

In the next section, there is another class called AmusementParkRide which doesn't have an instance variable of type Person but is passing Person as method parameter to the method allowedToRide directly.

public class AmusementParkRide {

    private String name;
    private int lowestHeight;

    public AmusementParkRide(String name, int lowestHeight){
        this.name = name;
        this.lowestHeight = lowestHeight;
    }   

    public boolean allowedToRide(Person person){
        if (person.getHeight() < this.lowestHeight){
            return false;     
        }

        return true;
    }

    public String toString(){
        return this.name + ", minimum height: " + this.lowestHeight;
    }
}

Driver class:

public class AmusementParkRideMain {

    public static void main(String[] args) {

        Person matt = new Person("Matt");
        matt.setWeight(86);
        matt.setHeight(180);    
    
        Person jasper = new Person("Jasper");
        jasper.setWeight(34);
        jasper.setHeight(132);

        AmusementParkRide waterTrack = new AmusementParkRide("Water track", 140);

        if (waterTrack.allowedToRide(matt)) {
            System.out.println(matt.getName() + " may enter the ride");
        } else {
            System.out.println(matt.getName() + " may not enter the ride");
        }

        if (waterTrack.allowedToRide(jasper)) {
            System.out.println(jasper.getName() + " may enter the ride");
        } else {
            System.out.println(jasper.getName() + " may not enter the ride");
        }

        System.out.println(waterTrack);

    }
}

Question: How do you know when to declare an object as a reference variable in another object? Based on the above examples, TimeMachine doesn't really have a HAS A relationship with the class person, intuitively, so not sure why it was implemented like that. Would this same implementation have been better like this, similar to how it's done in the AmusementParkRide class?

public class NewTimeMachine {

    public void travelInTime(Person person, int years) {
        person.setYear(person.getYear() + years);
    }

}

Driver class:

public class NewTimeMachineMain {

    public static void main(String[] args){

        Person lorraine = new Person("Lorraine");
        NewTimeMachine tardis = new NewTimeMachine();
        tardis.travelInTime(lorraine, 6);
        System.out.println(lorraine.getYear());

    }

}

Tried the approach above by creating the NewTimeMachine class and got the same result as the TimeMachine example. Just need to understand why/when to declare an object as a reference variable in another object vs how it was implemented in the AmusementParkRide example.


Solution

  • It's an entirely reasonable question to ask, but I'm afraid the answer is mu, in the Pirsig sense. The question assumes that there are objective criteria for software design. That assumption is hardly warranted.

    I wish more software design courses and text books would be more explicit that, so far, software design is more akin to a craft than a science. Not that there aren't heuristics, design principles, or patterns that discuss what to do and what not to do, but they should be considered as inspiration rather than hard rules.

    For example, I consider the book Design Patterns a fine catalogue from which one can draw inspiration, but it's not a collection of criteria and decisions. It doesn't say, in this situation, you must do that, but rather, if this is your situation, you may consider using this pattern. And the consideration is effectively left to the experience of the reader.

    Likewise, APPP, which introduces the SOLID principles, spends 100 pages outlining problems, forces, and other considerations, before presenting the first of the SOLID principles. And even then, these principles are guidelines rather than hard rules.

    Perhaps, one day the software development industry advances to a state where it's more of a science than a craft, but that's not the current state of affairs.

    It's reasonable to ask question like the OP, but much software design skill comes with experience and practice. The more you suffer from your design mistakes, the more you learn. That's not to say that you can't accelerate the learning process. You can learn from others' mistakes, too, so reading books, following courses, watching conference presentations, etc. is a good idea.

    Why did the course author choose one design over another? If the course is any good, he or she may actually explain the thinking that led to a given design choice, but you shouldn't expect to be able to extrapolate from only a handful of examples.