Tuesday, November 27, 2012

OO Programming with JavaScript

I came from an OO world. When I started coding with JavaScript, I always struggled with losing the techniques we used in OO programming to reduce code duplicates. Examples are we can easily use composition and inheritance in OO to make code reuse. Here is something I figure might be useful for people  migrating from OO world into JavaScript.

Basically, I want to use simple features in JavaScript to simulate the structures in the OO world: composition and inheritance. The result is actually very simple.

function myClassCtor (ctorParams)
{
var inner = {};
inner.privateData = ctorParams; // or something similar
inner.privateFunction = function(functionParams)
{
// function body
};

var outer = {};
outer.publicFunction = function (funcParams)
{
//function body
};
return outer;
};


This is the basic shape of a "class". Everything attached to the "inner" object is equivalent to your private section of the code and everything attached to the "outer" object is equivalent to your public section. I picked the word "inner" and "outer" since "public" and "private" seem to be reserved words (that's what DevStudio is telling me :-). In JavaScript every function is by nature "virtual", you just provide another function body to override.

If you need to inherit public functions from another class, you only need to change the way outer is constructed.

var outer = baseClass(ctorParams);

If you need to use functions from another class by composition, you have several ways of doing it

  • construct them on the stack in the constructor
  • construct them as a data member of "inner"
  • construct them as inner, i.e.var inner=composition(ctorParams);
When you realize a function is reusable from your private section, you can simply move the function to public section of a base class for your "inner" and construct your "inner" with the base class just introduced. The rest of your code doesn't change.

Similarly, when you realize a public function can be reused, you can migrate to a base class for your "outer".

You may also have "protected" section if you like.

var based = {};
based.data = sharedSecret;
based.protectedFunction = function(params)
{
//function body
};

var outer = baseClass(based);


and in your base class

function baseClass(based)
{

var inner = {};
inner.shared = based;
var outer = {};

outer.publicFunction = function()
{
// function body
inner.shared.protectedFunction(params); // call "protected" function
};
};


The part I like the most about this approach is you don't see "this" anywhere. In the early time of my JavaScript coding, figuring out what "this" is was the most painful part for me. Now you don't have to worry about it anymore.


Monday, October 15, 2012

How can Agile kill a project

I'll continue to talk about software engineering from previous post (How can Waterfall kill a project). People can learn from the failure of many waterfall projects in the wrong way. Let's see how agile can go wrong in the same situation.
A company has come up with this great idea to build car, boat, and truck (assuming they never exist before) to get to the emerging market. Being an innovative company, they really want to push the technology boundary.
Learning from the failure of the waterfall process, they decided to adopt agile methodology and build cars first without worrying about boats and trucks. With this simplified requirement, the project went smoothly. They delivered cars to the market on time within budget. Everyone is happy.

When the market starts to heat up and competition pour their products into the same market, manufacturing only cars is no longer profitable. So the company decide to continue their adventure by building the boats. With the success in delivering cars, one would reasonably think building boats should be much easier until one developer points out that they require about the same amount of the budget for building cars. Product manager asks why and the developer provides this answer: "Developing the engine is the part that consumed majority of the resource. The engine built for the cars is embedded into the car frame and cannot be reused for the boats since the car frame is not suitable for building the boats. To develop the boats, we'd have to develop the engine again." The company did their calculation. If they invest in building the boats with about the same cost, by the time their boats hit the market competition may also deliver similar thing. Since manufacturing cars is no longer profitable, manufacturing boats with the same cost may suffer the same fate. So the decision is made not to build boats less to say trucks. Since manufacturing cars is no longer profitable, the manufacturing line is closed. Everyone is sad.

In retrospect, what could have been done differently? Why didn't they design an engine that works for cars, boats, and trucks? Wait a minute! Are we going back to the failed waterfall process?

I'd learn the lesson differently. Agile tends to give developers tunnel vision and leads to under-engineering of the product. Taking away the design step in the engineering process only makes this situation worse. Agile or not, you still should follow the same design/engineering principle: separation of concerns. Had the engine been designed in such a way that it is not concerned about how it is mounted (in this case embedded in the car frame), it could have been reused for the boats even though it may not be capable of driving a truck yet.

How can Waterfall kill a project?

Waterfall engineering process has been used in many industries with great success. We've used it to build airplanes, railways, buildings, and many other things. But in software industry "Agile" has become THE software engineering process everyone is following. What is wrong with waterfall?

I often use this simple story to explain my understanding of it.

 A company has come up with this great idea to build car, boat, and truck (assuming they never exist before) to get to the emerging market. Being an innovative company, they really want to push the technology boundary.

The project is following a waterfall model. They started by doing a good design of the things they want to build. During this process, they realize that they need a piece named "engine" that can be reusable for all three products. They start to design this perfect engine. Nobody has ever built something like this before. Invent an "engine" is hard and invent an "engine" that can fit into all three products is harder than that. A lot of resource is put into the effort. The resource required is so immense that the project runs out of budget before they can deliver a single car.

In retrospect, what could have been done differently? Why didn't they design an engine that only works for cars and deliver some cars before worrying about boats and trucks? One would reasonably believe designing a simplified "engine" just for cars should not have consumed so much resource. In terms of software engineering, the lesson learnt is waterfall tends to over-engineer a product or a part of it. The effort put into this over-engineering effort may cause delay for accessing the market.

Some people learn the lesson differently. They think the "design" piece in waterfall is to be blamed for the failure. Why do you spend so much resource on generating these useless design documents before writing code? Coding is design after all!

 I believe lessons learnt this way is part of the reason that "agile" is born. In the name of "reducing documentation overhead", the design step is removed from the engineering process so that no design documents are generated. But I don't agree with the way this lesson is learnt. Can Agile kill a project? That'll be my next post.

Thursday, February 24, 2011

Functor Pattern: Separating Layout from Behaviour in SilverLight Control Design

SilverLight controls may get complicated when it has to handle mouse events and keyboard events. When too many events need to be handled the size of the code behind may grow to a big size. In this post, I'll show a design structure that separates the event handling logic from the layout of the Control. The purpose is to avoid code behind file growing into unmanagable size.

This simple example assumes you need a control to handle the following requirements:
1. There is a part in the control where user's left click must turn the control into "selected" mode
2. There is a part in the control where user's left click must invoke a sorting operation according to the sorting parameter bound to the control
3. When user right click on any part of the control, a context menu should be shown

The "normal" way of handling mouse events is to either override the mouse event functions in the UserControl class, or add mouse handler functions in the control. Putting user gesture event handling code in the code behind file is the main force that drives its size to grow. To avoid this problem, we'll use a set of mouse handler classes to handle these events instead.



Here is the layout of the control.



Other classes.



Here is the start up wiring.



Here is how we handle the first requirement.


Now sorting.


This is how context menu is created.


As shown above, the main control doesn't have any mouse event handling logic but some supporting functions. There is no if-else logic to resolve where the mouse left click is and what it means, sorting or selecting. There is no reason for the size of the code behind file to grow out of control when more complicated mouse handling is required. Each mouse handler class does one thing and one thing only.

Further more, the main control class has a much better chance to be reused since different usages may choose what mouse handlers to attach or not attach to give it different behaviour, e.g. not allow sorting. People may also override MouseHandler functions in derived MouseHandlers to provide different behaviour while no change is needed to the main control class. By attaching and detaching MouseHandlers at runtime, the main controls behaviour can also be changed at runtime.

The same approach can be applied to keyboard handling as well.

In C# implementation you don't really need the MouseHost class. Just add and extension to the UserControl class.

public static class MouseExtension
{
public static AttachMouseHandler(this UserControl userControl, IMouseHandler mouseHandler)
{
userControl.MouseEnter += mouseHandler.OnMouseEnter;
...
}
public static DetachMouseHandler(this UserControl userControl, IMouseHandler mouseHandler)
{
userControl.MouseEnter -= mouseHandler.OnMouseEnter;
...
}

}

Sunday, October 3, 2010

Replace MVVM with AbstractView pattern

With MVVM pattern, sometimes, people run into the problem that the VM class soon explodes to the size of a few thousand lines of code. To solve this problem, I'll present a new pattern I call Abstract View.

The reason for VM class to explode in size is that it is carrying too much responsibility.
1. Provide binding properties
2. Provide binding commands
3. Provide implementaion for commands and other functions required by the View and its code behind.

For a complicated view, it won't take long for the view model class to reach unmanagable size. To solve this problem we need to delegate some of the functions to other classes. But the View class still requires a binding target. Instead of using a View Model class, I'll call this simplified view model class Abstract View in that it defines the possible properties and operations a concrete view that is bound to it may carry out hence define the view in an abstract manner.

Here is a static view of this new pattern.



By using more than one CommandProviders, you can separate concerns horizontally and by allowing CommandProviders to user other delegates, you can separate concerns vertically. Mediators become facades for various delegated function units each providing service of a subject area.

This is a sequence diagram for starting up.



A typical user edit action sequence.



A typical user command handling.



Close view.



In this pattern, most of the functionality is moved out of the "ViewModel" class therefore it's size will be under control. When the Mediator size is grown out of control, it may optionlly use other delegates to redistribute its functionality.

Wednesday, July 14, 2010

Understand Model-View-Controller (MVC)

Among all the design patterns, MVC is probably the most cited. It had become such a legendary that part of it has been mystified. Wiki page for it even claims it "is a software architecture, currently considered an architectural pattern".

The following are some excerpts from the earliest description of MVC.

"In the MVC paradigm the user input, the modeling of the external world, and the visual feedback to the user are explicitly separated and handled by three types of object, each specialized for its task. The view manages the graphical and/or textual output to the portion of the bitmapped display that is allocated to its application. The controller interprets the mouse and keyboard inputs from the user, commanding the model and/or the view to change as appropriate. Finally, the model manages the behavior and data of the application domain, responds to requests for information about its state (usually from the view), and responds to instructions to change state (usually from the controller). " [SB]

"Unlike the model, which may be loosely connected to multiple MVC triads, Each view is associated with a unique controller and vice versa. Instance variables in each maintain this tight coupling. " [SB]

"Models are those components of the system application that actually do the work (simulation of the application domain). They are kept quite distinct from views, which display aspects of the models. Controllers are used to send messages to the model, and provide the interface between the model with its associated views and the interactive user interface devices (e.g., keyboard, mouse). Each view may be thought of as being closely associated with a controller, each having exactly one model, but a model may have many view/controller pairs." [KP]

"To maximize data encapsulation and thus code reusability, views and controllers need to know about their model explicitly, but models should not know about their views and controllers." [KP]

"Every instance of a view has exactly one model and exactly one controller. The model is normally set explicitly. Because view and controller classes are often designed in consort, a view's controller is often simply initialized to an instance of the corresponding controller class." [KP]

If we put all these together, the following class diagram is a good description of this pattern in its static view.



The following sequence diagrams show this pattern in action.
Initialization:


User Interaction Handling example:


Release:


The main benefit of this pattern is "This three-way division of an application entails separating (1) the parts that represent the model of the underlying application domain from (2) the way the model is presented to the user and from (3) the way the user interacts with it." [KP]

This pattern was designed in the environment of SmallTalk-80. Clearly, it had achieved what it is intended for.

However, when apply it to different development environment, adaption is often necessary. The biggest difference in most popular development environments versus SmallTalk is probably the fact that most of the them have GUI support frameworks, MFC/C#/VB/Java on Windows platform and Java/Cocoa on Mac. Most of these GUI support frameworks provides a set of "Controls" with built-in keyboard and/or mouse handling capability. It seems the "Controller" is now mostly merged into "Views" in these frameworks. The spirit of MVC is the separation of concerns. Despite the changes in development environment, the need for separation of concerns has never been altered. "Controller" in the form of its classic definition may not be required anymore but there is still the need for a class to control the transition of user device (keyborad and mouse) control, to interpret user guestures into business actions, to control model persistence. In this sense, MVC is still a valuable pattern for any GUI design project.

[SB] Steve Burbeck, "How to use Model-View-Controller (MVC)", 1987

[KP] Glenn E. Krasner and Stephen T. Pope "A Description of the Model-View-Controller User Interface Paradigm", 1988

Thursday, April 15, 2010

Agile and Design Evoluation

Agile is right in at least one way in that no matter how hard you try, your requirements do change over time. There are good reasons for requirements to change. Market condition changes, technology advances, and product scope changes are all good reasons for it.

Let's admit that requirements are changing and you are always shooting at a moving target. To handle requirements effectively, you need a good strategy to evolve your design to deal with the changes.

In agile practice, developers are often given a limited view of the product to start their implementation. The best design they can come up with will unavoidably only cover the variations within that scope. You may blame the initial designers for lack of abstraction in their design to handle future variations. But in reality there is nothing wrong with it since they are limited by the knowledge about future requirements. It is hard, if ever possible, to determine how abstract their design should be to cover possible future variations without knowing what will come up. A more practical solution is to evolve your design from concrete to more abstract.

One way of handling requirement changes is to constantly revisit your conceptual models in your design in every iteration of your agile process. Before you add more if-else statements to your functions, more enum values to your switch statements, or boolean flags to your data structures, you should really think about your conceptual models and your state machines. Are they still valid given the new requirements?

If-else statements are really behaviour changes. Theoretically, behaviour changes are supposed to be handled by polymorphism in good OO design. The need for more if-else statements is a good indication that you need more derivations to handle behaviour differences. More of your base classes should become abstract (pure virtual in C++). If-else statements may bandage your obsolete design but will lead to more grief for the future.

More enum values or boolean flags are really amendments to your existing state machines, exponentially unfortunately. As state space of your state machines expands so dramatically, it is unlikely your last state diagram will hold. Revisit these state diagrams to see how it should really be under the new requirements.

Given a set of requirements, come up with a good OO design is already a challenging task in most cases. Shooting a moving target only makes it harder. Without a good strategy to deal with requirement changes, it is unlikely your software project will end up with great success, at least from software design's perspective.