Struggling With OOP Concept

后端 未结 3 1553
太阳男子
太阳男子 2021-02-01 08:09

I\'m really struggling with a recurring OOP / database concept.

Please allow me to explain the issue with pseudo-PHP-code.

Say you have a \"user\" class, which l

3条回答
  •  长发绾君心
    2021-02-01 08:57

    Say you have a "wheel" class, which loads its data from the wheels table in its constructor

    Constructors should not be doing any work. Instead they should contain only assignments. Otherwise you make it very hard to test the behavior of the instance.

    Now, we have a "car" class, which loads its data from the cars table joined with the cars_wheels table and creates wheel objects from the returned wheel_ids:

    No. There are two problems with this.

    Your Car class should not contain both code for implementing "car logic" and "persistence logic". Otherwise you are breaking SRP. And wheels are a dependency for the class, which means that the wheels should be injected as parameter for the constructor (most likely - as a collection of wheels, or maybe an array).

    Instead you should have a mapper class, which can retrieve data from database and store it in the WheelCollection instance. And a mapper for car, which will store data in Car instance.

    $car = new Car;
    $car->setId( 42 );
    $mapper = new CarMapper( $pdo );
    if ( $mapper->fetch($car) ) //if there was a car in DB
    {
        $wheels = new WheelCollection;
        $otherMapper = new WheelMapper( $pdo );
    
        $car->addWheels( $wheels );
        
        $wheels->setType($car->getWheelType());
        // I am not a mechanic. There is probably some name for describing 
        // wheels that a car can use
        $otherMapper->fetch( $wheels );
    }
    

    Something like this. The mapper in this case are responsible for performing the queries. And you can have several source for them, for example: have one mapper that checks the cache and only, if that fails, pull data from SQL.

    Do I really have to choose between beautiful OOP code with a million queries VS. 1 query and disgusting, un-OOP code?

    No, the ugliness comes from fact that active record pattern is only meant for the simplest of usecases (where there is almost no logic associated, glorified value-objects with persistence). For any non-trivial situation it is preferable to apply data mapper pattern.

    ..and if I make a "city" class, in its constructor I'll need to join the cities table with the cities_dealerships table with the dealerships table with the dealerships_cars table with the cars table with the cars_wheels table with the wheels table.

    Jut because you need data about "available cares per dealership in Moscow" does not mean that you need to create Car instances, and you definitely will not care about wheels there. Different parts of site will have different scale at which they operate.

    The other thing is that you should stop thinking of classes as table abstractions. There is no rule that says "you must have 1:1 relation between classes and tables".

    Take the Car example again. If you look at it, having separate Wheel (or even WheelSet) class is just stupid. Instead you should just have a Car class which already contains all it's parts.

    $car = new Car;
    $car->setId( 616 );
    
    $mapper = new CarMapper( $cache );
    $mapper->fetch( $car );
    

    The mapper can easily fetch data not only from "Cars" table but also from "Wheel" and "Engines" and other tables and populate the $car object.

    Bottom line: stop using active record.

    P.S.: also, if you care about code quality, you should start reading PoEAA book. Or at least start watching lectures listed here.

    my 2 cents

提交回复
热议问题