17 October, 2011

My First Monad ... Simple ... Yet Immensely Useful

Motivation

Ever dreamed about putting all your exception handling or logging stuff at a single place? Imagine the maintenance problems it can solve. How to do it? Use a monad.

Note: Same code is shown in both images and text. Output is shown only in image.

What is a Monad?

A monad is a wrapper. What is a wrapper? A wrapper is a class that has an object of another class. What is the difference between an ordinary class and a monad? A monad has one special function, a higher-order function. What is a higher-order function? A higher-order function is a function that can take in argument a function. What do the higher-order function do with this input-function? It apply it on the object that the monad is containing. Here is the code:


public class LoggerMonad
{
    public T Value
    {
        get;
        private set;
    }

    public LoggerMonad(T value)
    {
        Value = value;
    }

    public LoggerMonad Bind(Func func)
    {
        Console.WriteLine(func.Method.Name + " is called at " + DateTime.Now.ToString());
        return func(Value).ToLoggerMonad();
    }

    public void Bind(Action action)
    {
        Console.WriteLine(action.Method.Name + " is called at " + DateTime.Now.ToString());
        action(Value);
    }

}

public static class LoggerMonadExtensionMethods
{
    public static LoggerMonad ToLoggerMonad(this T value)
    {
         return new LoggerMonad(value);
    }
}


Explanation

Lets go through it very slowly. You have a class called LoggerMonad. This class is your monad. It can wrap itself around any object, means it can contain an object of any type whatsoever. This class has a constructor which do the initialization stuff. Like all good constructors it do only one thing, initialize fields. There is one higher-order function too, called Bind which is overloaded twice. We will talk about it later. First a quick overview of generics.

Generics

We are using c# generics here. LoggerMonad is a generic class. A generic class is any class that contains a generic field or a generic method. A generic field is a field whose type is not specified inside the class, its specified elsewhere in code. Its still a static type means at the time of compilation the type would be known. Its not a dynamic type means the type is not unclear until runtime. C# is static-typed language which means that it do not allow dynamic types, uptil version 3.5. A generic method is a method that takes in argument or return a variable of generic type.

How To Use This Class?

int i = 1;
LoggerMonad monad = new LoggerMonad(i);

Further Explanation

You not have to use the monad this way. The above code is just a demonstration of how generics work. LoggerMonad can contain a field of any type, what type? the type that is specified when the constructor is called. You can use any type, means you are not limited to integer or numeric types. Note that we do not need to specify type above when calling constructor. Its because c# compiler is intelligent enough to infer the type of "i" variable itself.

Higher-Order Functions

Now, lets talk about the higher-order function. Its overloaded and its generic. The first one, which takes in input a "func", is to be called when you want to return something from your input-function. The second one, which takes in input an "action", is to be called when you don't want to return anything from your input-function. Note that the main point here is what you want to return from the input-function, not the Bind function. You can say that the Bind function is a wrapper around your input-function, so its like a method-level wrapping.

The Input-Function

The input-function itself can return a thing of any type. We have only one Bind method for it, so we have to return a general type of thing. Its because we don't want to have a separate Bind function for all types in c#, including your custom types. How do we do it? Remember that our LoggerMonad can contain an object of any type, so we simply return a LoggerMonad. That solves the problem. Note that our LoggerMonad has a public get around its field T, therefore the client-code can easily access the underlying value that is returned by the input-function.

Extension Methods

The last part of the listing is an extension method. Since its an extension method so you can put it in any static class of your code. I personally prefer to make a separate class for each type and put the related extension methods there. Note that the argument contains a "this", which means that the method ToLoggerMonad is an extension method. The method simply wraps the input value in a new LoggerMonad object and return that object.


public class Program
{
    public static void Main(string[] args)
    {
        string sText = "North Pole is 20,000 km away from the South Pole at any direction except top.";
        int iBeginAt = 0;
        int iEndAt = 10;
        string sCountry = "Pakistan";
        List list = new List;
        int iNumber = 105;
        TestSubstring(sText, iBeginAt, iEndAt);
        TestCount(sText);
        TestStartsWith(sText, sCountry);
        TestAddInList(list, iNumber);

        Console.Read();
    }

