Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Php modularity in parent-child relationship vs quick script execution

An application I am writing has groups of users, let's call them communities. Each community has meetings which also have a number objects associated with them (attendees, objectives, tasks, accomplishments, etc).

I'm a little confused as to what is the best way to implement initializing the children objects when a parent is created. Here is a simplified class setup.

First Implementation

<?php
class community
{
     public $id;
     public $name;
     //Store an array of meeting objects
     public $meetings = array();
     //Store an array of member objects
     public $members  = array();
     //etc

     public function getProperties()
     {
         //hit database for community properties including ids of meetings 
         //and members associated with this community
         //Set community properties

         //Use returned ids to populate community properties
         foreach($returnedMeetingIds as $meetingId)
         {
              //The meeting class is responsible for its own init.
              $newMeeting = new Meeting();
              $newMeeting->id = $meetingId;
              $newMeeting->getProperties();
              $this->meetings[$meetingId] = $newMeeting;
         } 
     }
}
?>

This method puts the responsibility of initialization on each object which in my opinion is better for maintainability and modularity but I can see this being a huge cascading bottleneck as more meetings are added because each meeting's child objects would also be responsible for initializing themselves.

The other way I can think to do this is to populate the $meetings array with a single database call. All meetings are stored in a single table with a community id field.

Second Implementation

<?php
class community
{
     public $id;
     public $name;
     //Store an array of meeting objects
     public $meetings = array();
     //Store an array of member objects
     public $members  = array();
     //etc

     public function getProperties()
     {
         $sql = 'SELECT * 
                 FROM meetings
                 WHERE community_id = :community'
         //etc
         $stmt->execute();
         while($meeting = $stmt->fetch())
         {
              $newMeeting = new Meeting();
              $newMeeting->id = $meeting['id'];
              //etc
              $this->meetings[$newMeeting->id] = $newMeeting;
         }

     }
}
?>

I believe the second class will execute much faster but I've now coupled the meeting class to the community class and that feels like it isn't the best of solutions.

My question is how much stock should be placed in decoupling these groups of classes (community, meetings, objective, accomplishment, task, etc)? My own personal feeling is that I should go with the First Implementation until it proves to be inappropriate for my traffic load and then move to something like Second Implementation. I'd like to know what someone with a little more experience has found to be the best practice. I feel this is a rabbit hole that once I go down could be difficult to refactor later. Also I'm not convinced that Either method is the right way to approach this. Thank you so much for any help provided!

like image 362
Tanner Avatar asked Nov 03 '22 14:11

Tanner


1 Answers

You have to ask yourself if you really require all those meetings in the community. Let's take a look at the following use case.

  1. You would like to output all the information of a community including a list of meetings. This may seem like a valid case where you want to construct a community and all its meetings. But there is a more efficient way to this.

    class Controller {
    
        public function showCommunity($id) {
            $community = $this->communityGateway->findCommunity($id);
            $meetings = $this->meetingGateway->findMeetings($community->getCommunityId());
    
            // output your community information and meeting information
        }
    }
    
  2. You have a use case where you need to manipulate all the meetings of a community. In your approach you would do it like this:

    $community = new Community();
    $community->doSomethingToAllMeetings();
    

    But you could just as well use the approach from example #1 for this. Instead of outputting your perform the actions required for the manipulation.


However if you do require the meetings then you should create them outside the community and pass them into the community object as a dependency (either in the controller if required during creation, or as a setter if they may be added later).

class Community {

    public function __construct($meetings) {
    ...
    }
}

What do you gain from the above approach?

  • You don't always load all the meeting information for each community.
  • You decouple the classes. One can now exist without the other and can be replaced for testing.
  • You don't overburden your business logic with the creation of objects. That should happen at Controller level and not in your business objects.
  • You can even replace those gateways and load your data from somewhere else if you want that.
like image 72
Dan Avatar answered Nov 15 '22 08:11

Dan