#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2008
    Posts
    10
    Rep Power
    0

    Red face Code organization/architecture advise


    I'm refactoring the code in an old procedural PHP app. Organizing the code into classes. Uncertain what is common practice in the following hypothetical situation:

    I have a object to represent a Car. It has methods like $Car->load(), $Car->save(), $Car->getTopSpeed()
    I have another object to represent a ParkingLot. It has methods like $ParkingLot->load(), ->save(), ->getNumberOfStalls()

    But now I need a method to get an array of Car objects that are in a ParkingLot. Does it make more sense to put a method for this in my Car class, or in my ParkingLot class? Or somewhere else?

    It seems I run up against situations like this quite frequently, and can never decide where a method like this should live.
    Thanks!
  2. #2
  3. Did you steal it?
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    13,965
    Rep Power
    9397
    An age-old question.

    IMO you put it in the ParkingLot because of the relationship: a ParkingLot contains Cars and can't really exist without them. You could also have a similar method in the object instance to get the set of cars parked in the lot, so there's a sort of precedent already.

    However there's a problem: ParkingLot needs to be able to create Cars. That's a bother but you can solve it in code by making a public "constructor" that takes raw data and returns instances. That's the best method I've come up with.
    Meanwhile if you put the method in Car then it has to know about ParkingLot, which feels worse to me because then you have to know specific information about ParkingLots (which aren't really fundamental aspects of Cars like the reverse is) and how they record access to Cars.
    Last edited by requinix; October 31st, 2013 at 03:46 PM.
  4. #3
  5. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,957
    Rep Power
    1046
    Hi,

    don't waste your time with philosophical musings. Put the method where it's most useful and makes the most sense to you. You may even end up defining the method in both classes (of course you should call one method in the other rather than copypasting the definition).

    Don't forget: objects are tools for solving problems. They're not about imitating the real world.
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2008
    Posts
    10
    Rep Power
    0

    good advise


    thx requinix,

    I struggle with this on pretty much every project - yet I can never seem to find discussions of similar situations on the net. I'm probably searching for the wrong thing I'd love to read more on the theory.

    What you've suggested is in line with the gut feeling I had, so full steam ahead then. As for the "ParkingLot needs to create Cars" problem, I've basically added a "populateCarPropertiesFromPassedValues" kind of function, which I think (?) is what you are getting at with a public "constructor". For example:

    PHP Code:
    class Car {
      public 
    $color null;
      public 
    $top_speed null;

      public function 
    load($car_id) {
         
    $car_db_record get_car_values_from_database($car_id);
         
    $this->populateCarPropertiesFromPassedValues($car_db_record);
      }

      public function 
    populateCarPropertiesFromPassedValues($values) {
        foreach(
    $values as $property => $value) {
          
    $this->{$property} = $value;
        }
      }
    }

    class 
    ParkingLot {
      public function 
    getCarsInParkingLot() {
        
    $all_car_db_records_for_lot get_all_cars_from_database($this->lot_id);
        foreach(
    $all_car_db_records_for_lot as $car_values) {
          
    $car = new Car();
          
    $car->populateCarPropertiesFromPassedValues($car_values);
          
    $car_objects_to_return[] = $car;
        }
        return 
    $car_objects_to_return;
      }

    Kind of a silly example, but heh
    Thanks again

IMN logo majestic logo threadwatch logo seochat tools logo