SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 36
  1. #1
    SitePoint Evangelist TomTees's Avatar
    Join Date
    Apr 2010
    Location
    Iowa
    Posts
    553
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Get and Set questions

    Is it correct that Get and Set are called "Accessor Methods"?

    Is there any reason why using them is bad?

    (I remember reading something somewhere - maybe on here - that said there was an alternative approach to using Setters/Getters?)


    TomTees

  2. #2
    Utopia, Inc. silver trophy
    ScallioXTX's Avatar
    Join Date
    Aug 2008
    Location
    The Netherlands
    Posts
    9,031
    Mentioned
    152 Post(s)
    Tagged
    2 Thread(s)
    Yes, they are called accessor methods (as they give access to properties of an object).

    And no, it's by all means not bad to use them. In fact, IMHO, it's bad not to use them.

    This roots in the belief that everything should be well seperated from each other and debuggable. When an object is allowed to change a variable of an other object directly, it's easy to loose track of where this happens, resulting in a debugging mayhem.

    Another good reason to use getters and setters is that you can manage which values are allowed, and which are not. For example, if you have a Person class, and that person has an "age" property, like so

    PHP Code:
    class Person
    {
       public 
    $age;
       
    // more code here

    I could very well do
    PHP Code:
    $p = new Person();
    $p->age 1000000
    Now, no-one lives to be a million, but the code won't raise any problems if you do this, but IMHO it should. Also, I could give a person a negative age, which is just as much impossible.

    If you do it like this
    PHP Code:
    class Person
    {
      private 
    $age;
      function 
    getAge()
      {
        return 
    $this->age;
      }
      public function 
    setAge($age)
      {
        if (
    $age 140) throw new Exception("I don't believe it, no-one is that old");
        if (
    $age 0) throw new Exception("Age must be a positive number");
        
    $this->age $age;

    That will give a warning that something's going wrong.
    Rémon - Hosting Advisor

    Minimal Bookmarks Tree
    My Google Chrome extension: browsing bookmarks made easy

  3. #3
    SitePoint Evangelist TomTees's Avatar
    Join Date
    Apr 2010
    Location
    Iowa
    Posts
    553
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ScallioXTX View Post
    Yes, they are called accessor methods (as they give access to properties of an object).

    And no, it's by all means not bad to use them. In fact, IMHO, it's bad not to use them.

    This roots in the belief that everything should be well seperated from each other and debuggable. When an object is allowed to change a variable of an other object directly, it's easy to loose track of where this happens, resulting in a debugging mayhem.
    I wish I could remember what and where I read that there was some debate on this topic...

    I think it was that everything in a class should be private?

    Or maybe it was that one class shouldn't call another class?

    Hmmm...


    Another good reason to use getters and setters is that you can manage which values are allowed, and which are not. For example, if you have a Person class, and that person has an "age" property, like so

    PHP Code:
    class Person
    {
       public 
    $age;
       
    // more code here

    I could very well do
    PHP Code:
    $p = new Person();
    $p->age 1000000
    Now, no-one lives to be a million, but the code won't raise any problems if you do this, but IMHO it should. Also, I could give a person a negative age, which is just as much impossible.
    (What about the fact that I was a Roman Soldier in my former life?!)


    If you do it like this
    PHP Code:
    class Person
    {
      private 
    $age;
      function 
    getAge()
      {
        return 
    $this->age;
      }
      public function 
    setAge($age)
      {
        if (
    $age 140) throw new Exception("I don't believe it, no-one is that old");
        if (
    $age 0) throw new Exception("Age must be a positive number");
        
    $this->age $age;

    That will give a warning that something's going wrong.
    So you should do debugging in classes that way, or is that just for during development?

    (I thought you were supposed to use some fancy "exception" thing when writing OOP classes?)

    Back to the original post...

    So it sounds like most people use Setters and Getters and that is a fairly acceptable way to code my classes?



    TomTees

  4. #4
    Utopia, Inc. silver trophy
    ScallioXTX's Avatar
    Join Date
    Aug 2008
    Location
    The Netherlands
    Posts
    9,031
    Mentioned
    152 Post(s)
    Tagged
    2 Thread(s)
    Quote Originally Posted by TomTees View Post
    I wish I could remember what and where I read that there was some debate on this topic...

    I think it was that everything in a class should be private?

    Or maybe it was that one class shouldn't call another class?

    Hmmm...
    Classes should call other classes, if they couldn't ... well, I just don't see how you would write code without classes calling each other.
    However, classes shouldn't set / get properties of other classes directly, for reasons described in my previous post.

    Quote Originally Posted by TomTees View Post
    (What about the fact that I was a Roman Soldier in my former life?!)
    That doesn't count, there is no former_life_occupation property in the Person class

    Quote Originally Posted by TomTees View Post
    So you should do debugging in classes that way, or is that just for during development?
    It's not merely for debugging, it's also to protect the integrity of the data. If you use setters and getters you can control what values are allowed for specific properties of a class, and that allows you to handle errors if something goes wrong.

    Quote Originally Posted by TomTees View Post
    (I thought you were supposed to use some fancy "exception" thing when writing OOP classes?)
    That's what the throw new Exception("some message") bit in the code of my previous post does
    See Exception Handling on Wikipedia for more info.

    Quote Originally Posted by TomTees View Post
    So it sounds like most people use Setters and Getters and that is a fairly acceptable way to code my classes?
    If you consider me most people, then yes
    All kidding aside, using setters and getters is considered better practice than accessing properties in other classes directly.
    Rémon - Hosting Advisor

    Minimal Bookmarks Tree
    My Google Chrome extension: browsing bookmarks made easy

  5. #5
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,135
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    Every object should have control of its own state. Public properties do not support this practice and expose state change without allowing the object being able to regulate it. I never use public properties for that reason. Restricting direct access to the objects state to methods also makes things much easier to debug and read.
    The only code I hate more than my own is everyone else's.

  6. #6
    SitePoint Evangelist TomTees's Avatar
    Join Date
    Apr 2010
    Location
    Iowa
    Posts
    553
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ScallioXTX View Post
    Classes should call other classes, if they couldn't ... well, I just don't see how you would write code without classes calling each other.
    However, classes shouldn't set / get properties of other classes directly, for reasons described in my previous post.
    Okay.


    That doesn't count, there is no former_life_occupation property in the Person class
    Ha ha.


    It's not merely for debugging, it's also to protect the integrity of the data. If you use setters and getters you can control what values are allowed for specific properties of a class, and that allows you to handle errors if something goes wrong.
    So you do most or all data validation in your classes in the Set method?


    That's what the throw new Exception("some message") bit in the code of my previous post does
    See Exception Handling on Wikipedia for more info.
    Oh, I think you left that out of your last post, actually.


    If you consider me most people, then yes
    All kidding aside, using setters and getters is considered better practice than accessing properties in other classes directly.
    Okay.


    TomTees

  7. #7
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    988
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    getters/setters ARE public properties, just with an overly verbose implementation. They share all the same design issues. There are hundreds of articles on the subject. Here's a good start: http://www.javaworld.com/javaworld/j...5-toolbox.html

    edit: ScallioXTX's code is a perfect example actually. You're still accessing the $age property directly, only now you have exceptions being thrown at arbitrary points in the application

    For a start, exceptions shouldn't be used for validation. They should be used when the system cannot work with the given data.

    Secondly, in the real world, this type of thing is rather cumbersome. Imagine the Person object is being populated from a form. By having an exception in the setter you can only present one error message at a time to the end user. Helpful. It also stops code excution so you cant show the form again.

  8. #8
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    I think what you may have read, TomTees, is about the magic methods, __get and __set.

    I don't use them personally, but that's simply because people here don't like them. I can't even remember the reasons - so if anyone DOES know, let me know :P
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  9. #9
    SitePoint Zealot
    Join Date
    Feb 2009
    Location
    Bristol
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    http://stackoverflow.com/questions/5...d-setters-evil

    Getters and Setters are not evil, but they can be. As with a lot of OOP methodologies, it's a balancing act.
    For example, decoupling is good, it helps maintain Single Responsibility Principle - but can lead to unwanted class proliferation. If you're writing a mini framework etc. how far do you need to go?
    On the other hand, strong coupling makes your system brittle/inflexible, but in some cases it's a better tactical decision given the context of the project.
    Design patterns require design decisions...

  10. #10
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    988
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    If you do it like this
    PHP Code:
    class Person
    {
      private 
    $age;
      function 
    getAge()
      {
        return 
    $this->age;
      }
      public function 
    setAge($age)
      {
        if (
    $age 140) throw new Exception("I don't believe it, no-one is that old");
        if (
    $age 0) throw new Exception("Age must be a positive number");
        
    $this->age $age;

    That will give a warning that something's going wrong.
    I cant edit my post but what you're actually doing here is Design By Contract, which is a completely different subject. However, in DBC you'd use assertions which get turned off in the live application, rather than exceptions which cant be turned off.

  11. #11
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Getters are called accessors, setters are called mutators.

    I try to avoid needing to use them.

    Far better to tell an object to do something, rather than be manipulated by some outside source.

    Trivial example:

    PHP Code:
    class Point
    {
    protected 
    $x;
    protected 
    $y;

    function print() { echo 
    '('$this->x', '$this->y')'"\n" }

    Rather than
    PHP Code:
    $p = new Point()
    echo 
    '('$p->getX(), ', '$p->getY(), ')'"\n"

  12. #12
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    988
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    The problem there, even obvious in that trivial example, is you've moved the display logic into the object. What if you want to display it differently? What if you want to display it in 2 different ways. Doing that makes maintenance and reusability a lot more difficult.

    You'd end up with huge classes which contain all the possible view logic used by that object. Then you have issues with complex objects and views which need data from multiple objects which are otherwise unrelated.

  13. #13
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TomB View Post
    The problem there, even obvious in that trivial example, is you've moved the display logic into the object. What if you want to display it differently? What if you want to display it in 2 different ways. Doing that makes maintenance and reusability a lot more difficult.

    You'd end up with huge classes which contain all the possible view logic used by that object. Then you have issues with complex objects and views which need data from multiple objects which are otherwise unrelated.
    Thats when the double dispatch comes in.

    PHP Code:
    class Point
    {
      protected 
    $x$y;
      function 
    accept(PointVisitor $visitor
      { 
        
    $visitor->visit($this->x$this->y);
      }
    }

    class 
    EchoPointVisitor implements PointVisitor
    {
      function 
    visit($x$y) { echo '('$x', '$y')'; }
    }

    $p = new Point();
    $p->accept(new EchoPointVisitor()); 

  14. #14
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    988
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Hmm that looks interesting and does work around the problem, but how well does it scale? I mean when an object has many properties it could get messy... and from a maintainability point of view doing something as simple as putting one extra property into the view means changing the HTML, the class which implements the interface, the interface itself and the function which passes the properties to the "visitor" (as you have called it there, is that the technical term?) rather than changing only the HTML. Seems like a lot of extra work from that point of view, imho.

    What about complex objects? E.g. classic example, an "Order" object which links to a "Customer" object and a set of "Item" objects. I cant see how that works without getting very messy and splitting the HTML across lots of different functions.

    I don't fully understand it so perhaps I'm missing something vital here but it seems like a lot of work for little practical benefit.

  15. #15
    SitePoint Evangelist TomTees's Avatar
    Join Date
    Apr 2010
    Location
    Iowa
    Posts
    553
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TomB View Post
    getters/setters ARE public properties, just with an overly verbose implementation. They share all the same design issues. There are hundreds of articles on the subject. Here's a good start: http://www.javaworld.com/javaworld/j...5-toolbox.html

    edit: ScallioXTX's code is a perfect example actually. You're still accessing the $age property directly, only now you have exceptions being thrown at arbitrary points in the application

    For a start, exceptions shouldn't be used for validation. They should be used when the system cannot work with the given data.

    Secondly, in the real world, this type of thing is rather cumbersome. Imagine the Person object is being populated from a form. By having an exception in the setter you can only present one error message at a time to the end user. Helpful. It also stops code excution so you cant show the form again.
    That was a good article except I only got half-way through it before it was over my head.

    And, yes, I think what you wrote, TomB, is what I was trying to recall.

    My post has started a good discussion, and it leads to my bigger question/problem...

    Where do I begin?!

    And who do I listen to?!

    Clearly, there are a lot of different approaches and opinions. And I have to be careful because this is like Michael Jordon and Larry Bird debating the finer points of basketball when I just want to learn how to play the game?!

    I want to build an e-commerce site.

    I do not want to buy one. And I don't want to configure one either.

    (If you wanted to learn to drive, hiring chauffeur or watching your friend drive isn't the way to learn.)

    It is my belief that if I break the problem down into smaller pieces, it is very attainable.

    In fact, a good portion of the hard part is already done ---> sketching the e-commerce site out and writing out the process flows (using Use-Cases).

    My only challenge now is learning how to take my design and write it out using PHP (and hopefully OOP).

    Sorry to go off tangent, but it seems like the more I read and the more I ask for help the farther behind I get?!

    If I can get some help on creating a handful of reasonable classes, deciding what their contents will be, and how they will talk back and forth, then I should be okay.

    The good news is I know exactly how our e-commerce site will look and work, I just need some help doing it in PHP and OOP.

    I guess I went off topic...



    TomTees

  16. #16
    SitePoint Guru bronze trophy
    Join Date
    Dec 2003
    Location
    Poland
    Posts
    930
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TomTees View Post
    Where do I begin?!

    And who do I listen to?!

    Clearly, there are a lot of different approaches and opinions. And I have to be careful because this is like Michael Jordon and Larry Bird debating the finer points of basketball when I just want to learn how to play the game?!

    I want to build an e-commerce site.
    Then I would say - just make plans to the best of your current abilities and begin work! Debates on design patterns can go on indefinitely with real experts having different opinions. Debating can be very time consuming - better to do your job and later you will be able to discuss the finer points or - you will discover the answers for yourself.

    As to your original question I would suggest this: treat getters and setters as fully valid constructs but when designing objects keep the tendency to have them do stuff instead of getting and setting their internal properties. I'm also learning OOP, I have already had some good experience with it but still I find there are a lot of patterns and ways to program I don't know of - it all has to come gradually because I don't think it's possible to grasp it all at once.

  17. #17
    SitePoint Evangelist TomTees's Avatar
    Join Date
    Apr 2010
    Location
    Iowa
    Posts
    553
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Lemon Juice View Post
    Then I would say - just make plans to the best of your current abilities and begin work! Debates on design patterns can go on indefinitely with real experts having different opinions. Debating can be very time consuming - better to do your job and later you will be able to discuss the finer points or - you will discover the answers for yourself.
    Thanks for the pep talk!

    Since this thread is mushrooming, feel free to hope over here to my related question on what classes do I need, and what data between classes and communications between classes makes sense.


    As to your original question I would suggest this: treat getters and setters as fully valid constructs but when designing objects keep the tendency to have them do stuff instead of getting and setting their internal properties.
    What do you mean by "have them do stuff"??



    TomTees

  18. #18
    SitePoint Guru bronze trophy
    Join Date
    Dec 2003
    Location
    Poland
    Posts
    930
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TomTees View Post
    What do you mean by "have them do stuff"??
    Ok, let me give you an example. Suppose you have a shopping cart object and you want to add a new product to the cart. If you went the route of "getting and setting their internal properties" that would look like this:
    PHP Code:
    $cart = new Cart;
    $products $cart->getProducts();
    $products[] = $newProduct;
    $cart->setProducts($products);

    $total $cart->getTotal();
    $total += $newProduct->getPrice();
    $cart->setTotal($total); 
    Now the same by "have them do stuff":
    PHP Code:
    $cart = new Cart;
    $cart->addProduct($newProduct); 
    This example is extreme but should illustrate the point well. In the first example you are essentially manipulating the object's internal properties from the outside while in the second one you only tell the object what to do and the object itself is responsible for performing all other necessary subtasks like incrementing cart's total, etc. It's much easier to maintain if you don't have to remember about all these subtasks from all the places you add a product. And in fact, the calling code should not care about them.

  19. #19
    SitePoint Guru
    Join Date
    Oct 2006
    Location
    Queensland, Australia
    Posts
    852
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I personally try to avoid using setters and getters. If a public property needs to be protected from bad or out-of-range data, then it should probably be avoided. One important thing I've learnt in the last few months, is to program for the language you're using. Because PHP, like most object-orientated languages, doesn't have any getter or setter mechanisms built-in, I try to avoid the need for them in my code. On the other hand, a language like C# which does have a built-in getter and setter mechanism, lends itself to heavier use of object properties.

    On the same note, PHP is also a dynamic language, so it's good to use this to your advantage when it comes to setters and getters. For example, I don't hesitate in making public boolean properties. Even though I can't guarantee that this property want be set to a non-boolean value, I can rely on PHP's dynamic type conversion in my code. For example, the following is perfectly safe, even though the variable I expect to be set to a boolean value, is actually an array...

    PHP Code:
    $boolean = array("chalk""cheese");

    if(
    $boolean == true)
    {
        
    // Do something

    Some may argue that this approach could hide bugs. That could be considered a con to some people, but it's important not to forget the pros of this approach, which is cleaner, simpler, less error-prone code. Programming is all about striking that balance, as I'm sure everyone would agree.

    You can also take advantage of PHP's inline type casting when your variable absolutely must be of a given type. E.g...

    PHP Code:
    $string 67.6;

    if((string) 
    $string === '67.6')
    {
        
    // Do something.

    Not a very good example, but it demonstrates my point. Inline type casting like this should only be rarely required. If you're code absolutely requires a variable to be a specific type or set of types, and a setter/getter is the only way you can think of achieving this, then this is normally an indicator that you should possibly rethink your class. It's sometimes not possible to avoid setters and getters completely, but use more as a last resort, than a preferred solution.

    That's my opinion anyway. Good design in one language, may not always be good design in another, and vice versa.

  20. #20
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by TomTees View Post
    Clearly, there are a lot of different approaches and opinions. And I have to be careful because this is like Michael Jordon and Larry Bird debating the finer points of basketball when I just want to learn how to play the game?!
    Actually what you are seeing is a progression.

    Hats off to ScallioXTX for a clear explanation of why a setter method can be better than a raw member variable, but (sorry) it's incorrect to say it's bad *not* to use them.

    The progression in this case is:
    (1) Classes as data holders
    (2) Classes as encapsulated data holders
    (3) Tell don't ask
    (4) I know what I'm doing so goodbye rules
    (5) DSLs

    The problem with 1 is that anything can change my internal values. I was caching that thank you very much, now what?

    The problem with 2 is that although you cannot get near my innards, I was a pain to write and endlessly bureaucratic. Rules is rules, blah, blah.

    The good thing about 3 is you realise that, if all I do is hang on to a value for someone else, what on earth am I doing with that value. I hand it over or do the work. Less code that way. Shorter is better.

    If I know the downside in 4, I can still have public properties. If I'm an internal object that is only seen by a few classes and the semantics are pull stuff in and push stuff out, go use a public property. Maybe the semantics are that it actually is a "property". If I get stuck later I can dig my way out with __get(), right? If you really can get away with it, just use a variable. In code shorter is better...oh, I already said that.

    In DSL land of 5, what you see is not what you get. I may look like an object with public members, but I have __get()/__set() secrets. Are my values in memcache? In Postgres? You'll never know. Write the code you want and let me do my magic.

    Steps 1 - 5 are universal and known as the "Dreyfus model". 1 is novice (what do I do?), 2 is advanced beginner, where everything is rule fitting. 3 is competent, they really solve the problem. 4 is proficient, they look at the larger picture. 5 is expert, they are looking to change the game and create new rules. People are at different levels for different skills. You can often guess their level from their tone .

    Advice like not using exceptions for validation is kind of level 2 ("why not?" says level 4). Trouble is you need to make the mistakes that a lot of this advice is trying to avoid, just so you can get to level 4. You are doing the right thing though. In having heard the nagging voices, when you do hit the problems you will have a solution at the ready.

    Quote Originally Posted by TomTees View Post
    In fact, a good portion of the hard part is already done ---> sketching the e-commerce site out and writing out the process flows (using Use-Cases).
    Can you express these as test cases? If so then you have indeed done the hard part.

    Quote Originally Posted by TomTees View Post
    If I can get some help on creating a handful of reasonable classes, deciding what their contents will be, and how they will talk back and forth, then I should be okay.
    That's incredibly hard and an unrealistic goal. Not what you wanted to hear?

    Object models rarely appear out of thin air. If the do, they are invariably wrong. You have to evolve them, usually as you code. OO actually makes it easy to change stuff as you go. Right now you are at the window sill worrying if you should jump, not knowing you are about to land on a feather bed. Jump damn you.

    The book you are after is "Refactoring" by Martin Fowler. This will answer a lot of the questions you have already asked.

    The main thing is to code a small part of your solution. Then a second bit. Don't write a third bit until you have rewritten the first two parts to be nice. Then write the third bit. Modify it 'til it's nice. Only then the 4th bit...you get the picture. Your object model will either emerge or you'll get stuck with a more specific question.

    Quote Originally Posted by TomTees View Post
    The good news is I know exactly how our e-commerce site will look and work, I just need some help doing it in PHP and OOP.

    I guess I went off topic...
    You so didn't

    Can you tell us one of your use cases, one of the work flows you have worked out? Then we can post code.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  21. #21
    SitePoint Addict
    Join Date
    Oct 2004
    Location
    Sutton, Surrey
    Posts
    259
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I DON'T use getters and setters. The reason for this is code efficiency. I deal in applications which access a lot of database tables, so I have a separate class for each table. These inherit from an abstract table class which contains all the code which is common to every database table. Each table has a series of columns, but rather than get/set them individually I leave them in an array so that I can move them around 'en bloc'. For example, when using a form to insert data into a table all the columns are presented in the $_POST array, so I insert the whole array using a single method call:
    Code:
    $dbobject = new $table;
    $fieldarray = $dbobject->insertRecord($_POST);
    That is much more efficient than unpicking each column by name from the $_POST array and inserting it individually.

    As I use the MVC pattern I regard each database object as being the Model, and is instantiated and accessed by the Controller.

    You should notice that the Controller does not use getters and setters for individual field/column names, therefore the same controller can be used on ANY database table. This in turn means that I now have a set of reusable controllers, one for each operation, rather than one for each table+operation. This gives me maximum reusability, and makes it easy to modify a single controller and have the changes echoed across a large number of tasks.

    Some of you may yell at me and say "But that's not how it's done!", but who says that YOUR way is the ONLY way? Who says that YOUR way is the BEST way?

  22. #22
    SitePoint Evangelist TomTees's Avatar
    Join Date
    Apr 2010
    Location
    Iowa
    Posts
    553
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft View Post
    Hi...

    Actually what you are seeing is a progression.
    No, the term is "Thread Entropy"...


    OO actually makes it easy to change stuff as you go. Right now you are at the window sill worrying if you should jump, not knowing you are about to land on a feather bed. Jump damn you.
    I'm trying, just want to make a "calculated" first jump.


    Can you tell us one of your use cases, one of the work flows you have worked out? Then we can post code.

    yours, Marcus
    Ha ha. My main use-case including all flows is over 600 lines, so that wouldn't be a good way to help me out.

    I need help taking baby steps.

    I'll have to ask some smaller more specific questions. (The Setter/Getter was just a side theoretical type question, I suppose.)



    TomTees

  23. #23
    SitePοint Troll disgracian's Avatar
    Join Date
    Aug 2006
    Location
    Samsara
    Posts
    451
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ren View Post
    Thats when the double dispatch comes in.
    You probably need to point out that you would have to be very careful what you pass to the visitor object: i.e., copies of private members unless they are immutable. Otherwise the visitor object could modify private data, and that's not good.

    And that could run into performance issues if you have to copy large amounts of data.

    Cheers,
    D.

  24. #24
    SitePoint Guru Chroniclemaster1's Avatar
    Join Date
    Jun 2007
    Location
    San Diego, CA
    Posts
    784
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TomTees View Post
    I think it was that everything in a class should be private?

    Or maybe it was that one class shouldn't call another class?

    (I thought you were supposed to use some fancy "exception" thing when writing OOP classes?)

    So it sounds like most people use Setters and Getters and that is a fairly acceptable way to code my classes?

    TomTees
    I think you are seeing some Thread Entropy here, maybe what's needed is a little explanation of WHY you do some of these things, because absolutely it's a balancing act.

    Keep things private (Information Hiding): This is a good principle, and I usually start by making everything in my class private, then you up the access modifier the minimum amount necessary to accomplish whatever needs to get done.

    The advantage of keeping things private is that code which lives outside of your class doesn't know how the class works. If you go in and change something later, does it matter to any code outside of your class? Well, if you're only changing things that are private the answer is a resounding NO. It didn't know what the hell was going on in the first place, and you've only touched stuff that it didn't know about. Therefore, the more stuff that stays private, the more stuff that stays flexible. If you have to change something that's protected, let's say the name of a protected member, you now have to look through any code which subclasses your class to see if you find the old name anywhere and update that too. If you change the name of a public member... you are now looking through your entire code base for any place that you consumed that class. It's not that you CAN'T do that, in fact if your program is going to be upgraded it will have to be, it's just a pain in the ass. This kind of thing is simply accepted on long term iterative development projects. The key is that making things private MINIMIZES how often we need to do this. So hiding your implementation is an extremely flexible practice. The flip side is that a class with ALL private members quite literally does NOTHING. Again, the real idea is that you want to minimize the public interface (the members, properties, functions, etc.) that people can see from the outside. Give other classes the things they need. Don't give other classes additional information, just because it might be convenient at the moment; it will bite you when you have to modify your code later.

    Minimize class communication (Decoupling): You can see how this is just the flip side of Information Hiding. Information Hiding allows your class to guarantee that other classes don't become dependent on things you would really prefer they don't use; so you literally use "private" to forbid them to use it. Decoupling means writing your class so that it doesn't USE of other classes, at least no more than necessary.

    Keep in mind that if you're class doesn't call ANY other class, then it is stuck with doing all the implementation itself. Encapsulation is the most powerful tool in programming because it allows you to hide implementation, so "Perfect Decoupling" comes at the price of not getting ANY benefits of Information Hiding. Here again, it's about what trade off makes the most sense to you.

    Say you are creating an AuthenticationManager class to log users in. Do you have it get all the information from the UI? Probably not. Let the UI class handle those details and call you to manage the authentication parts. The AuthenticationManager can then assume it's first job is when someone calls its public Login() function and the username and password will be supplied as parameters. No need for AuthenticationManager to get involved in any of that.

    Now we need to find out what the user's hashed password is from the database? Is that really authentication related? Data Access is more DAL level work, so call the DAL class which handles your users and pass in the user name; the DAL will hand you back the hashed password from the database. NOW we have coupled Authentication Manager to a function in the DAL, is this bad? Well, it means that someone (quite probably you) will have to update this code in AuthenticationManager if someone ever changes the interface of that DAL function. That's not a great thing and we would prefer not to if we don't have to. But in this case there's no other way to get that hashed password so effectively we HAVE to. Therefore I AM going to couple my AuthenticationManager to this DAL function because I want to be able to hide all the implementation of how the DAL function actually does everything it does. In this case, my desire for encapsulation and information hiding is trumping my desire for decoupling.

    Now I have the password the user provided and the hashed password from the database. Obviously this does me NO good, I can't compare those two things. I need to hash the password the user provided. Am I going to write this code into the AuthenticationManage? If I do, I have excellent decoupling. However, here again, I would submit that there's nothing about an AuthenticationManager that specifically screams "I hash stuff." If this is a really small application and I want to combine the hashString() function into this class, then we should probably rename our class from AuthenticationManager to SecurityManager because it's no longer handling just authentication but cryptographic management as well. Our other option, is to encapsulate hashString() out to a new CryptographyManager class and couple ourselves to the hashString() function. Note that if we want to get any work done we are coupling to the hashString() function. Unless we're not going to accomplish anything (and our program will do nothing), we are only talking about WHERE we are coupling to. We can either depend on a function in our class or we can depend on a function in another class. Ideally, we would like the function to be in our class to limit the complexity of our application (fewer classes running around is better than many classes running around). However, if our classes our difficult to understand (like a hashString() function in an AuthenticationManager) or if our classes get too long or confusing then it's time to simplify things with another class.

    How do you determine what to break out?? ABSOLUTELY look for the code you can pull out which will require the minimum amount of contact between the old and the new class, ie look for how you can decouple the new class most completely. Chances are this is the best way to create a usable abstraction as well.

    Exceptions are expensive, so they're generally my 3rd choice. 1st, try to take care of it yourself. Work around the error; this may mean throwing out the results of an iteration and continuing, assuming a default value, etc. 2nd, terminate and see if the user can take care of it; this is standard practice for user input errors. There's no need to throw an exception, just return an error string telling the user what they need to do e.g. "I'm sorry, I can't create a new account for you without a valid email address, please try again." In best case scenarios, exceptions are only to handle issues that you believe will never come up in your application when it goes live. But then we live in the real world so you will find them sometimes.

    Getters and Setters are ways to expose information or modify information. This means they couple one class to another and violate the principle of information hiding. Are they bad? No. Just make sure you use them only when you really need them. For example, I find very little objectionable about Getters. If you've created your classes to good and consistent abstractions, you have a very robust application architecture, and you should feel free to create getters for any "necessary" information that other parts of the application may need. ie don't create a field and a Getter function for it. Wait until another class needs it and then create a Getter method; you should probably consider whether that class really NEEDS the information in the first place too.

    Setters, I'm absolutely more skeptical about. I'm perfectly willing to let other parts of the app LOOK at the first and last name fields of my User class. Should any of them be CHANGING it?? If I think twice before I create a Getter, I think AT LEAST three times before creating a Setter. When given the opportunity, I've actually created the admin for a website as a separate application on a separate subdomain to increase security for reasons that included this. If you don't need to admin the application, you can leave out a lot of Setters. You'll need those in the admin application, but not here.
    Whatever you can do or dream you can, begin it.
    Boldness has genius, power and magic in it. Begin it now.

    Chroniclemaster1, Founder of Earth Chronicle
    A Growing History of our Planet, by our Planet, for our Planet.

  25. #25
    SitePoint Evangelist TomTees's Avatar
    Join Date
    Apr 2010
    Location
    Iowa
    Posts
    553
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Chroniclemaster1,

    Excellent post!!

    I really like your detailed pararaphs on "Information Hiding" and "Decoupling". The way you explained things will definitely help me at a larger design level when I'm figuring out what classes to create, what each class should do, and if one class should talk to another.

    And you did all of that in a polite fashion!

    Thanks,


    TomTees


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
  •