    public static void TestSubstring(string sText, int iBeginAt, int iEndAt)
    {
        Func funcSubstring = s => s.Substring(iBeginAt, iEndAt);

        string sSubstring = sText.Substring(iBeginAt, iEndAt);
        Console.WriteLine("sSubstring = " + sSubstring);

        string sSubstring_Monad = sText.ToLoggerMonad().Bind(funcSubstring).Value;
        Console.WriteLine("sSubstring_Monad = " + sSubstring_Monad);
    }

    public static void TestCount(string sText)
    {
        Func funcCount = s => s.Count();

        int iCount = sText.Count();
        Console.WriteLine("iCount = " + iCount);

        int iCount_Monad = sText.ToLoggerMonad().Bind(funcCount).Value;
        Console.WriteLine("iCount_Monad = " + iCount_Monad);
    }
}


Explanation of Client-Code

The above is our client-code. Client-code is always the code that uses the library. Here, our library is all the code in the first image, that is, the LoggerMonad class and the extension method.

The Four Methods In Client-Code

Our client-code calls four methods. Inside each of these methods, a call is made to an instance method directly, that is, without using the monad, and then the same call is made using the monad. You only have to see one of these methods to see the comparison. So, if I have an object called "sText", whatever its type is, and i have a method called "Substring" inside that object, then I can simply call it this way: "sText.Substring(argument1, argument2);" where argument1 and argument2 are any two objects of integer type. Its a simple call but it has following maintenance problems:


  1. Most of the time the objects we are using are of library classes whose code we cannot modify. So we cannot put anything inside the methods we are calling.


  2. If we want to do something, such as logging, before we call a method, then wherever in our code we have called that method we have to write the logging code there. A copy-paste can do that, but later on, if we want to change the logging related code then we have to go through all of these places and change code there. Even that could be done. What can never be done is change that code after you have ship your library. Its a scenario where you have made a library of your own, deployed that library on computers of your customers, then make a client-code that uses that library, so far so good. But later on if you want to change your client-code without touching your library code then you cannot do that in anyway.


  3. You may simply forget to insert the logging code at some places or make some mistake so that the logging code is called differently at different places.
    Its better to keep all the logging code at one place so you only have to change one class if ever a change requirement comes. Note that whatever is said above about logging goes also for exception handling or whatever stuff you want to do before or after execution of your methods.


The First Client-Code Method In Detail
Lets go through first of the methods in our client code, the TestSubstring method. Compare the call at line no. 65 with the call at line no. 68. The first call need not be explained because its the way you actually do your callings now, the new thing is the second way of calling. What we have done is that we have first converted our object "sText" into a LoggerMonad by calling the extension method. Once its a LoggerMonad it can access the Bind method. The overloaded Bind method we are interested here is the one that returns a value. Take a quick look at line no. 21 (image 1) to see the signature of the method.

The first thing to note is that it takes a function in argument, not an action. The difference in two is that a function always returns a value while an action never. The function, that is, the input-function is a generic function. Its last type "R" is the return type. This gives our flexibility to return any type from our function. We are not limited to returning the same type of the wrapped-field inside the monad. This is actually different than the classic use of monads in functional languages such as haskell, and its a technique I invented. It do not deviate us from the essence of monads, because its an enhancement, not a replacement.

We do have to tell the return type. That is what "" is doing at line no. 68. Though we are returning a string from a string object "sText", we are not limited to return the same type. This is demonstrated in the other 3 functions called from the Main method. Lets go back to line no. 21. Take another look at the signature and this type focus on the return type. Although the monad itself is of type "" (see line no. 8 above), the return type is "". Means we apply the Bind function on any LoggerMonad of type T and return another LoggerMonad of any type R. That is why we have put no restriction on the type the LoggerMonad contains. The LoggerMonad can contain a field of any type.

The Bind method applies the function it takes in input on the field the class is containing. This is what the line "func(value)" is doing. We are taking in input a function and applying that function on the "value". Now, here is where it becomes tricky, and this is the thing which is stinging in your object-oriented brain since you have seen the code in the first image. What is going on?


A Look Back At Procedural Programming

