No, I'm sorry this is not a real app. I am building something else, but I don't think it is appropriate for me to post the actual software model we're working on at work. I'm not sure if my client will be okay with me asking on a public mailing list.
Although the Room / Window example sounds ridiculous on the surface, it is where the methods should be placed that puzzled me. To use a super abstract example, it'll be like.. 1 ObjectA has an ObjectX, ObjectY, and ObjectZ. ObjectX, ObjectY and ObjectZ have n public methods each (where n may be = 10+). If I push all behaviors onto ObjectA, then A will have all 30+ public methods (+ its own). Yes, we'll respect the Law of Demeter, and no one will know ObjectA really has ObjectX/Y/Z, but wouldn't ObjectA become super fat? Regards, Henry Ho On Tue, Feb 17, 2009 at 1:06 PM, Peter Bell <[email protected]> wrote: > > I'm a little confused. Do you actually have a customer paying you to > build the application below? If not, and you are building a real OO > app I'd suggest using that as the example. There are only rules of > thumb in OO design and they are incredibly context specific. Try > asking an artist "which color is best" for a painting . . . As such, > using some kind of generic example is usually a really bad way to go > (which was why I always hated the OO books talking about engines being > composed within a car). > > Of course, apologies if this is a real app that you *are* building > right now for a client to mock up a room control system or something. > It's just not all that often I see such apps in the CF world. > > Best Wishes, > Peter > > > On Feb 17, 2009, at 3:45 PM, Henry wrote: > > > > > The Room object is getting bloated, what should I do? > > > > Room has Windows, and you guys advised me to use Room.closeWindow(). > > That's what I did. However, instead of one getWindow() function in > > Room, Room now has 10 methods related to operations for Window. > > > > Now Room also has an owner of type User , and owner handles the login > > (), changePassword(), etc. > > Room has an owner, that makes sense. > > Which solution's better now? > > > > Solution 1: // 1 getOwer() method in Room > > > > Room.getOwner().changePassword(oldPassword, newPassword) > > Room.getOwner().validatePassword(password) > > Room.getOwner().setName(newName) > > > > > > Solution 2: // 3 methods in Room > > > > Room.changeOwnerPassword(oldPassword, newPassword) > > Room.validateOwnerPassword(password) > > Room.setOwnerName(newName) > > > > > > How about... Plan? Let's say Plan has method isEnable(featureName). > > The view layer needs to call this function to determine which Tab to > > show. > > Room has a plan, that makes sense. (One user can have many Rooms, > > each Room has a plan) > > > > > > Solution 1: // 1 getPlan() method > > > > Room.getPlan().isEnable("customizeWindow") > > Room.getPlan().isEnable("selectStyle") > > Room.getPlan().isEnable("ceilingFan") > > > > > > Solutions 2: > > Room.canCustomizeWindow() > > Room.canSelectStyle() > > Room.hasCeilingFan() > > > > Now I'm confused. Do you guys still think solution 2 is the preferred > > choice? Even thought it can make my Room object bloated with several > > times more methods? > > > > > > Thank you! > > Henry Ho > > > > > > On Feb 12, 12:53 pm, Henry <[email protected]> wrote: > >> Thanks a lot. > >> > >> I liked Solution 2 too, but found the method Room.closeWindow() a > >> little awkward. I guess it is actually fine, after hearing the > >> reasons from you guys. > >> > >> Yes, this is a high tech room that closes its own Window. :) > >> > >> Henry Ho > >> > >> On Feb 12, 11:20 am, Jared Rypka-Hauer <[email protected]> > >> wrote: > >> > >>> Principles: Tell don't ask, encapsulation, domain object modeling > >> > >>> Unequivocally option 2. Option 1 doesn't actually model anything > >>> other > >>> than relationships. A real domain model reflects relationships thru > >>> composition but uses behavior to shield peer objects from their API. > >>> This allows them to act only upon those relationships where the are, > >>> in the eyes of the domain, subject matter experts. Domain objects > >>> like > >>> Room, Window and Door should all have behaviors. Given the > >>> confines of > >>> the example (which is kind of a bad one, really), Room.closeWindow() > >>> is perfectly appropriate even though in real life you would probably > >>> say Person.closeWindow(Room,Window); since Rooms don't actually > >>> close > >>> their own windows... ;) > >> > >>> Hey, it could even be that Person.closeWindow() has private > >>> functions > >>> and state like variables.currentRoom and findClosestWindow(), so > >>> Person.closeWindow() would (in my model anyway) use Person's state > >>> to > >>> find the closest window in a room. > >> > >>> OTOH, internally, Room's protected scopes could do the same thing > >>> thru > >>> findPesonClosestToWindow().closeWindow(variables.myWindow), or any > >>> combination of the above. In any and/or all cases though, they all > >>> focus on encapsulation by implementing the behaviors in the > >>> appropriate domain object allowing everyone to interact without > >>> worrying about objects they need't worry about. In providing > >>> closeWindow(), Room is actually encapsulating the operations > >>> required > >>> to close or open the window and as a result is actually OO. > >> > >>> Along those same lines, option 2 abides by the principle of "Tell, > >>> don't ask" which is a key OO concept in helping the developer to > >>> establish behaviors on domain objects. If you're telling a domain > >>> object to take action in its domain space, you're unconcerned with > >>> the > >>> implementations of it's composites (so you're only working with the > >>> API of the adjacent object... in this case, the Room) and letting > >>> the > >>> object itself worry about the internal details of actually closing > >>> the > >>> window. > >> > >>> Option one is technically procedural, queueing up operations to be > >>> executed in sequence by some object that knows far too much about > >>> its > >>> environment. Room.getWindow().close()... asking an object for > >>> another > >>> object, then taking direct action on that object yourself is a very > >>> procedural approach. It works just fine, but it's not OO... no, > >>> really, it's not. I promise. "get" is not a behavior! ;) > >> > >>> I'm not saying I like one better than the other, because the "It > >>> Depends Principle" says that either could be more valid than the > >>> other > >>> depending on context. hehehehe > >> > >>> J > >> > >>> On Feb 12, 2009, at 12:49 PM, Henry wrote: > >> > >>>> Let's say.. there's a Room. Room has Window, and Door. Room has a > >>>> state (empty, not empty). And this Room is smart that it only lets > >>>> you close the Window when it is not empty. > >> > >>>> So.. we have: > >> > >>>> Room.isEmpty() > >>>> Window.open() > >>>> Window.close() > >> > >>>> Now... since Window.close() needs to check if room is empty first, > >>>> what should be a better solution? > >> > >>>> // Solution1: > >>>> Room.init() > >>>> Window.init(room) // window has reference to Room > >>>> Window.close() // checks if Room is empty first by > >>>> calling > >>>> room.isEmpty() > >> > >>>>> Room.getWindow().close() > >> > >>>> // Solution2: > >>>> Room.init(Window window) > >>>> Window.init() // window has no reference to Room > >>>> Window.close() // will close itself w/o checking > >> > >>>>> Room.closeWindow() // Room object checks if it isEmpty(), if > >>>>> yes, > >>>>> then it calls window.close() > >> > >>>> What do you guys think? Which one is the better solution? Why? > >>>> base > >>>> on which OO principle? > > > > > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "CFCDev" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/cfcdev?hl=en -~----------~----~----~----~------~----~------~--~---
