SitePoint Sponsor

User Tag List

Page 2 of 3 FirstFirst 123 LastLast
Results 26 to 50 of 63
  1. #26
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    netherlands
    Posts
    104
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm sorry to bump this thread up, but I tried the following:
    I wanted to see how a very simple application (part of) would turn out using noun-classes with representative roles, and one using doers with actual doer roles. Well, these designs are how I would do it, so there's probably something terrible wrong in the following examples, but ok

    The idea was to create a simple betting mechanism (let users bet on a particular match), with the following purposes/requirements:
    - Beeing able to bet on a match
    - Check for winners when a match is played
    - Update finance if a bet is a winner

    So I started coding away with the noun approuch, leading to this:
    PHP Code:
    <?
    class Bet
    {
        var 
    $_score;
        var 
    $_amount;
        var 
    $_finance;
        
        function 
    Bet($score$amount$finance)
        {
            
    $this->_score $score;
            
    $this->_amount $amount;
            
    $this->_finance $finance;
        }
        
        
        function 
    checkWinner($score)
        {
            if(
    $score == $this->getScore())
            {
                
    $this->_updateFinance();
            }
        }
        
        
        function 
    _updateFinance()
        {
            
    $this->_finance->add($this->_amount*2);
        }
        
        
        function 
    save()
        {
            
    //some simple db insertion
        
    }
    }


    class 
    Match
    {
        var 
    $_bets;
        
        function 
    Match($bets)
        {
            
    $this->_bets $bets;
        }
        
        
        function 
    setPlayed($score)
        {
            foreach(
    $this->_bets AS $bet)
            {
                
    $bet->checkWinner($score);
            }
        }
        
        
        function 
    addBet($score$amount$finance)
        {
            
    $finance->remove($amount);
            
    $bet = new Bet($score$amount$finance);
            
    $bet->save();
        }
    }


    class 
    Finance
    {
        var 
    $_amount;
        var 
    $_owner;
        
        function 
    Finance($amount$owner)
        {
            
    $this->_amount $amount;
            
    $this->_owner $owner;
        }
        
        
        function 
    add($amount)
        {
            
    $this->_amount += $amount;
        }
        
        
        function 
    remove($amount)
        {
            
    $this->_amount -= $amount;
        }
        
        
        function 
    getOwner()
        {
            return 
    $this->_owner;
        }
    }
    ?>
    I wouldn't say it is bad after all actually, it was less confusing to allocate methods then I thought (probably because it is so small). Though, their are still methods to discuss their home about, without me beeing really able to defend my allocation discision.

    One thing I have to mention though, is (which I didn't expected actually) that I need to pass a db/connection class to the Bet class, because it needs to insert inself. An alternative would be to use a datamapper or some sort, so that the match class can insert the bet instead, so passing the db to the match. But... that feels like a 'i-dont-know-what-to-do-with-it, so-i-just-place-it-here' discision. The match does not need the db connection, I just gave it to take care of the insert the bet instead of bet itself (maybe the method addBet() is wrong there? )

    Second design, using doers:
    PHP Code:
    class BetPlacer
    {
        function 
    BetPlacer($db)
        {
            
    $this->_db $db;
        }
        
        
        function 
    place($score$amount$financeHolder)
        {
            
    //insert in db
        
    }
    }


    class 
    WinChecker
    {
        function 
    WinChecker($bets)
        {
            
    $this->_bets $bets;
                    
    $this->_score 0;
        }
        
        
        function 
    checkWinners($score)
        {
                    
    $this->_score $score;
            foreach(
    $this->_bets AS $bet)
            {
                
    $this->_checkWinner($bet);
            }
        }
        
        
        function 
    _checkWinner($bet)
        {
            if(
    $bet['score'] == $this->getScore())
            {
                
    $financeHolder $bet['financeHolder'];
                            
    $financeHolder->add($bet['amount']*2);
            }
        }
    }


    class 
    FinanceHolder //well err.. I just changed the name for doer sake, I liked the role actually :o
    {
        var 
    $_amount;
        var 
    $_owner;
        
        function 
    Finance($amount$owner)
        {
            
    $this->_amount $amount;
            
    $this->_owner $owner;
        }
        
        
        function 
    add($amount)
        {
            
    $this->_amount += $amount;
        }
        
        
        function 
    remove($amount)
        {
            
    $this->_amount -= $amount;
        }
        
        
        function 
    getOwner()
        {
            return 
    $this->_owner;
        }

    I must say (beeing really objective on the subject ), that this design feels more correct. Making this design makes me feel like I've done a correct job; the methods feel like they're home. Passing the db is now no problem at all really. Just give it to the BetPlacer, it's his role to place bets, so its natural and logical to give him that nasty db object. The classes are maybe to focussed, maybe they would be more appropriate as a method of a bigger class, but this is more or less how I would do it.

    Why did we need Match after all? The purpose was to check if bets were won, so this design sticks more to its purpose. Instead of changing the state of match by inserting its score (well, after all, this is how it is used in the domain model/real world. Any thoughts maybe?), we just call a WinnerChecker to see which bets were one directly.

    This seems like the doer approach has a win. But actually this 'test' has made me started thinking even more. I got rid of the bet and match classes in the doer example, but I get the feeling that I need these dataholders in one way or another. Im so used to these dataholders that Im afraid to let them go. Did I do the wrong thing? Are dataholders nescesary? Maybe they are really usefull, for instance while trying to present them on the screen. Or to prevent a long parameter list. Or to make it easier to insert them into db memory. I see dataholders as a really tricky point, if not, the trickiest.

    Dataholders, hmm. I looked it up at refactoring (Fowler), and found it at the "bad smells" section. So it's actually a bad smell, except for the sentence they mention at the end of the paragraph: "They are okay as a starting point, but to participate as a grownup object, they need to take some responsibility". Did the Bet class had enough responsibility... ?
    Last edited by Manor; Jan 8, 2005 at 12:51.

  2. #27
    SitePoint Zealot
    Join Date
    Jun 2004
    Location
    Bogota
    Posts
    101
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi!

    I've been thinking about this a lot too and I've come to the conclusion that there are certain classes you cannot get rid off just because they are passive. I suppose it has to do with the fact that you'll ultimately have to deal with simple data, that is not suppose to do anything else but exist... In your case, the Bet class.

    In both code examples you provided, you had to go bet by bet until you found the winner. Granted, in the first code example you'd ask the bet itself if it is a winner by doing:

    PHP Code:
              foreach($this->_bets AS $bet)
              {
                  
    $bet->checkWinner($score);
              } 
    which is not a real responsability of the bet IMO. You then moved to

    PHP Code:
              $this->_score $score;
              foreach(
    $this->_bets AS $bet)
              {
                  
    $this->_checkWinner($bet);
              } 
    wich looks better to me, but evidences even more the fact that you need to work with a passive object -- the bet. In this case the bet was implemented just as an associative array you pass over to the classes that need them to compute a winner or whatever you need.

    I can't find a way to reduce a system just to doers my self. I always find there are a few objects only ment to hold the information needed for others to do the stuff with them.

    Just as an excercise, if you were writing a card game, do you think you'll be able to get rid of the class named Card? (even if it is just an associative array).

    Regards,
    -Andres
    If I have wings, why am I walking?

  3. #28
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    netherlands
    Posts
    104
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by otnemem
    I can't find a way to reduce a system just to doers my self. I always find there are a few objects only ment to hold the information needed for others to do the stuff with them.
    I share the same feeling. But I find it so d*mn shame that we need them. They do nothing, they represent only data. A class is way too complex to only manage data. Can't we do without them? I got used to them after a while, but I kept thinking; we have all kinds of refactorings to let a class not grow too big or stay too small, to create an almost perfect design. But something like dataholders we can't remove? It seems like a big design fault, which we can't solve.

    Quote Originally Posted by otnemem
    Just as an excercise, if you were writing a card game, do you think you'll be able to get rid of the class named Card? (even if it is just an associative array).
    It seems normal at first to have a card class. Thats how we normally set things up after all. But when I started to implement this bet idea, I also thought it would be near to impossible to create something without dataholders. And still, I get the feeling that it only worked without dataholders because this example is so small, and any expanding in the application would require a bet class after all.

    And sure, you will always need an associative array or longer parameter list. You need information anyway. But I think this is a better way of transporting and holding information then making a seperate class, doing nothing, only holding that information. Or is it?

  4. #29
    SitePoint Guru
    Join Date
    Dec 2003
    Location
    oz
    Posts
    819
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Often you need a start when you begin on a domain you haven't modelled before. The noun and verb idea are a starting point when you have nothing more solid to go on. This is fine. It will be refactored into a more acurate model over time as you learn more about your domain.

    Over this time you find that you add responsiblity to some of these elements and they come to have more responsibilities. They may will likely still hold data, but also have responsibilities to go with them. Those that don't may be better factored into more domain specific entities that are more responsibility centered.

    To say that you just shouldn't have anything that starts as a data holder is just putting unneccesary restraints on your modelling efforts, which will be reflected in a more obscure and less comprehensible design.

    Quote Originally Posted by Manor
    Dataholders, hmm. I looked it up at refactoring (Fowler), and found it at the "bad smells" section. So it's actually a bad smell, except for the sentence they mention at the end of the paragraph: "They are okay as a starting point, but to participate as a grownup object, they need to take some responsibility". Did the Bet class had enough responsibility... ?
    You haven't modelled the whole system yet. As you would develop it, it would either have responsibilities added, or else be refactored into something else that is more suitable.

    Quote Originally Posted by otnemem
    I can't find a way to reduce a system just to doers my self. I always find there are a few objects only ment to hold the information needed for others to do the stuff with them.
    It helps to have entities that people can relate to in their mind. I seems logical initially to have a Better, a Bet object because you can relate such a model to entities that exist as you know them.

    Code:
    Better better = BetterRepository.GetBetterById(id);
    better.PlaceBet(new Bet(amount, race))
    In this case, the bet may be just a data holder. If so, it could be refactored at a later stage into a service.

    In fact, I would likely have it stay as a data holder even if it attracted no responsibility since the code is clear and unambiguous. To remove or avoid them completely simply because you read somewhere will lead to a model that you will find hard to understand, use and improve on.

    Eli

  5. #30
    SitePoint Zealot
    Join Date
    Jun 2004
    Location
    Bogota
    Posts
    101
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lazy_yogi
    Code:
    Better better = BetterRepository.GetBetterById(id);
     better.PlaceBet(new Bet(amount, race))
    In this case, the bet may be just a data holder. If so, it could be refactored at a later stage into a service.
    Hmm... I'm having trouble picturing it. Care to elaborate?

    Quote Originally Posted by lazy_yogi
    In fact, I would likely have it stay as a data holder even if it attracted no responsibility since the code is clear and unambiguous. To remove or avoid them completely simply because you read somewhere will lead to a model that you will find hard to understand, use and improve on.

    Eli
    I'm glad I'm not alone in this. I feel exactly the same.

    Regards,
    Andres
    If I have wings, why am I walking?

  6. #31
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Does the class have a singular name? A plural name might indicate that what you really want is the singular name, and some container class.
    Choosing From Candidate Classes -

    http://www.gvu.gatech.edu/edtech/BOOST/designmap.html

  7. #32
    ********* 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 otnemem
    I've been thinking about this a lot too and I've come to the conclusion that there are certain classes you cannot get rid off just because they are passive. I suppose it has to do with the fact that you'll ultimately have to deal with simple data, that is not suppose to do anything else but exist... In your case, the Bet class.
    I agree. I have a theory that this comes down to just three situations...

    1) The OO world is rubbing against the outside world, such as a user interface or a DB.
    2) You need to store data temporarily in memory because you want to create aggregate results over time separated data. E.g I want to search for unpaired brackets in a stream. This gives you containers/data holders.
    3) You have a temporary object for the life of a method call. You are using an object because you don't want to restrict yourself to a hash at this stage in case it gets more complicated later or because it's a little more self documenting.

    At least I cannot think of any others.

    Quote Originally Posted by otnemem
    Just as an excercise, if you were writing a card game, do you think you'll be able to get rid of the class named Card? (even if it is just an associative array).
    Hm. I think this is going to illustrate just where the doers approach wins over noun/verb. At the early stages of a (betting) system deciding the data structures is most likely to be premature. For example you could have a Hand class that calculates it's current value. Adding a "card" to the hand produces a new hand...
    PHP Code:
    $new_hand $dealer->draw($hand)->discardWorst();

    class 
    Hand {
        function 
    addCard($card) { }
        function 
    discardWorst() { }
        function 
    calculateValue() { }
    }

    class 
    Dealer {
        function 
    draw() {
            return 
    $hand->addCard($this->getRandom())
        }

    Here card could be a simple string. All depends on the game of course, but I reckon you can be more sure about having a Dealer class than you can about having a Card class.

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

  8. #33
    SitePoint Zealot
    Join Date
    Jun 2003
    Location
    Elsewhere
    Posts
    107
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's something that's been bothering me for a while now:

    All the 'verb' classes are nouns as well. Writer, Connector, BetPlacer.... they're all nouns based on verbs (to write, to connect, to place a bet).

    What's more, a nounified-verb class often decribes a behaviour, and its interface mirrors its name: Writer->write(), Connector->connect(), BetPlacer->placeBet(). Apart from the behaviour described in its name, objects of this type have little substance: there is little or no object data.

    Could they be a (bad) code smell, or an indication for refactoring?


    ...

    After giving this matter a bit more thought, I think I can identify (at least) four types of classes/objects. I'm going to post some half-baked ideas here, so this list most probably needs some refactoring (if it makes any sense at all):

    1. Business Domain objects: (User) generally quite passive

    2. Behavioral objects: (Writer) interface mirrors classname, little substance.

    3. Application? objects: (Database) most 'complete' objects of these four. Combines some configuration with behaviour. Interface does not mirror class name.

    4. Structural (or Flow?) objects: (Iterator) little substance, behaviour, or responsibility at the applicaiton level. Provide structural flexibility.


    Feedback anyone?

  9. #34
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    netherlands
    Posts
    104
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Azmo
    What's more, a nounified-verb class often decribes a behaviour, and its interface mirrors its name: Writer->write(), Connector->connect(), BetPlacer->placeBet(). Apart from the behaviour described in its name, objects of this type have little substance: there is little or no object data.

    Could they be a (bad) code smell, or an indication for refactoring?
    Yes, I've been thinking about this as well. But maybe it is based on what scale of resonsibility you base the name/role of the class on, and especially what scale your application needs. Writer may be a very small role in a, lets say, airline application, to write ini files or something like that. On the other hand, if your application is about writing reports or anything like that, the responsibility for writing becomes a lot bigger, and the class will more likely have more methods/data other then $writer->writeTo($file). I would say that one should make these classes on instinct, and later on see if the seperated class adds any value, and if it carries a large enough responsiblity to stay.

    About the 4 categories, I'm not sure. The first 2 seems logical, although I don't know how much these 2 differ. Why can't bussiness objects have doer names? About those other two... well, they seem to be categories on another level. A more detailed one. But I can't think of any better ones, so I have no right to comment yours :P

  10. #35
    ********* 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 Azmo
    All the 'verb' classes are nouns as well. Writer, Connector, BetPlacer.... they're all nouns based on verbs (to write, to connect, to place a bet).
    I think the real win from this discussion will be discerning a good starting point that can be dished out to members on the forum who are completely new to OO and are all at sea. I don't think we will catch all classes, etc, but that doesn't matter. Once you start developing the code will wil speak to you and tell you where it wants to go.

    In that regard I think BetPlacer is a better starting point than Bet. Likely it will eventually become a class like Gambler, where placing bets is just one option. On the other hand I can see someone getting stuck at...
    PHP Code:
    class Bet {
        function 
    place() { }

    Quote Originally Posted by Azmo
    Could they be a (bad) code smell, or an indication for refactoring?
    Factories often have just one active method. On the other hand, don't forget the constructor. A DB connection will connect() in it's constructor and have an execute() method for sending SQL.

    If you do end up with lot's of single method classes, I have a hunch that it will sort itself out...
    PHP Code:
    $placer->placeBet($dealer$amount$chip_stack); 
    We are aggregating two objects as simple parameters. Once the ChipStack appears only in the BetPlacer context it will make sense to move the functionality into that class. The merging will become even a little mechanical.

    I think the single method classes are a more fluid starting point than lot's of nouns. Also by their very nature the code will start minimal and functional. I think these are big wins. I doubt that this would be the final end point of the code though.

    Quote Originally Posted by Azmo
    .1. Business Domain objects: (User) generally quite passive

    2. Behavioral objects: (Writer) interface mirrors classname, little substance.

    3. Application? objects: (Database) most 'complete' objects of these four. Combines some configuration with behaviour. Interface does not mirror class name.

    4. Structural (or Flow?) objects: (Iterator) little substance, behaviour, or responsibility at the applicaiton level. Provide structural flexibility.
    That was what I was trying to do with a practical application. We should aggregate our "findings" into an uber list that we can compress down. If we know where we are heading, then it might be easier to see how to get there. Does anyone have any design examples where they got completely stuck? It would be nice to find some bad formulations too.

    Also regarding the categorisation of classes, there is one in Roles, Responsibilitiesand Collaborations (Wirfs-Brock)...
    1) Information holder
    2) Structurer - maintains relationships
    3) Service provider
    4) Coordinator - reacts to events and delegates
    5) Controller - makes decisions
    6) Interfacer - transforms information and requests

    I have never found this list very useful though. Which is odd, because the rest of the book is a gold mine.

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

  11. #36
    Resident OCD goofball! bronze trophy Serenarules's Avatar
    Join Date
    Dec 2002
    Posts
    1,911
    Mentioned
    26 Post(s)
    Tagged
    0 Thread(s)
    I think you all are putting way too much thought into this. While publically usable frameworks need a good naming system, the actual system is less important than consistancy within it. I don't care if an object is named Dog, Canine, Cat or Feline. However, I'd expect objects named Dog and Cat to co-exist, as well as Canine and Feline, but never Dog and Feline or Canine and Cat.

  12. #37
    ********* 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 Serenarules
    I think you all are putting way too much thought into this
    I don't. Naming is the most important thing you can do to a class. OO design is hard and I think you are rather missing the point of the thread. It's about coming up with tighter, more flexible designs faster. It's a very practical discussion.

    Frankly I don't think these issues are discussed nearly enough. Just trawl through some old postings on OO to see just how big an issue this is. Design is a critical part of software development. Selecting your classes is a critical part of the design.

    How do you do your design?

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

  13. #38
    SitePoint Enthusiast
    Join Date
    Nov 2004
    Location
    Arizona, USA
    Posts
    94
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    I think the single method classes are a more fluid starting point than lot's of nouns. Also by their very nature the code will start minimal and functional. I think these are big wins. I doubt that this would be the final end point of the code though.
    I agree 100%.

    From a refactoring standpoint, it also seems much more logical to refactor the responsibilities of the single method 'doers' into classes with more responsibility (i.e. your BetPlacer to Gambler example), as opposed to factoring out responsibility from ambiguous 'noun' classes that have attracted too much responsibility in the first place..

  14. #39
    Resident OCD goofball! bronze trophy Serenarules's Avatar
    Join Date
    Dec 2002
    Posts
    1,911
    Mentioned
    26 Post(s)
    Tagged
    0 Thread(s)
    Marcus,

    I'd be happy to answer your question. I think the basis behind my assertion is proved in the opening line of your post. "I don't [agree]." In order for a disagreement to exist, the topic at hand must be based on opinion and not fact. Having said that, there are two answers to your question. The simple answer is that I don't really have a development plan per se. The extended answer is that my tactics depend greatly on the overall complexity of the application at hand, and the target language, as not all languages support the same features or ease of implementing existing features.

    In general I follow prescribed methods, such as conceptual and physical analysis of existing procedures before doing anything else (the 80/20 rule). After flowcharting the processes and catalogging the data schemas, I design the database. Typically this is a Microsoft MSSQL database and therefore I have stored procedures available. With that in mind, I design the database such that it can stand alone the application itself. All stored procedures take username and hashed password as the first two parameters. Following that, anything else will be a very thin client app. In the design on this client, After some more paperwork designed to categorise elements into data access, transactional and presentation layers I then code the interfaces that my objects will implement, then the base classes, stubbing out all function such that they contain no functional code. I move up the ladder from there. Once all classes have been stubbed out and return simple "expected" results, I can test the framework without worrying about affecting actual data. Then I simply fill in the method code from the ground up with actual working code.

    But I haven't talked about naming yet. I typically follow old style C naming styles...

    IObject = interface declaration
    CObject = base level inheritance - (change I to C) adds basic working code
    CThisObject = working class
    CThatObject = working class

    That's the "formula". Now to the names. Based on what I described in the above paragraphs, I create certains types of objects. At the data layer, I create things such as CRecord and CRecodset, then derive specialized classes per table, such as CMembers and CMember. Recordset level classes support select functions and maintain results. Record level classes maintain a single record and support update functions. The presentation layer is typically the easiest and contains classes that handle input and output. As things are pretty abstracted at this point, there aren't a great many presentation classes. Typically one class per page (CIndex, CMemberList, etc). The transactional later is the one that falls most under the topic of this thread as the names become harder to come up with. What I do is look at what I already have in the data layer, and the presentation layer and find a common ground that hooks the objects up. For example, if I need to hook up CIndex (presentation) with CSessions (data layer) I may code a middle component as COnlineList or CForumList. These class contain typical transaction logic and database calls via the data layer components.

    In a nutshell, data layer components get table-based names, presentation layers get page-based names, and all middleware layers get task based names, typically something that makes sense based on a presentation-to-data relationship.

    I would like to point out that *in my opinion* there is no right or wrong for object naming. Certainly some conventions are more readable then others and still others make more logical sense. What it comes down to is personal taste, consistancy, and great documentation. Remember, as with the w3 standards, there are times when an app requires something more, or at least something that may break compatibility. This isn't wrong per se. While the advantages and disadvantages of compliance are known, that doesn't mean all application MUST be compliant. If there's a need, then do it. If you have a need to name your classes one way over another, do so. Just be consistant and document your api.

  15. #40
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for your post

    Thanks for your posting,

    In a nutshell, data layer components get table-based names, presentation layers get page-based names, and all middleware layers get task based names, typically something that makes sense based on a presentation-to-data relationship.
    On the point of your presentation layer naming, what basis are you using? For example, what would you name a presentation layer or class for displaying a list of comments from a blog in an administration area?

    I'm finding your representation of things interesting, so please continue

  16. #41
    Resident OCD goofball! bronze trophy Serenarules's Avatar
    Join Date
    Dec 2002
    Posts
    1,911
    Mentioned
    26 Post(s)
    Tagged
    0 Thread(s)
    This is a PHP forum, so I assumed web presentation here, so the "page" based naming. Different display contexts may require different naming conventions.

    The answer to your question requires several parts.

    The methodology involved in displaying a list of recently submitted comments in an administration interface (presumably for approval/rejection) would involve objects at several layers. The data layer objects would most likely be named CComments, which wraps calls to fetch the data (same component used for client access) and stored results in a collection internally. This class would expose iterators for looping etc. Each item would be of class CComment, which maintains field values and exposes insert (for use with CComments->AddNew(CComment $item)), update and delete calls. The middle tier here would contain the logic for adjusting the CComments content appropriate to that of a user with admin status, and would be named something like CAdminComments. This object would expose further abstraction of the calls to the database, such as GetAdminComments ApproveComment, RejectComment. These functions woudl then in turn call the right CComments functions. The presentation layer would most likely conists of several classes. The top level class being CAdmin (to wrap admin.php). It would use classes like CUserIfno CSessionInfo, CInputVars (sanitizes all acceptable form and request vars then unset's the system vars - gotta keep the app clean) to get operating info, and theming classes such as CSkinGlobal for headers, footers, and other common elements. Finally it would use CAdminMenu, CAdminDisplay and CAdminAction to display things correctly. CAdminDisplay would handle your display by making use of the CAdminComments object.

    Note: actual HTML would be kept in external files in theme specific folders. The skin classes never change. They'll know based on settings which folder to load pre-defined files from.

    If I had a current project going, I'd take a snap of my object diagrams so you could get a better picture of what I am doing. Maybe next time.

  17. #42
    ********* 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 Serenarules
    I'd be happy to answer your question.
    And indeed you did; very thoroughly .

    I can see now why you are not finding this discussion helpful. You are basically coding a database driven app. The stuff that is left has very little business information, it is all the technical stuff of presenting tables. This stuff is mostly formulaic in object terms, with the design skill pushed into the data modelling. Your set-up is...

    Presentation --> ResultSet --> StoredProcedures/Data Model

    Really the area we are discussing is outside of that narrow remit (although a lot of PHP apps. fall into this slot). More like...

    Presentation --> Application --> Domain Model --> Persistence

    You are getting rapid initial development within a well known domain. This discussion relates to unclear or constantly evolving domains or one where the application is not primarily about presenting database data.

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

  18. #43
    Resident OCD goofball! bronze trophy Serenarules's Avatar
    Join Date
    Dec 2002
    Posts
    1,911
    Mentioned
    26 Post(s)
    Tagged
    0 Thread(s)
    Thanks Marcus. I concur that a volatile system, such as you describe, should impose a better system of designing objects than what my systems current use, however, I would probably find some way of augmenting my own strategy to adapt rather than alter the entire idiom. The reason is simple actually: all application, regardless of client environment, programming language and storage method, all do several common things. Those things would be collect data, act on data, store data and present data. Even if your writing an imaging application, it's still acting on data. Multi-server distribution does complicate things however. I suppose my inclination would be to administer an in-depth review of the overall system architechture and identify commonalities. Then write a set of interfaces that could be used to extend/alter the system as needed, rather than rely on naming. Let's take the betting example.

    IBet -> CBet - > CRaceHorseBet / CCardGameBet

    IBookie ->CBookie -> CRaceHorseBookie / CCardGameBookie

    IPayoff -> CPayoff -> CRaceHorsePayoff / CCardGamePayoff

    I wouldn't make the PlaceBet function a member of IBet, rather IBookie because in real life one would actually place the bet with a bookie. The bookie doesn't come to you.

    $bookie->PlaceBet($bet);

    I don't think it matters overall what the architecture of the system is. If you sit down and really think about what the system is actually doing, and how similar concepts are played out in real life, it becomes easier to design and implement your application classes.

  19. #44
    ********* 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 Serenarules
    I don't think it matters overall what the architecture of the system is. If you sit down and really think about what the system is actually doing, and how similar concepts are played out in real life, it becomes easier to design and implement your application classes.
    I think it is crucial. To have a hybrid that you describe is a nightmare, with duplicated logic, or at least logic spanning systems, all over the place. Once you drop out of the DB driven app. sphere of influence, it's definitely right to then go all of the way to a coded model.

    Given that an all or nothing approach is better (my experience is that it wins hands down), which way to go?

    It is only sufficient to "think about what the system is actually doing" on very small/stable applications. Real ones that run small companies (20000 line+) cannot be built this way, or even by a single programmer. They are built iteratively (refactoring at each stage). The model will initially be wrong, the requirements will be wrong and probably the choice of architecture will be wrong as well. Once apps. become a certain size, they all become volatile.

    There is a whole field of study devoted towards categorising problem spaces, called "sense making". Most models have these categories: order, hidden order, complex, chaos. Synonyms vary.

    An example of an ordered domain is a parcel service. They are all pretty similar and differ only slightly in the cost versus speed of delivery profile. They all have vans, planes and motorcycle couriers. If you wanted to enter this arena, most of the solutions would be known and all you can do is tweak existing models or go out of business a few percent at a time. Companies working in this region have a top down mangement structure.

    Hidden order is the area that programmers and scientists love. There is a difficult problem to be solved and you have to get a team together. With no known solutions, management had better keep out of it. Team building, communication and adaption are the order of the day.

    An example of a complex situation is a war. Any plan you try is then passed it's sell by date, because the enemy will come up with a counter. The military describe this as "no plan survives contact with the enemy". The stock market is another example, and in fact small businesses (non market leaders) in general. They are chaotic in the mathematical sense and predictable only in the short term.

    A good example of chaos is a children's party. Not much you can do to assure happiness and pretty much anything could happen at any time. Here the goal is reaction to sharply changing events to change the situation. An emergency ward is another example. All you can really do is make the correct resources available and have skilled individuals. There is no time for communication and learning during the event.

    The first three are often described in business terms as best practice, good practice and bad practice (avoiding that is).

    Because of the lead times in building datamodels, and their high sensitivity to change, DB designs are common in large market leading companies or in systems that just have to work and don't come into contact with the market place (e.g. payroll). You can spend a week changing one table and porting the data, because it won't change that often. The majority of actual money earning business resides in the complex region, however. As developers we cannot operate in this region so, to give us some order, we impose iterations and some form of requirements gathering. This gives us windows of stability in which to fight for a market edge.

    The window is small. Typical iterations are 2-4 weeks. What do your processes look like if their requirements change twice every month. Designing everything up front will be an early casualty for sure if it takes two weeks to develop the design.

    It is this complex/hidden region that is familiar to me. It's the reason I moved from data modelling to OO.

    The rise of the internet has made IT less of a back-end operation and more of a front-end revenue generator. Personally I can see the relational DB declining and being replaced with alternative rapid development technologies, such as full text and specialist CMS tools. I can also see them being replaced as integration platforms in favour of messaging, such as SOAP.

    Oh wait, that's already happening...

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

  20. #45
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    netherlands
    Posts
    104
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    I think the real win from this discussion will be discerning a good starting point that can be dished out to members on the forum who are completely new to OO and are all at sea. I don't think we will catch all classes, etc, but that doesn't matter. Once you start developing the code will wil speak to you and tell you where it wants to go.
    What kind of starting point did you had in mind? Like a step-by-step list to identify important classes and behaviours or something?

    Quote Originally Posted by lastcraft
    I have never found this list very useful though.
    Me neither

  21. #46
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    netherlands
    Posts
    104
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by bdunlap
    From a refactoring standpoint, it also seems much more logical to refactor the responsibilities of the single method 'doers' into classes with more responsibility (i.e. your BetPlacer to Gambler example), as opposed to factoring out responsibility from ambiguous 'noun' classes that have attracted too much responsibility in the first place..
    Interesting, I haven't thought about it yet in such kind of way. One question though: Why should it better from a Refactoring standpoint? I haven't really found any refactoring texts that mention that its more logical to refactor small classes into bigger ones, in opposite to extracting ones.

  22. #47
    Resident OCD goofball! bronze trophy Serenarules's Avatar
    Join Date
    Dec 2002
    Posts
    1,911
    Mentioned
    26 Post(s)
    Tagged
    0 Thread(s)
    Marcus, as always, you've given me a great post to consider. I'll reply once I've thought about what you've said.


  23. #48
    ********* 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 Manor
    What kind of starting point did you had in mind? Like a step-by-step list to identify important classes and behaviours or something?
    Nothing that grand. Say someone asks "how do I choose my classes?", one punt might be "choose a few major business actions and create them as single method classes, refactor from there". Beats the noun/verb thing for me.

    Actually I am not really sure .

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

  24. #49
    SitePoint Enthusiast
    Join Date
    Nov 2004
    Location
    Arizona, USA
    Posts
    94
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Manor
    Interesting, I haven't thought about it yet in such kind of way. One question though: Why should it better from a Refactoring standpoint? I haven't really found any refactoring texts that mention that its more logical to refactor small classes into bigger ones, in opposite to extracting ones.
    'Logical' was a poor choice of wording on my part. 'Practical' is probably closer to the thought that I was trying to convey. That said, none of the reading material dealing with refactoring that I'm familiar with specifically mentions the idea in that context, either.

    At first thought, the concept sounds somewhat ludicrous. Why on Earth would you want to refactor into larger classes? The simple answer is - you wouldn't, generally. If, however, you start off with a design that consists of a large number of single-method 'doers', you've already got a (overly) fine-grained model. Each responsibility is in plain view, unobstructed by the clutter that an ambiguous 'noun' class has the habit of attracting. To me, this seems a much better (and clearer) starting point for refactoring. As Marcus said...

    Quote Originally Posted by lastcraft
    If you do end up with lot's of single method classes, I have a hunch that it will sort itself out...
    and...

    Quote Originally Posted by lastcraft
    I think the single method classes are a more fluid starting point than lot's of nouns. Also by their very nature the code will start minimal and functional. I think these are big wins. I doubt that this would be the final end point of the code though.
    With this I agree 100%. And I guess that's why I'd find it to be more 'practical' (maybe another bad choice of words ) from a refactoring standpoint. You'd find yourself refactoring these small, easy-to-spot responsibilities into somewhat 'larger' roles that make sense. This as opposed to starting off with big, cluttered nouns where the new relationships don't present themselves as easily at first glance (to me, at least).

    I guess what it boils down to for me is, it seems like a lot less work..

  25. #50
    Resident OCD goofball! bronze trophy Serenarules's Avatar
    Join Date
    Dec 2002
    Posts
    1,911
    Mentioned
    26 Post(s)
    Tagged
    0 Thread(s)
    I think we are discussing multiple things here are we not?

    1) Multiple function classes vs. single function classes
    2) Noun class names vs. non noun class names
    3) Object modelling vs data modelling

    I have come to some conclusions regarding these issues.

    1) I think it depends on the object context. Validators will probably only need one function: validate. Other, higher level objects, may require a great many functions to operate efficiently.

    2) I'm still undecided on this one, though I still lean toward logical naming based on "what's it do?" or "what is it?". Some objects can't be given a non noun name. For instance, I prefer typing so I use a custom set of php classes I wrote. This set includes classes such as String (note the upper case s) which operate like this:

    $value = new String('abcd');
    $value->concat('efgh');

    3) I think these two items are both required and exist on a scale from left to right, much like democat and republican. Where your app fits will be some place between the two extremes. Your teams level of experience and intellect will dictate this to some degree. I'm not sure one is more right than the other, on a whole, but can affect the outcome of a project depending on the needs of the app.

    Does that make sense?


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
  •