Lets go back to the simple world of procedural programming, where there are no objects. Since you are an object-oriented programming so you are supposed to be already an expert in procedural programming, therefore you should understand the basic concept I am going to refer now. In the procedural programming term, when we say "apply a function on a variable v" then we mean that we pass the variable v as an input argument to the function. That is not what we mean here, in the higher-order function sense. When we say that Bind applies the input-function to the field "value" we do not mean "apply" in the same sense as in procedural programming.

Applying A Function

What do we mean then? We mean this: "call the function of the object". The arguments are not mentioned here, in this code. The code "func(value)" of line no. 24 is same as the code "value.func()". Let it sink in your brain. We are not passing value to the func, we are applying func on value, we are calling func of value. We are calling a method called func which is inside value. We are calling value to call its method func. What parameters do func takes then? See line no. 68.

sText.ToLoggerMonad().Bind(funcSubstring).Value;

The Bind Function

Bind is taking in input a function called funcSubstring and then internally calling it on the object the monad is containing. Lets not talk about the return value now. Take a look at what funcSubstring is, line no. 63, listed below too:

Func funcSubstring = s =>
s.Substring(iBeginAt, iEndAt);

We have defined a function here. The function itself takes two arguments "iBeginAt" and "iEndAt". Once inside the Bind the "s" is replaced by the wrapped-field Value. What finally happens is this "sText.Substring(iBeginAt, iEndAt)".
It looks like an unnecessarily long way of calling a method. Instead of doing this:

sText.Substring(iBeginAt, iEndAt)

we have to do this:

Func funcSubstring = s => s.Substring(iBeginAt, iEndAt);
sText.ToLoggerMonad().Bind(funcSubstring).Value;


Why Use Such A Long Code?


It means instead of one simple line we uses two lines. Why? We do not really have to give a name to the input-function. We can very well do this:

sText.ToLoggerMonad().Bind(s => s.Substring(iBeginAt, iEndAt));

We gave a name to the input-function because we are doing logging here and we want to know the name of the function that is called. See output below:



Drawbacks of Monads

At the end, our calling do gets longer, instead of "sText.Substring(iBeginAt, iEndAt)" we have to do "sText.ToLoggerMonad().Bind(funcSubstring).Value". Still we have two advantages: all of our binding logic gets at single place, we can effectively put code inside library functions.

Where Is The Logging Code Anyways?

See line no. 23. Here we are logging at screen. You can put your code here to log in a database or file or whatever.

The Second Overload of Bind Method

We have only one thing left to talk about now. Its the second overload of the Bind method, the one that takes an "action" argument. Its to be called when the input-function do not returns anything. We have to use overload here because c# don't allow "R" to be void in the first overload. See line no. 27. Note that the Action is of type "T", we not have any return type so there is no "R" there. The Bind itself is of return type void. In the client-code we need not worry about which Bind to call because the c# compiler can handle it itself. See line no. 101 below.

/* code continues in class Program */
    public static void TestCount(string sText)
    {
        Func funcCount = s => s.Count();

        int iCount = sText.Count();
        Console.WriteLine("iCount = " + iCount);

        int iCount_Monad = sText.ToLoggerMonad().Bind(funcCount).Value;
        Console.WriteLine("iCount_Monad = " + iCount_Monad);
    }

    public static void TestStartsWith(string sText, string sCountry)
    {
         Func funcStartsWith = s => s.StartsWith(sCountry);

         bool isStartsWith = sText.StartsWith(sCountry);
         Console.WriteLine("isStartsWith = " + isStartsWith);

         bool isStartsWith_Monad = sCountry.ToLoggerMonad().Bind(funcsStartsWith).Value;
         Console.WriteLine("isStartsWith_Monad = " + isStartsWith_Monad);
    }

    public static void TestAddInList(List list, int iNumber)
    {
         Action> actionAddInList = l => l.Add(iNumber);

         list.Add(70);         
         Console.WriteLine(list[0].ToString());

         list.ToLoggerMonad().Bind(actionAddInList);
         Console.WriteLine(list[0].ToString() + " " + list[1].ToString());
    }


We pass on the action actionAddToList to the Bind method, which overload of Bind is not our concern. Ofcourse this could be simplified as following:

list.ToLoggerMonad().Bind(l => l.Add(iNumber));

You can enclose your calling of function or action in the overloads of Bind inside try catch and put your exception-handling logic there if you want to have an ExceptionHandlerMonad instead of a logger monad. You can have both by putting both of these logics in the Bind method.

