I've updated this component to allow for keyboard and forward/back navigation. I'm still improving it, refactoring, but it is almost finished.
Here is the original post.
“Test until fear turns to boredom”
I've updated this component to allow for keyboard and forward/back navigation. I'm still improving it, refactoring, but it is almost finished.
Here is the original post.
My code smells bad. There is no doubt about it. As soon as I read that metaphor my head was nodding with understanding. This book is a classic, and I recommend it to anybody that wants to improve their coding habits and create more flexible applications that don't make you sad and angry.
It is a thick volume, but 2/3s of the text is the catalog of refactorings. This makes the text describing the concepts of refactoring a relatively short read. Mr Fowler guides you through the process, providing a simple example and clearly explaining the thought processes involved. The catalog covers a wide range of common approaches to refactoring an application.
[kml_flashembed movie="http://joelhooks.com/examples/slideShow/VESlideShow.swf" height="530" width="500" /]
I've been working on improvements for this thumbnail/slideshow component. The way the continuous scroll flows is very nice. It provides a very fluid feel. I have it reading XML from SlideShowPro director. SSPD simply gives a structure of albums and images, so the component should work from essentially any XML source as long as it follows the same schema:
<gallery> <album id="0" description="DESCRIPTION" title="TITLE" tn="PATH" lgpath="PATH" tnpath="PATH"> <img src="FILENAME" /> ... </album> </gallery>
There is still a good bit of work to do. Right now the slideshow is coupled with the thumbnail container. I think that should be seperated, because I can see various uses for thumbnails outside of a slideshow. It needs style and event metadata so that it will function as a proper Flex component. I am also going to roll it into mediated PureMVC components for inclusion in VE:Session.
The source is here.
In computer programming, an enumerated type is an abstract data type used to model an attribute that has a specific number of options (or identifiers) such as the suit of a playing card (i.e. a Club, Diamond, Heart or Spade). Using this type allows the program to handle the attribute more efficiently than a string while maintaining the readability of the source code.
-from Wikipedia
I've found this method (illustrated in code below) for enumeration of datasets to be useful, and at this point even essential, in my applications. Prior to this I was actually cutting and pasting the arrays that I was using in my various combo boxes and other selection components as dataProviders. By breaking the dataset into an enumeration class, it makes it easy to maintain the list and lets the dataset function as a first class citizen, ensuring that your data is consistent throughout the application.
package enum { /** * CloudTypeEnum enumerates cloud types. * @author JHooks * */ public class CloudTypeEnum { public static const NONE:CloudTypeEnum = new CloudTypeEnum( "None", -1 ); public static const CUMULUS:CloudTypeEnum = new CloudTypeEnum( "Cumulus", 0 ); public static const STRATUS:CloudTypeEnum = new CloudTypeEnum( "Stratus", 1 ); public static const CIRRUS:CloudTypeEnum = new CloudTypeEnum( "Cirrus", 2 ); public static const NIMBUS:CloudTypeEnum = new CloudTypeEnum( "Nimbus", 3 ); public var value:String public var ordinal:int /** * CloudTypeEnum constructor * @param value * @param ordinal * */ public function CloudTypeEnum( value:String, ordinal:int ) { this.value = value; this.ordinal = ordinal; } /** * A list of cloud types * @return * */ public static function get list( ):Array { return [ CUMULUS, STRATUS, CIRRUS, NIMBUS ]; } /** * A list of cloud types appropriate for use in ComboBox and other * selection components as a DataProvider * * myComboBox.dataProvider = CloudTypeEnum.cList; * @return * */ public static function get cList( ):Array { return list.unshift( NONE ); } /** * Select a cloud type by its value property * @param value * @return * */ public static function selectByValue( value:String ):TaskTypeEnum { for each ( var cloudType:TaskTypeEnum in CloudTypeEnum.list ) { if ( value == cloudType.value ) return cloudType; } return NONE; } } }
Thanks to Cliff Hall who showed this to me via one of his PureMVC demo applications. For the life of me I can't remember which one.
This is here as sort of a TODO for myself this year. I want to try this experiment. I really like the concept of breaking down OO projects into this extra fine granularity.
He suggests writing a 1000-line program with the constraints listed below. These constraints are intended to be excessively restrictive, so as to force developers out of the procedural groove. I guarantee if you apply this technique, their code will move markedly towards object orientation. The restrictions (which should be mercilessly enforced in this exercise) are:
1. Use only one level of indentation per method. If you need more than one level, you need to create a second method and call it from the first. This is one of the most important constraints in the exercise.
2. Don’t use the ‘else’ keyword. Test for a condition with an if-statement and exit the routine if it’s not met. This prevents if-else chaining; and every routine does just one thing. You’re getting the idea.
3. Wrap all primitives and strings. This directly addresses “primitive obsession.” If you want to use an integer, you first have to create a class (even an inner class) to identify it’s true role. So zip codes are an object not an integer, for example. This makes for far clearer and more testable code.
4. Use only one dot per line. This step prevents you from reaching deeply into other objects to get at fields or methods, and thereby conceptually breaking encapsulation.
5. Don’t abbreviate names. This constraint avoids the procedural verbosity that is created by certain forms of redundancy—if you have to type the full name of a method or variable, you’re likely to spend more time thinking about its name. And you’ll avoid having objects called Order with methods entitled shipOrder(). Instead, your code will have more calls such as Order.ship().
6. Keep entities small. This means no more than 50 lines per class and no more than 10 classes per package. The 50 lines per class constraint is crucial. Not only does it force concision and keep classes focused, but it means most classes can fit on a single screen in any editor/IDE.
7. Don’t use any classes with more than two instance variables. This is perhaps the hardest constraint. Bay’s point is that with more than two instance variables, there is almost certainly a reason to subgroup some variables into a separate class.
8. Use first-class collections. In other words, any class that contains a collection should contain no other member variables. The idea is an extension of primitive obsession. If you need a class that’s a subsumes the collection, then write it that way.
9. Don’t use setters, getters, or properties. This is a radical approach to enforcing encapsulation. It also requires implementation of dependency injection approaches and adherence to the maxim “tell, don’t ask.”
I went ahead and ordered the ThoughtWorks book too. I've used their Mingle product, which I find very compelling, so I am looking forward to their essays.