What I learned today:
Underlining Principles of being a Software Craftsman:
*Experimenting with multiple Design Patterns: I am sure once a Craftsman reaches a certain point, they can simple pick up on the code scent and rapidly unveil the most logical Design Patter; however, before that point is reached, trying multiple patterns to a given problem might prove not only to create a better solution, but also to be a valuable learning experience.
General Knowledge of Language:
* Data classes, or classes composed of very little functional code and nearly all variables, can be dangerous. They typically will lead to procedural code, which is undesirable in Object Oriented software.
* It is usually better to avoid inheritance. If there is a way around it, even if you have to share instances of a class, you should use the lesser of two evils.
* Cyclic dependancies are typically a bad sign, however it is acceptable if two classes are logically dependent. In other cases you should stick an interface in between.
* Dispatcher / Jump Table: Though not really a design pattern so much as a strategy, I used it as a pattern to mold my code around. Typically a Dispatcher or Jump Table is an array of functions with indices as the result of some equation of operation. A common example is how C++ uses Jump Tables to access methods in a class.
I used a Dispatcher as an array of objects rather than functions. Each object was an instance of class designed to handle a different event. It was used to eliminate a flurry of if-else statements in order to determine which Key had been pressed, and if there were any modifiers (shift, command, alt being held down). I created an array of 16 different objects, each was the derivative of a KeyProcessor interface, and each had a processKey(int keyCode) method. Using 4 deciding factors, and scaling each, I created a simple algorithm to properly dispatch the KeyEvent to the proper handler.
* Chain of Responsibility Pattern: This patter works just as you might imagine from the name. It begins with some request that needs to be handle. This request is sent to some main processing object which checks to see if it can handle it, and if not, passes it along to the next processing object in the chain. If the next processing object can't handle the request, it the passes it along, and so forth until the request finally reaches something that can handle it. Typically there will be a well defined mechanism to pass requests along the chain, such that new processing objects can be easily added. The Chain of Responsibility pattern can actually be quite similar to a dispatcher with a pyramid like structure of responsibility.
I was going to use the Chain of Responsibility pattern just like a dispatcher, having high level links passing KeyEvents down to lower level links based off the same criteria I used to created my dispatcher algorithm. The chain would have been more like a tree, and each level would have a binary decision of which direction to pass the event on. In the end, this would have eliminated a large portion of the if-else chain, but would still contain several conditional statements.
Thats pretty much it for today. I have faith that tomorrow my design will withstand the scrutiny of Micah! Of course, it wouldn't surprise me if he had one simple improvement, which somehow alluded me, and that drastically alters my design...