Anonymouse Function


Lets take a closer look at "s => s.Substring(iBeginAt, iEndAt)". This is body of function. This function has no name, so its an anonymous function. This is the input-function we are supplying to the Bind function. Remember that Bind is a higher-order function so it can take in input a function. It can also return a function but we do not need that functionality in any monad so we not use it.

What do the above line means? It means that this function requires an argument called "s". We need not worry about the type of "s", that is specified and handled somewhere else in our code. If there are multiple arguments then we have to separate them by commas and use a bracket, such as "(s, m)" instead of "s". In a monad we apply the input-function on the wrapped-value as explained earlier, see line no. 24 and 30 for a quick reference. It means we only have to supply one argument, the wrapped-value. In all monads, the input-function, the function that is anonymous, always takes only one argument.

What do this input-function returns? It returns whatever the last line in it returns. Here it returns whatever "s.Substring(...)" returns. The return type could be anything, but whatever it is, it can be converted to a LoggerMonad, therefore our Bind method has to have only one return type, "LoggerMonad".

The above is not actually true. The input-function may not return anything at all, means it can have a "void" return type. In that case we use the other overload of Bind explained earlier.


The Entire Code


I haven't shown code in sequence above, for better focus. Following is the complete code with output:





12 October, 2011

Dehydration

Definition


Its the art of shortening a word on basis of sound.

Description


There are rules for shortening as explained in detail further down in this article, for example, silents are ignored, from consecutive-duplicate consonants only one is taken, inner vowels are removed etc.

Reading them involves some guess work, therefore they are appropriate in short texts only, where due to smaller context guessing is more accurate.

Building Blocks of English Language


Consonants have what we can call "hard sounds", such as "s", "n", "p" etc. Vowels have what we can call "soft sounds", such as "i", "e" "o" etc. None of the consonants or vowels can make a word on its own in english language, they need each other. Consonants make the bases, vowels connect them("soon", "peon", "sin", "sit", "net" etc) or appear as suffix or prefix ("eat", "ant", "emergent" etc).

There are five letters in english language which are always a vowel, and there is "y" which is sometimes vowel and sometimes consonant. For example in "yet", "yellow", "yup" etc "y" is a consonant, and in "party", "symphony", "sybase", "myopia" etc "y" is a vowel.

Other than consonants and vowels there is a third building block of english language, its the "Combination of letters that combiney produce a single sound". Examples are:


  • "tion" as in "station", "mention", "tradition" etc.

  • "sh" as in "sharp", "shave", bushes" etc.



Rules



  1. Remove all vowels that appear in between the consonants in a word.

  2. Keep all those vowels that appear at beginning of word and have sound, such as "art" remains "art", "application" becomes "applctn", "ottoman" becomes "ottmn" etc.

  3. Keep all those vowels that appear at end of word and has a sound, such as "see" remains "see", "happily" becomes "Hply", "attache" becomes "atche" etc. Remove those that don't have sound, such as "sine" becomes "sn", "advocate" becomes "advct" etc.

  4. If there are two consonants or two vowels together that have same sound then keep only one of them, such as "suppress" becomes "sprs", "cinderella" becomes "cndrla" etc.

  5. If a consonant or vowel is silent then remove it.

  6. For combination-of-words that combinely produce a single sound, consider them as made up of letters that can make up that sound, not the actual letters, then apply rules to them. Such as "station" is considered as "stashn" and becomes "stshn", "sharp" becomes "shrp", "tradition" is considered as "tradishn" and becomes "trdshn" etc.



Implementations



advocate advct
advocates advcts
add ad
address adrs (keep one consonant)
bench bnch
button btn
cancel cncl
clear clr
court crt
computerized cmptrzd
code cd
comments cmnts
date dt
data dt
diary dry
download dnld
directory drctry
edit edt
empty empty
error err
file fl
father fthr
general gnrl
hidden hdn
index indx
inner inr
insert insrt
inserted insrtd
info inf
information infrmtn
judgement jdgmnt
last lst
list lst
message msg
mother mthr
notification ntfctn
notify ntfy
name nm
nic nc (nic is an abbrevation)
num nm
number nmbr
old old
order ordr
person prsn
party prty (keeping the ending "y")
release rls
row rw
radio rd
random rndm
stream strm
success scs
specific spcfc
signing sgng
table tbl
text txt
type tp
upload upld
update updt
value vl
year yr
partitioon prtshn
protectorate prtctrt
chair chr


