SitePoint Sponsor

User Tag List

Results 1 to 19 of 19
  1. #1
    I want my 4th arrow! garlinto's Avatar
    Join Date
    Jun 2002
    Location
    Riding the electron wave
    Posts
    372
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    One class to update them all....

    I have a 4 classes that all have the same methods. They are each a cart class representing the diverse product inventory we keep in our facility. Symantically speaking, I thought that this was the most logical way to do it, especially since each cart class deals with it's own look-up table and only it's own.

    All of these classes share these methods:
    PHP Code:
       $CLASS_0->update();
       
    $CLASS_0->cleanup();
       
    $CLASS_0->recalcTotal();
       
       
    $CLASS_1->update();
        
    $CLASS_1->cleanup();
        
    $CLASS_1->recalcTotal();
       
       
    etc... 
    So, in the page logic for the apps that use these classes, I have long sets of code where I call the above methods for each of the four classes every time I update them, remove a product, and so on. Get's very redundant after a while as you can see

    In doing some research on inheritance and aggregation, I realized that I could probably design a superclass that would call the update methods for all the instantiated classes with one method. Such a class would really simplify my code structures. I'm just not sure what the design for such a class would look like.

    In my mind, I envision a class that when called, instantiates each of the other classes and maintains them based on the method args I pass to it.

    Is this appropriate? Can anyone point me in the right direction? I can write the code, but I don't have enough understanding of app-design to really move forward with this. Any suggestions/insight would be appreciated.
    Ducharme's Axiom: "If you view your problem closely
    enough, you will recognize yourself as part of the problem."


  2. #2
    SitePoint Addict
    Join Date
    Jan 2004
    Location
    New York
    Posts
    254
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You can use the command pattern. The idea is to have all 4 classes with same method names and adding references of those objects to the command class.

    Here is a quick example.
    PHP Code:
    class command {
      var 
    $objects = array();
      function 
    addObject(&$object) {
        
    $this->objects[] =& $object;
      }
      function 
    updateAll() {
        for(
    $this->objects as $object) { //goes through every object added by addObject() method
          
    $object->update();
        }
      }


  3. #3
    I want my 4th arrow! garlinto's Avatar
    Join Date
    Jun 2002
    Location
    Riding the electron wave
    Posts
    372
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the quick reply.

    Correct me if I'm wrong, but even though the classes that I need to command are persistant, the command class doesn't necessarily need to be persistant.

    Following your design schema, would this be recommended usage:
    PHP Code:
    // Cart.php
          
    if ( ! isset ( $_SESSION['cart'] ) )
          {
              
    $_SESSION['cart'] =& new Cart;
          }
          
    $CART =& $_SESSION['cart'];
          
          
    // Gases.php
          
    if ( ! isset ( $_SESSION['gases'] ) )
          {
              
    $_SESSION['gases'] =& new Gases;
          }
          
    $GASES =& $_SESSION['gases'];
          
          
    // Steel.php
          
    if ( ! isset ( $_SESSION['steel'] ) )
          {
              
    $_SESSION['steel'] =& new Steel;
          }
          
    $STEEL =& $_SESSION['steel'];
          
          
    // Labor.php
          
    if ( ! isset ( $_SESSION['labor'] ) )
          {
              
    $_SESSION['labor'] =& new Labor;
          }
          
    $LABOR =& $_SESSION['labor'];
          
          
    // CustomCart.php
          
    $invoice_id =& echoVar INV_NUM );
          if ( ! isset ( 
    $_SESSION['customcart'] ) )
          {
              
    $_SESSION['customcart'] = &new Customcart$invoice_id );
          }
          
          
    $CSTM =& $_SESSION['customcart'];
          
        
    // Command.php controller class
          
    $CMND = &new Command;
          
    $CMND->addObject $CART );
          
    $CMND->addObject $GASES );
          
    $CMND->addObject $STEEL );
          
    $CMND->addObject $LABOR );
          
    $CMND->addObject $CSTM );
          
          
    /** to update... **/
          
    $CMND->updateAll $_POST );
          
     
    etc... 
    I'll need to code a switch for removing items from any particular class, since I don't need to call the $CLASS->remove() method for all of the classes, just the affected class. Something like:
    PHP Code:
        // URL query string -> mypage.php?remove=gases&id="600010"
        
    $CMND->remove$_GET['remove'], $_GET['id'] ); 
    What do you think so far? Is there any way I can improve on this or is this acceptable?
    Ducharme's Axiom: "If you view your problem closely
    enough, you will recognize yourself as part of the problem."


  4. #4
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In doing some research on inheritance and aggregation, I realized that I could probably design a superclass that would call the update methods for all the instantiated classes with one method. Such a class would really simplify my code structures. I'm just not sure what the design for such a class would look like.
    It can be as simple as taking the common code out of your multiple classes, putting it in a base class and then extending your multiple classes with the base class. You will need to add some code in each of your multiple classes to tell the common code which look-up table to use.
    PHP Code:
    class unique1 {
    function 
    func1() {}
    function 
    func2() {}
    }

    class 
    unique2 {
    function 
    func1() {}
    function 
    func2() {}

    Becomes
    PHP Code:
    class base {
    var 
    $lookuptable;
    function 
    base($lookuptable) {
    $this->lookuptable $lookuptable;
    }
    function 
    func1() {}
    function 
    func2() {}
    }

    class 
    unique1 extends base{
    function 
    unique1() {
    $this->base('lookuptable1');
    }
    }

    class 
    unique2 extends base{
    function 
    unique2() {
    $this->base('lookuptable2');
    }

    Christopher

  5. #5
    I want my 4th arrow! garlinto's Avatar
    Join Date
    Jun 2002
    Location
    Riding the electron wave
    Posts
    372
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    arborint, thanks for the suggestion. I may try something like that, since it would centralize the code design. To me, code is much eisier to maintain when it is centralized like that.

    I'll try something and post any questions if I need some direction.
    Ducharme's Axiom: "If you view your problem closely
    enough, you will recognize yourself as part of the problem."


  6. #6
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    For some reason your design seems odd and I suspect that some kind of inversion of your current thinking may be the way to go. It is not clear to me what CART, GASES, STEEL, LABOR, and CSTM are, but it seems they are the place to start -- not making them all carts.
    Christopher

  7. #7
    I want my 4th arrow! garlinto's Avatar
    Join Date
    Jun 2002
    Location
    Riding the electron wave
    Posts
    372
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Actually aborint, you are right. Each of those is a cart. I think you have touched on a vital point. I know that my design is not, shall we say, 'proper', and because of that fact I am creating challenges that normally would not be present. I wish I had more training in application design and theory, but alas, I'm having to learn as I go.

    In my apps, the data are what have driven the design, and that may be where the difficulty lies. But I don't know what to do in place of my current design.

    Briefly:
    There are five pricing tables (among many others) in the database: main, gases, steel, labor, and customproducts. Each of this tables has its own cart class, with many of the same methods in each. I've designed the apps in this way because the table id's can overlap. In other words, If I want to add product number "235900" to my invoice, "235900" could be a table id in any one of those tables. So, instead of building complex logic structures inside and outside the classes to manage where each product is from and keep track of it for subsequent lookups ( for pricing and descriptions and so on ), I designed 5 classes that each handle thier own look-up table, and another class that totals them all and gives me access to subtotals, tax amounts, and a grandtotal.

    But as was mentioned, the code is now getting very bloated and cumberson with much redundancy.

    With just this much explained to you, can you suggest a more intuitive design? Or will the one I have work with some changes? I don't mind a redesign if it will mean better mantainability, greater efficiency and will allow the design to follow a more logical path.
    Ducharme's Axiom: "If you view your problem closely
    enough, you will recognize yourself as part of the problem."


  8. #8
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Off Topic:

    One ring to rule them all...

  9. #9
    I want my 4th arrow! garlinto's Avatar
    Join Date
    Jun 2002
    Location
    Riding the electron wave
    Posts
    372
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    Off Topic:

    One ring to rule them all...
    * sigh *

    Here I was thinking: Wow! A nice juicy reply to sink my teeth into so I can get started with my redesign.

    Instead, more Sitepoint jocularity.
    Ducharme's Axiom: "If you view your problem closely
    enough, you will recognize yourself as part of the problem."


  10. #10
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by garlinto

    Briefly:
    There are five pricing tables (among many others) in the database: main, gases, steel, labor, and customproducts. Each of this tables has its own cart class, with many of the same methods in each. I've designed the apps in this way because the table id's can overlap. In other words, If I want to add product number "235900" to my invoice, "235900" could be a table id in any one of those tables. So, instead of building complex logic structures inside and outside the classes to manage where each product is from and keep track of it for subsequent lookups ( for pricing and descriptions and so on ), I designed 5 classes that each handle thier own look-up table, and another class that totals them all and gives me access to subtotals, tax amounts, and a grandtotal.

    But as was mentioned, the code is now getting very bloated and cumberson with much redundancy.

    With just this much explained to you, can you suggest a more intuitive design? Or will the one I have work with some changes? I don't mind a redesign if it will mean better mantainability, greater efficiency and will allow the design to follow a more logical path.
    Sound to me like you should be using one of three alternatives: Template Method, Strategy or State.

    Template Method would move the common functions to the superclass, including having some of those methods call expected subclass methods which are undefined in the parent class (abstract methods if you are using php5). You would then use inheritance to create subclasses which would fill out those unique methods.

    Strategy is useful when you can encapsulate the entire uniqueness of your algorithm into classes, and then you choose the class to "bind" in when you create the class. You then delegate to the strategy when you need it's functionality.

    State is similar to Strategy, but you bind it via a method call and can switch State at will.

    The fundamental difference between a Strategy and a State is the State can change during the lifetime of the object, whereas with Strategy and TemplateMethod you make a decision when you create the object how you want it to behave.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  11. #11
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)


    Sorry, just thought of that looking at the threads title you see About to sign off now for today, though I will definitely read the posts in this thread tomorrow when I have more time.

    If I can help in anyway, I'll see about posting it here...

  12. #12
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I agree with Jason that Strategy concept is the way to go here. I could also almost see it as a pricing Factory something like:
    PHP Code:
    $cart->addProduct(new Product($sku, new Pricing($type))); 
    Where the Pricing class returns a MainPricing , GasesPricing, SteelPricing, LaborPricing, or CustomProductsPricing object depending on the type you pass it. All have the same interface.
    Christopher

  13. #13
    I want my 4th arrow! garlinto's Avatar
    Join Date
    Jun 2002
    Location
    Riding the electron wave
    Posts
    372
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arborint
    I agree with Jason that Strategy concept is the way to go here. I could also almost see it as a pricing Factory something like:
    PHP Code:
     $cart->addProduct(new Product($sku, new Pricing($type))); 
    Where the Pricing class returns a MainPricing , GasesPricing, SteelPricing, LaborPricing, or CustomProductsPricing object depending on the type you pass it. All have the same interface.
    Thanks to all of you.

    So that I understand: when you use the $cart->addProduct() method, how is the _Pricing object returned, and how do I access it? Can you define the proposed structure for me in more detail? I don't feel that I "get it" enough to start writing code.
    Ducharme's Axiom: "If you view your problem closely
    enough, you will recognize yourself as part of the problem."


  14. #14
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

  15. #15
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The Cart gets its info from the Product which in turn gets is price info from Pricing.
    PHP Code:
    class Product {
    var 
    $sku;
    var 
    $pricing;

    function 
    Product($sku$pricing) {
      
    $this->sku $sku;
      
    $this->pricing $pricing;
    // lookup other product info here
    }

    function 
    getSku() {
      return 
    $this->sku;
    }
    function 
    getPrice() {
      return 
    $this->pricing->getPrice($this->sku);
    }


    Christopher

  16. #16
    I want my 4th arrow! garlinto's Avatar
    Join Date
    Jun 2002
    Location
    Riding the electron wave
    Posts
    372
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks all. I am going to go with your design arborint and see what I can come up with. However, again, I need to clarify something:

    In your one-line example a few posts up, I see that Product and Pricing are both objects ( classes ). However, in your most recent example, that is not the case. Have you changed the your design suggestion or am I just missing something? I don't mean to be dense, I just want to understand.
    Ducharme's Axiom: "If you view your problem closely
    enough, you will recognize yourself as part of the problem."


  17. #17
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sound to me like you should be using one of three alternatives: Template Method, Strategy or State.
    Sounds like a Strategy would be the best choice to begin with, though I'd hide this behind a Factory?

    Just my thoughts

  18. #18
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In your one-line example a few posts up, I see that Product and Pricing are both objects ( classes ). However, in your most recent example, that is not the case. Have you changed the your design suggestion or am I just missing something?
    If you look how Product uses Pricing you will notice that Pricing is an object. That's the Strategy part. As long as the Pricing object you pass to Product supports the getPrice method then Product works.
    PHP Code:
    function getPrice() {
      return 
    $this->pricing->getPrice($this->sku);

    You will need to build a Factory class that selects the correct kind of Pricing object to pass to based on the product type. The Factory could be as simple as:
    PHP Code:
    class PricingFactory {

    function & 
    instance ($type) {
        include_once 
    "inc/{$type}.php";
        return new 
    $type();
    }

    }

    // assuming you have a inc/GasesPricing.php with a GasesPricing class in it
    $pricing PricingFactory::instance('GasesPricing'); 
    Christopher

  19. #19
    I want my 4th arrow! garlinto's Avatar
    Join Date
    Jun 2002
    Location
    Riding the electron wave
    Posts
    372
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    *in voice of Mr. Burns* Excellent!

    The lightbulb in my mind is now starting to sputter and pop. While I was waiting for some clarification I did some research of my own and now think that I understand the Factory method a little more clearly as well.

    Thanks a bunch for all your help. When I complete the class[es] I'd like to post the beta and see what you think.
    Ducharme's Axiom: "If you view your problem closely
    enough, you will recognize yourself as part of the problem."



Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •