PDA

View Full Version : When should I wrap functionality in its own class?


brianemsu
08-20-2009, 12:00 AM
I have been working with OOP concepts for a little while now and I am starting to grasp some of the concepts. Although, I am wondering about when and if I should wrap certain functionality in it's own class. For instance, the example I'm working on now contains a Sprite object that is loaded with text fields stacked vertically to make a tall text box sprite object. I want this sprite object to move up and down on mouse input. Now, I could just include the mouse input listeners inside the class containing the sprite object to be moved OR I could wrap the mouse input functionality inside its own class. I'm thinking the "MouseUtil" class, as I've come to think of it, would be a Singleton, as there is only one mouse ever attached to the computer ( in most cases ).

It may look something like this:

package com.bee.utils
{
import flash.display.DisplayObjectContainer;
import flash.errors.IllegalOperationError;
import flash.events.MouseEvent;

public class MouseUtil
{
private static var _instance:MouseUtil;

public function MouseUtil( enforcer:SingletonEnforcer )
{
// throw error if instantiated with the 'new' operator
if( enforcer == null ) throw new IllegalOperationError( "Singleton Class!" );
}

// singleton method
public function get instance():MouseUtil
{
if( MouseUtil._instance == null )
{
MouseUtil._instance = new MouseUtil( new SingletonEnforcer() );
return MouseUtil._instance;
}
else
{
throw new IllegalOperationError( "An instance of MouseUtil already exists" );
}

}

public function startMouseMove( target:DisplayObjectContainer ):void
{
// target would most likely be a reference to the stage
target.addEventListener( MouseEvent.MOUSE_MOVE, onMouseMoveEvent );
}

private function onMouseMoveEvent( e:MouseEvent ):void
{
// --add functionality here to move the sprite object up and down--
//
// being so specific to the one sprite object, it would create a strong
// dependency here... this doesn't seem to be what I want, but I have to create
// the dependency somewhere... where is the best place?
}

// also would add more mouse functionality later, as well as ways to remove the listeners
//
// is all of this just me trying to reinvent the wheel?

}
}

class SingletonEnforcer {}

Am I just adding unneeded complexity by wrapping mouse functionality in its own utility class? What would you recommend?

Flash Gordon
08-21-2009, 05:26 AM
What I'd do: Your TextFieldStack object should be looked at as a component. Implement the functionality it needs to work, but allow it to be controlled from the outside as well. Think about how an accordion component works. It does control itself but allows itself to be controlled externally as well. For instanced I can get the "selectedItem" and clicking it would animate it to that state as well.

I'd also recommend not using singletons very often. Because they are an easy concept to grasp they tend to be way too overused and the word "Util" implies a static class.

brianemsu
08-22-2009, 08:30 PM
ok, I have heard that singletons are not good to use all the time... why is this?

I went back and re-watched Lee Brimelow's video on the OOP scroll, where he abstracts a scrollbar and scrollbox into their own classes and it helped out a little in understanding what you're talking about.

It's not going to help my messy code for now though... I'll have to remember this for the next project.

wvxvw
08-22-2009, 09:32 PM
Besides what Flash Gordon said, why do you throw an error in the instance getter? This doesn't really make sense since after you create the MouseUtil once, you can have as many references to it as you wish, and throwing error in the getter will not prevent you from making more references.

brianemsu
08-22-2009, 09:46 PM
hmm, I might have typed that out faster than I was thinking. Maybe that should be

public static function get instance():MouseUtil
{
if(MouseUtil._instance == null)
{
MouseUtil._instance=new MouseUtil(new SingletonEnforcer());
trace("Singleton instantiated");
}
return MouseUtil._instance;
}

ASWC
08-23-2009, 07:37 AM
If you are learning OOP concepts then I would advise you to keep singleton as your last subject of studies.

maskedMan
08-23-2009, 03:22 PM
An argument against Singletons

http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/

The same guy giving a talk about global state and singletons

http://www.youtube.com/watch?v=-FRm3VPhseI


And after that, google the phrase "singletons are evil" and observe the myriad articles on the subject.

brianemsu
08-23-2009, 07:19 PM
@maskedMan Thanks for those links! I watched the video, a lot of it went over my head but I guess the main point I got from it was that Singletons ( Global state ) are bad because they hide your dependencies. You should always reveal your dependencies in an obvious manner ( by requiring them in the constructors ).

I'll read through more of Misko Hevery's articles. There's a lot of good information there.

Also, I have a background in Graphic Design and I feel like the world of programming is one huge rabbit hole that I'm falling into. It's fun though!

maskedMan
08-23-2009, 07:47 PM
Misko's opinions are heavily colored by his experience as a software test developer (not a bad thing), and Singletons have a way of making automated testing painful. Personally, I tend to agree with the idea that global state is bad and that using Singletons as a glorified global state makes programs less readable, less coherant, and harder to maintain. When you have the time and luxury to make a sensible architecture, you really should do so.

So why do people still rely on Singletons? It's not just because they're in the big, shiny Gang of Four Design Patterns book. It's because they are quick to implement, easy to create, and their global nature allows you to break architectural restraints at the drop of a hat in an emergency situation. The practice of requiring specific objects as arguments in other object's constructors is known as Dependency Injection, and it does make an easier to read and harder to screw-up structure... but depending on your situation that extra structural overhead could just get in your way if it ends up that all your assumptions have the rug pulled out from under them. (What, you mean the people on high have demanded that we must never use CreditCardProcessor and must always pass CreditCard to the Database?!?!?)

Likewise, sometimes you have only an hour before ship and some ridiculous feature request has been made and you have to shove it in somehow... static-reference Singleton to the rescue! Completely breaks your architecture, but at least it saves the day (and your job).



Also, I have a background in Graphic Design and I feel like the world of programming is one huge rabbit hole that I'm falling into. It's fun though!


That's pretty common in the Flash world. Fine Arts and Multimedia student here. Wasn't a CompSci major by any stretch of the imagination, aside from taking 100 and 200 level CS electives as an Undergrad.

Try looking into some other programming languages sometime for a glimpse at all the things Flash abstracts away. (I'm thinking C and C++ here).

proas
01-01-2010, 01:55 AM
In his book Implementation Patterns (http://www.amazon.com/Implementation-Patterns-Kent-Beck/dp/0321413091) Kent Beck talks about "A Theory of Programming". You can read that section here (http://www.ddj.com/architect/204201170?pgno=1). The whole read is fantastic, but I would pay special attention to his "Principles":


Local Consequences
Minimize Repetition
Logic and Data Together
Symmetry
Declarative Expression
Rate of Change


Also check out Uncle Bob's Principles of OOD (http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod), especially the Single Responsibility Principle.