Relation to Programming


I am developing this convention for later use in naming of variables. It would be used in naming local variables, means variables declared inside a function, not the parameter-variables.

Similarities


You have already seen something similar before. In microsoft world, a convention very similar is already in use since decades. Take a look:

button btn
textbox txt
directory dir
information info
calendar cdr
clear clr
screen scr

Although this convention is similary to my dehydration convention, its not the same. Some differences are:


  1. The shortform is sometimes restricted to three characters. In dehydration there is no such limit.

  2. Sometimes the second word is totally absent from the shortform. For example "txt" for textbox. In dehydration it would be "txtbx".


Why this convention



  1. Due to no limit on number of characters the frequency of name-collision is low. Name-collision is when the same shortform refers to multiple longforms.

  2. Its easy to make the sound of the word in mind, that helps in reading.

10 October, 2011

System Complexity

What is a system?

A system is a group of parts that act together to accomplish a common goal.

Examples:



  1. Company made up of employees


  2. Sentence made up of words


  3. Team made up of players


  4. Cloth made up of threads


  5. Organ made up of Cells


Note: A part can be a system itself.


Need of system


Specialization

Some parts can do somethings that other parts cannot.

Example:

It needs so much special skills and experience that a person cannot be a chartered accountant and a nuero surgeon at the same time in one life time. A hospital which needs both, has to hire two different people.


Simultaneity

In some situations, multiple tasks need to be done at the same time to achieve the desired result.
Example:

In an office there has to be a guard that has to keep an eye on the door, exactly at the same time a peon has to make tea, exactly at the same time a clerk has to fill a voucher.


Readiness

Some works need to be done constantly without any break.

Example

The borders of a country need to be guarded constantly without a minute’s break. A part cannot work continuously because after sometime of working the part burns out and needs to be repaired. There has to be shifts.


Advantages of System


Risk Reduction

If a part is in a system, then the chances of damage to that part is greatly reduced, because in case of a problem the other parts can come for rescue.

Example:

A person living in a village has greater chances of surviving an illness or injury or a famine, than a person living alone in a jungle.


Resiliency

Resiliency to the whole group, if one part fails another part can continue providing same services until the first part is repaired or replaced.

Example:

If a farmer has many different types of crops sown simultaneously on different acres, then in case of an infestation some of the crops are likely to be saved. If the farmer has sown only one type of crop, then it would be an all or nothing situation.


Quality


Specialization brings quality in output. Taking advantage of reduction in responsibilities, a part can invest more time in education, and can also narrow down the area of education to know a lot about a very little set of things

Example:

A large corporation is capable of hiring specialized, highly educated personnel with very limited area of responsibility. A small company cannot afford that and have to have mediocre level people where every person wear multiple hats.




Economy


Taking advantage of reduction in responsibilities, a part can choose to do what its best in. Also, since number of duties is decreased, time formerly spent in context-switching, setting-up and moving to new workplace is reduced.

Example:

In an economy where trading is safe and frequent, different regions can afford to grow only those crops that their lands are better in, and rely on other regions to provide other crops they need through trade. A self-sufficient village on the other hand, has to grow all it needs and have to sufferent in quality and quantity as a result.


Power

A group of parts working together has very high chance of defeating an individual part working alone. It is simple power-in-number thing. Also the parts can surround the enemy part and attack all at once instead of a linear one-by-one approach.

Example:

The surrounding thing is the essence of German army technique to win over all Europe except UK in a matter of months. The trick was to always encounter enemy forces in small parts, so though the German army was small in number overall, yet in every battle individually it was in majority. Note that there is no advantage in having more resources if all of those resources cannot be used at once when needed.


Disadvantages of System


Complexity


Complexity is number of connections between parts in a system. If no part of a system has any connection to any other part, then the complexity of the system is exactly zero. It not matter how many parts are there in the system.


The problem with connections is, as number of connections grow, the number of paths also grow.

Defining Paths
A path is a flow of execution.

Example:

