Java – OOP Objects, nested objects, and DAO’s

daojavaobject-orientedobject-oriented-designPHP

Here's something I keep struggling to figure out the best solution to. I've had this problem while working with PHP and Java so it's a fundamental understanding of OOP issue. Examples are in PHP.

Let's say I have a few object's here. Song, Artist, ArtistProfile, User.

So in some instances I want the ArtistProfile and an array of User objects (subscribers) when I call the Artist (e.g. the artist's profile page), in other instances I only want the Artist info, like when viewing a page of the song.

Should I be nesting one object as part of another or should I be creating more specific objects for different usages.

Option 1: Nested

Class Song {
   private $songId;
   private $songName;
   private $year;
   private $Artist; //Artist object
}

Class Artist {
   private $artistId;
   private $name;
   private $age;
   private $subscriberArr; //Array of User objects which then have more nested objects such as a Role object, Profile object
   private $profile; //Profile object which could also have more nested objects
}

Class User {
   private $userId;
   private $name;
   private $age;
   private $role; //Role object
   private $profile; //UserProfile object
}

Option 2: Build more objects

Class Song {
   private $songId;
   private $songName;
   private $year;
   private $artistId;
}

Class Artist {
   private $artistId;
   private $age;
   private $name;
}

Class User {
   private $userId;
   private $name;
   private $age;
   private $roleId;
}

Class SongWithArtist {
   private $song; //Basic Song object
   private $artist; //Basic Artist object
}

Class ArtistWithProfile {
   private $artist; //Basic artist object
   private $profile; //Profile object
   private $subscriberArr; //UserDisplay object containing basic User object
}

 Class UserWithProfile {}

Option 1 means wasting a lot of time/resources grabbing information I may not need for that page but easier to manage. Option 2 is messy and requires keeping track of which object is what but faster and far less db calls. Which is the 'correct' option and/or is there a 3rd correct option?

Best Answer

Should I be nesting one object as part of another or should I be creating more specific objects for different usages.

  1. Follow OO principles first which means "more specific objects." In doing so your classes may "line up" with your database schema or not but do not let DB schema trump good OO design.

  2. Single Responsibility Principle will help guide you in what classes to build. SRP means, for example, that a Song is a song. It is not an artist, it is not a list of subscribers, so it should not have artist or subscriber stuff in it. Only song stuff.

  3. The above means that you will have lots of small, independent, fully functional things - classes. By "fully functional" I mean, if a Song is a name, date, and id then that's what's in it. period. The fact that a certain artist sings that song does not inherently, fundamentally define what a Song is. This means other classes to model relationships like "an artist's song repertoire" for example.

  4. Small functional classes leads to good DAO's and flexibility for your user interface.

Option 1 means wasting a lot of time/resources grabbing information I may not need for that page but easier to manage. Option 2 is messy and requires keeping track of which object is what but faster and far less db calls

  1. You are falling victim to premature optimization. How can you know up front that option 2 will have "fewer DB calls?" What does that mean anyway?

  2. This is simply the wrong way to think about your domain classes/model. This is why you end up duplicating your DB schema:

.

Class SongWithArtist {
  private $song; //Basic Song object
  private $artist; //Basic Artist object
}

When what you should have is something describing the real world:

Class ArtistPortfolio {
    private Artist $theArtist;
    private List<Song> $portfolio;  // list of songs (s)he sings 
}

Class ArtistSubscribers {
    private Artist $theArtist;
    private List<User> $subscribers;  // list of people who like this artist
}

// And it would probably make sense to combine the above 2 classes:

Class ArtistProfile {
    // an Artist object, not just an id. We're doing OBJECT oriented programming.
    private Artist $theArtist;

    private List<Song> $portfolio;  // list of Song objects 
    private List<User> $subscribers; // list of User objects
}

// and if you need a list of profiles...
Class ArtistProfiles {
    private List<ArtistProfile> $profiles; // a list of type ArtistProfile

    public ArtistProfile GetProfileByArtist (Artist thisArtist){}
    public ArtistProfile GetProfileByName (string name) {}
    public ArtistProfile GetProfileById (string id) {}
}

// I'd say a ArtistProfile could be part of an Artist..

Class Artist {
    private $id;
    private $name;
    private ArtistProfile $profile; // this is composition.
}


//In lieu of the above, an DAO oriented Artist composition ...
// Just go with the refactoring flow!
Class Profile {
    private $id;
    private $name;
    private $birthdate
}

 Class Repertoire {
    // a Profile object, not just an id. We're doing OBJECT oriented programming.
    private Profile $theArtist;

    private List<Song> $portfolio;  // list of Song objects 
    private List<User> $subscribers; // list of User objects
}

Class Artist {
    private Profile $me;
    private Repertoire $myStuff; 
}

Too Many DB Calls!

NOT. You can instantiate a Artist object without populating the $myStuff and in turn, defer populating $subscribers / portfolio lists until needed. This is called lazy loading.

Related Topic