0

Let's say there is class called AccountingService. Using this class I fetch all kinds of ecommerce records like products, customers, etc. The fetching happens inside a controller action. Once fetched, I should process and save these records to some kind of ecommerce shop.

What I want to do is create an implementation of Shop

namespace PrestaShop;

use Shop\ShopInterface;

class Shop implements ShopInterface
{
    public function saveProduct(array $products)
    public function saveProductQuantities(array $productQuantities)
    public function saveCustomers(array $customers)
    public function getOrder($orderReference)
}

The problem is that the methods are incredibly long, because many foreign keys, pivot tables, relations need to be saved to MySQL tables. I would like to extract product, customer, quantitiy methods into seperate classes/components that work as dependencies for this class.

I am using array because the fetched records are in bulk (lets say 10k), so I can't instantiate an object for each record and save it via active record.

Using separate Repository pattern objects doesn't make sense to me, because all these objects product, customer, quantity are related and have connected tables.

I'm looking for advice on how to split up the implementation PrestaShop\Shop into smaller classes.

Any other advice on hwo to structure this app logic is welcomed.

  • those functions sure look like fun – Ewan Oct 23 '15 at 12:01
  • if you problem is that the functions are too long, you should probably post one of the functions. I dont see why they cant be reasonably sized – Ewan Oct 23 '15 at 12:03
  • It's around 400 lines long all sub-methods included. Have to look up if records already exist in DB, match them by ref, save manufacturers, save categories, products, associations, shop, language associations, insert/update. So yeah... – gskema Oct 23 '15 at 12:09
  • ok but the sub methods will obvs be reused across public methods? – Ewan Oct 23 '15 at 13:06
  • Actually the "sub methods" of the 4 methods in the xample are only called once, but it is possible to call then from different contexts. – gskema Oct 23 '15 at 13:15
2

You should split up the interface. Customers and products are not related so having an interface with saveProduct-methods and one with saveCustomer-methods will reduce the amount of code in your implementations.

If you can't split the interface up (because it is not under your control, for example), simply create a couple of classes that contain the different implementations split up, inject these classes into the class that implements the interface and route your calls to those classes. These can again have classes with specific roles injected into them (if a customer contains products, a CustomerSaver can have a ProductSaver injected so it can use the methods on that class).

All code that is generic (ie common to those classes) can be put in a base class that all sub-saving classes derive from.

namespace PrestaShop;

use Shop\ShopInterface;

class ProductSaver
{
    public function saveProduct(array $products)
    {
         //implement here
    }
}

class Shop implements ShopInterface
{
    function __construct($productSaver, $customerSaver)
    {
        $this->productSaver = $productSaver;
        $this->customerSaver = $customerSaver;
    }

    public funtion saveProduct(array $products)
    {
        $this->productSaver->saveProduct($products);
    }

    //and so on...
}
  • I was having some similar ideas. There also one more entity - order which is a composite of both product and customer, so that complicates things quite a bit. I guess I'll have to think about what domain objects and respective classes would be the best to use in my app. – gskema Oct 23 '15 at 12:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.