The vegetable that reaches my table every day has the following path:

Farm -> Farm Market -> Transport Vehicle -> City Whole Sale Market -> Local Vegetable Shop.


When the complexity grows, the path becomes long and multiple paths come into existence where there was only one part formerly. Let us suppose the farmer now instead of waiting for annual flood, choose to buy artificial fertilizers:

Mine -> Fertilizer Factory -> Transport Vehicle -> Fertilizer Whole Sale Market -> Village Fertilizer Shop -> Farm -> Farm Market -> Transport Vehicle -> City Whole Sale Market -> Local Vegetable Shop

So far, there is only one part though the length of part has increased. The longer the path becomes, more at the ways to short-circuit it to make smaller paths.

Mine -> Fertilizer Factory -> Transport Vehicle -> Fertilizer Whole Sale Market -> Village Fertilizer Shop -> Farm -> Farm Market -> Transport Vehicle -> City Whole Sale Market


Note that in above, some people choose to buy vegetable directly from the wholesale market, therefore a short circuit. The other path still exists where people still buy from local vegetable shop instead of going to the wholesale market. We have two paths now instead of one. It can become more complicated.

Mine -> Farm -> Farm Market -> Transport Vehicle -> City Whole Sale Market -> Local Vegetable Shop


In the above, some of the farmers choose to mine the minerals on their own (or recycle excretions), while other farmers are still buying fertilizers from the market. Therefore a new path is created, and the two existing ones still exists.


Of course some of the farmers may choose to buy directly from wholesale market, in which case we get 4 paths. There are many combinations.


As number of connections between parts of a system grow, the number of paths also grow. Same thing could happen in multiple ways utilizing different flows of execution. The number of words that are needed to explain the system grows. The number of test cases grows. It becomes harder and harder to capture all paths.


To tackle complexity, there has to be a manager. An overriding executer that can initiate, rollback, pause, resume, stop any flow. Flow is when the path is being utilized. Flow is like current, path is like wire.


How to Handle Complexity in a Computer Program


In a computer program there are methods that perform actions. If any method can call any other method then paths increase and so do the complexity. We have to divide methods in two types:



  1. Methods that can call other methods


  2. Methods that cannot call other methods.

The First Type of Methods


These are the paths. When you want to change a path, change the body of this method.

Example:

Suppose the business logic is this:



  1. User input data in a form.


  2. Form is sent to code-behind.


  3. Code-behind validate user input.


  4. Code-behind insert data in database.


  5. Success message is displayed.

What we need to do is make five methods of the second class and call them one by one from the first type of method. The function that validates data cannot for example insert it in database. The function that validates data just return a true/false to the first type of method.


Why use this scheme where methods are divided in two types? Because we can easily change the path, and because we can find out very easily that what is going on.


Let us suppose there is a change in business logic. Now, we have to redirect user to another web-page instead of displaying success message on the same page. How to do it? Very simple, make a new method that redirect user. In the first type of method, replace the call to the method that display success message to the call to the method that redirects


How to Document This?


Use a Sequence Diagram. Sequence Diagram shows the flow. Don’t get yourself confused with the concept of “message passing” and “objects” yet. Just try to make a Sequence Diagram without any object-oriented stuff!


We have to make a separate Sequence Diagram for every functionality. Some of the functionalities are:


  • Customer can add a new order.

  • Customer can view orders.

  • Customer can change an order.

  • Customer can delete an order.

  • A report of orders last year that exceed Rs. 100,000.

  • Audit trailing.

  • Searching in orders.


In an event-driven programming, user can initiate almost any functionality. We have to put the first type of method in the event-handler.


What Architecture This Is Called?


The above scheme is very close to the MVC architecture. In MVC, controller is the logic that controls the workflow i.e. the path. Model and View are not allowed to call each other directly. All interaction between Model and View has to go through the controller. Of course there are variations in MVC which do allow Model and View to call each other directly but that kill the purpose.

Do not think too much about the concept of objects yet. Do not consider Model, View and Controller as objects. Consider them as functions.

Lets give this scheme a name. Lets call it "Director-Actor Procedural Design". Director is the method that calls other methods. Actor is the method that do not call another method but do the work itself.

Director do not do any work. It delegates the work to actors and orchestrate the workings of the actors. It decides whether and when to call who. It also handle exceptions, because it knows what to do, that is, what other method to call in case of an exception. It also allocate and deallocate resources. Actor cannot allocate the resources itself, because the same resource may need to be used by another actor first, for example an actor initializes an object with values and then the new actor uses that object. If the second actor allocate its own resource then it would be a new object which we do not want. Actor cannot deallocate resource because in case of an exception control goes back to the director and then only the director can deallocate the resource.

There are no director-directors, means there is no super director that calls a director. The directors are called asnchronougly by event handlers.

The directors are the effective event handlers, means almost the entire work that need to be done in an event handler is done by a director. There is no logic in the eventhandler except passing the values of related controls to the director, means there is no if-else or loop in eventhandlers. The only work of eventhandler is to call the right director and pass on the values of related controls.

Director is control-type-agnostic, means director don't have to know what controls are displayed to user, be it a group of radio buttons or a drop down list. User can select an option anyway, by checking a radio button, by selecting an option from drop down list or by clicking a button, whatever. Its the work of the form and the event handler in that form to extract the values from the controls and send it to the appropriate director. Therefore, if user interface changes, means your company decide to use a web page instead of a web form for example, you do not need to change the director.

Director is also database-provider-agnostic. It not matter to director whether you are using Sql Server, Oracle, MS Access or even flat file database. The inner workings of database is handled by the stored procedures layer and the calling of those stored procedures is handled by the model layer.


Similarities With MVC


The above do very much look like the MVC pattern. Director is very much same as the Controller in the MVC. The differences are the Controller need not be an object, it could be a method, and, only the directors can call only the actors.


Similarities With Object-Oriented-Programming


The central theme of object-oriented-programming is not to limit who calls who, the central theme of object-oriented programming is what data a function act on, this is called encapsulation. All the other stuff in object-oriented programming is built around this basic concept. Inheritance, and polymorphism are not in their full glow without encapsulation.

The above scheme is based on limiting who calls who. This is independent of what data the functions are acting on. There can even be no data the function is acting on, for example the function is creating a file, or displaying something on screen etc, i.e. there are no variables. The function can be pure, means the function only acts on its input data and not change anything in environment. Means the function don’t change anything in file system, database and network. The above scheme works in all such scenarios.



Back To Ways of Reducing Complexity


A little recap


It was decided to have two types of methods. First one, named Directors, can call other methods. The second one, named Actors, cannot call other methods. It was also decided that the first type would manage the workflow.

We can put a prefix to names of both types of methods. For directors the appropriate prefix is “Handle”, for actors the appropriate prefix is “Do”. So a validation method is called “DoValidation”, an insert method is called “DoInsert”, a file writer method is called “DoWriteFile” etc. The handlers are like these: “HandleSubmit”, “HandlePageLoad”, “HandleCancel”, “HandleRefreshGrid”, “HandleDelete” etc.

So for every desired situation, we have a handler. The handler manages resources and executes operations by asking doers to do what they are supposed to do. A desired situation is an anticipated situation, such as “user clicks on submit button”, “user sends invalid input”, “user wants to load the page” etc. In event-driven programming, an anticipated situation is already associated with an event handler therefore that event-handler would have to call a director.

So, you are a software developer, you can make softwares and websites. A colleague of you in your company is an accountant; he can write vouchers and make ledger entries. Another colleague of you in the same company is a marketer, he can run a media campaign or do a user survey. All three of you are there in the company’s office, sitting idle, waiting for manager to tell you when to work and what to work on. The point is, all three of you are operatives, doers, actors, you do things but you don’t decide when to do it, you also don’t decide what to work on. Your manager should tell you what to do, for example decide whether its a new ERP or a new website. Your manager should tell the accountant in what bank’s what account number he must work on. Your manager should tell the marketer which people to act on and when.

You, your accountant friend and your marketer acquaintance are methods. You take inputs. You cannot order each other to work. You don’t decide when to work. You can't handle unexpected situations on your own, such as a power failure, you have to report back to manager and manager then decide what to do.


We have two sets of synonyms in our scheme:



  1. Directors, Handlers, Managers, Executors.


  2. Actors, Doers, Operatives.


Should A Handler Method Call Another Handler Method


Now it is getting complex. We have only one level of hierarchy uptil now. We have handlers that calls doers and that’s it. No handlers are allowed to call other handlers. The question is, what if a workflow is part of a larger workflow.

Many operations in add and edit are same. In both you have to validate user input. In both you have to show a success message if task is successful, otherwise show an error message.

I do not recommend doing this level of software reusing. Handlers shouldn’t call other handlers, period. It is because to implement this, we have to change body of the operatives. We have to put conditions in operatives to do certain things when called by one handler and do some other things when called by some other handler and do common things when called by any handler. The point of separating the two types of methods is that one is independent of another. If both are dependent on each other then there is no advantage of separation. Infact its not a separation.
The biggest problem in softwares is that things are interrelated. One change in one part results in a lot of changes in other parts. We want to minimize impact of changes. There are ways to do this, such as object-oriented-programming where we can change private methods without any effect outside the object. We can also write automatic testing code to be sure that all effects are accounted for. Still, the essence of problem is not tackled. Object-oriented-programming do not reduce who call who very effectively, a private method can call a method in some other object. Automatic testing can give us extra eyes but it not make the garden greener. Some of the situations can be overlooked in testing.

The real solution is to reduce dependencies. What is dependency? Dependency is when behavior of one thing changes when behavior of another thing changes. For example: virus in my computer effects my productivity because I depend on my computer to do my work, but virus in a doctor’s computer do not effect his productivity because he do not use computer to do his work.

Dependencies in software is the cost of code reuse. When we reuse a method, we call it from more than one places. In most situations, the body of that method has to react differently depending on who is calling it.

The solution is to make one thing independent of another. The other thing would still be dependent on the first one and that is ok, that is code reuse. We have to make two-way dependency one-way. How? Make the actors small. This can only be accomplished if the Single Responsibility Principle is followed at the method level, means one method do exactly one thing.

Example:

Insert and Update:

You have an “insert” operation and an “update” operation. You have to do user-input validation in both cases. The validation operation is same in both cases except that in case of update you have to validate the id of the record. The id of the rercord can be in form of value of an item in drop down list or it can be in a hidden field, whatever. You have to make sure that the Id of record is there and that its numeric and that its non-negative, before you start the update operation.

You should make a method that validates all fields except the id field. Then you should make a separate method that validates only the id field. Now, in the insert workflow, you call only the first method and in update method you call both the methods. As a bonus, you get a ready-made validation function for the delete workflow. Note that in the delete workflow you only have to validate the id.

Create File If Not Exist Then Write In It:

In some situation you have to write in a file if it exists, and if it not exist then create the file first then write in it. These are two separate operations: Create File if not exist, Write in file. There should be two methods.

Allow User to Type Numeric Keys With Or Without Dot:

In a web page this is client-side scripting. You catch the key user pressed, if its not numeric you cancel the event. There can be two situations, one in which user can type an integer only, such as Id of a record, count of something etc, that is, things which cannot be decimal. The other situation is when user can input a decimal, such as price of an item. You want to validate the key in both cases and decide whether to cancel the event.

You should make two methods, one valids numeric keys only without dots, the other validate dot keys only. Then in situation where you need to validate both write something like this:


if(! (DoIsValidNum(txtData.value) DoIsValidDot(txtData.value)))
evt.Cancel = true;
When you validate only numerically then:


if(!DoIsValidNum(txtData.value))


evt.Cancel = true;



Summary




  • Things better exist in a system, than alone. Its good for them (risk-reduction) and for the system(resiliency).


  • There are situations where systems are unavoidable, such as: Specialization, Simultaneity and Readiness.


  • Effectiveness of a system is directly proportional to number of interactions between its parts. Unfortunately, complexity of the system is also proportional to that.


  • There is a way to reduce complexity while keeping effectiveness at the same level. It is to allow only one kind of workers to use other workers.


  • In a computer program:



    • We should have only one type of methods, the Directors, which could call other methods, the Actors, that do things.


    • A Director shouldn't be allowed to call another Director.


    • An Actor should perform only one work.


    • A Director shouldn't do any work, except orchestrating the working of the Actors.


    • Director should decide when and what Actors to call, in what order, what to pass to them and what to do with the returned value.


    • Exception handling should be done by Directors only.