Sunday, November 3, 2013

Is variable named "i" fine ?

At many places we see variable named "i","j","c" etc scattered every where around the code; in all the methods. The obvious question that rises is "is such short variable name (e.g., i,j,k,c,k etc) fine?". Many people says that the variable name should ALWAYS be long and descriptive but you sense of "code smell" says that it is fine. But some people says that it is fine. This might actually confuse you.

Here is the  rule to answer answer the above question:


Uncle Bob's Rule:
For variable:
           Longer the scope, the longer the name should be.
For function/methods and classes:
           Longer the scope, shorter the name should be.



Lets understand it with an example of variable name:

The code below with variable named "i" is fine because the scope of "i" is very short :
    private static int getSumOfCharsInString(String name)
    {
        int sum = 0;
        for (int i = 0; i < name.length(); i++)
        {
            sum += getIntValueForChar(name.charAt(i));
        }
        return sum;
    }


But here the following code with variable named "c" is NOT FINE because the scope of the variable named "c" is very long(Its up to you to decide how much length to be considered as "long"). The variable named "c" should be refactored to something meaningful and long.
int main()
{
    char c;
    void getfile();
    void getfname(char []);
    char temp[MAX];  
    getfile();
    getfname(temp);
    if ( source != '\0' && html != '\0' )
    {
        fprintf( html, "%s", "" );
        fclose( html );
        fclose( source );
        printf("\nThe file is now created");
    }
.
.
.
    do
    {
       c = getc( source );
       if ( c == EOF )
       {
          break;
       }
       else if ( c == '<' )
       {
          fprintf( html, "%s", "<" );
       }
       else if ( c == '>' )
      {
          fprintf( html, "%s", ">" );
      }
      else if ( c == '&' )
      {
         fprintf( html, "%s", "&" );
      }
      else
      {
         fprintf( html, "%c", c );
      }
  }
  while ( c != EOF );
.
. 
}

Thursday, September 12, 2013

Learn Your IDE

Folks, Learn your IDE.

You just can't start using the IDE thinking that "yahh... !! I know how to type", "I know how to run"; but that is not enough. You need to consciously learn your IDE.

The modern IDE is very powerful. They charge you such high amount of money because of the facility they provide. It has a lot of power which can save you a lot of time.

It's worth spending some days learning the shortcuts of your favorite IDE. Whether it is ItelliJ Idea or Visual Studio; do spend time learning it.

They have features like "Incoming tab", "Refatoring" etc which will make you confident.

Thursday, August 15, 2013

Clojure Learning

If you are learning Clojure from books and if you feel that they are not a good place to start with then here is a resource that might help you in getting started and give you over all idea.

http://blackstag.com/blog.posting?id=5

Although will not teach every detail but should be a good place to start with rather than the books that are available.

Saturday, July 13, 2013

Problem 42


The nth term of the sequence of triangle numbers is given by, tn = ½n(n+1); so the first ten triangle numbers are:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
By converting each letter in a word to a number corresponding to its alphabetical position and adding these values we form a word value. For example, the word value for SKY is 19 + 11 + 25 = 55 = t10. If the word value is a triangle number then we shall call the word a triangle word.
Using words.txt (right click and 'Save Link/Target As...'), a 16K text file containing nearly two-thousand common English words, how many are triangle words?

/**
 *
 @author Umang 
 * started at : 13/07/2013 09:01 PM 
 * completed at : 9:26 PM
 */
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.StringTokenizer;

public class Problem42
{

    private static HashMap<Integer, Long> triangleValues;
    private static int countedTill = 0;

    static
    {
        triangleValues = new HashMap<>();
    }

    private static long calcuateTriangleNumber(int no)
    {
        return no * (no + 12;
    }

    public static long getTriangleNumber(int no)
    {
        long triangleNumber = 0;
        if (no >= countedTill)
        {
            
            int i = 0;
            for (i = countedTill; i <= no; i++)
            {
                triangleNumber = calcuateTriangleNumber(no);
                triangleValues.put(no, triangleNumber);
            }
            countedTill = i;
        }
        else
        {
            triangleNumber = triangleValues.get(no);
        }
        return triangleNumber;
    }

    private static boolean isTriangleNumber(long no)
    {
        boolean isTriangleNumber = false;
        long triangleNumber = 0;
        int i = 0;
        do
        {
            triangleNumber = getTriangleNumber(i);
            if (triangleNumber == no)
            {
                isTriangleNumber = true;
                break;
            }
            i++;
        }
        while (no >= triangleNumber);
        return isTriangleNumber;
    }

    private static String getFileContent()
    {
        StringBuilder content = new StringBuilder("");

        File aFile = new File("D:/words.txt");
        Scanner aScanner = null;
        try
        {
            aScanner = new Scanner(aFile);
        }
        catch (FileNotFoundException ex)
        {
            System.out.println("File could not be readed");
            ex.printStackTrace();
            System.exit(0);
        }
        while (aScanner.hasNextLine())
        {
            content = content.append(aScanner.nextLine());
        }
        return content.toString();
    }

    private static LinkedList<String> getWordList()
    {
        LinkedList<String> result = new LinkedList<>();

        String content = getFileContent();
        StringTokenizer lineTokenizer = new StringTokenizer(content, ",\"");
        while (lineTokenizer.hasMoreTokens())
        {
            result.add(lineTokenizer.nextToken());
        }
        return result;
    }

    private static int getCharNo(char character)
    {
        int charNo = 0;
        char capitalized = Character.toUpperCase(character);
        charNo = ((intcapitalized64;
        return charNo;
    }

    private static long getValueFromString(String str)
    {
        long count = 0;
        for (int i = 0; i < str.length(); i++)
        {
            count += getCharNo(str.charAt(i));
        }

        return count;
    }

    public static void main(String args[])
    {
        int triangleNumberCount = 0;
        LinkedList<String> wordList = getWordList();
        for (String word : wordList)
        {
            if (isTriangleNumber(getValueFromString(word)))
            {
                triangleNumberCount++;
            }
        }
        System.out.println("There are " + triangleNumberCount + " triangle numbers");
    }
}

Friday, April 5, 2013

making life easier for PHP developers - auto uploading files

Here is a post that explain the solution to the problem I had faced a little while ago.

I was working on a PHP project. Git was my version control system. And FTP was the primary protocol for uploading the PHP files from development server(on local machine) to the deployment server(remote machine).

I felt that uploading the files manually to the server was tedious task (although I could find out what files have changed between given commits etc). This uploading was taking quite a lot of time of ours so I thought of getting some automated solution to this problem. I "googled" a little about it and here is the solution:

We were already using the Git. We used a ready made - open source solution developed by other developer.

The tool that made our life easier was git-ftp. It is hosted on https://github.com/ezyang/git-ftp. You can freely obtain it and use it for your purpose. In our case we used it for uploading PHP files but it might work for other suitable tasks also.

Here is are the steps to install "git-ftp" on windows machine:
Step 1: Install Python 
Obtain Python 2.7.3 from the official Python website. Start the installer. It should have screens as shown below.









Step 2: Put python executable in path

After the last screen appears click on finish button. No you will have Python installed on your machine.
But executing it from the console would give you an error because it is not in path. In order to put python executable in your path you need to do it as shown in the images below:


Copy the path where python is installed.


Right click on My Computer and then click on properties.

Then click on Advanced System Settings.

Then click on "environment variables" button.

Then search for "Path" in "System Variables" and append the ";" and the path in which Python is installed.

Then click on ok ok ok ...

By now you will have python set and you will be able to execute it from command line.

Step 3 : Install Setup Tools
Installation of setup tools is required. Set up tool's windows installer can be obtained from https://pypi.python.org/pypi/setuptools .
Install it as shown in the screenshots.






By now you will have set up tools installed.

Step 4: Install GitPython
You need to install GitPython then. It is required because the Python script will be accessing the git repository. GitPython can be obtained from http://gitorious.org/git-python.
you need to install it from command line by invoking the setup.py with install parameter.
eg:




Now we have got GitPython installed we can move on to our project directory.

Step 1 to step 4 will be one time only. Step 5 to will be repetitive for project.

Step 5: obtain and put the python script in your project directory.
We can obtain the python script from https://github.com/ezyang/git-ftp.
Put the git-ftp.py script in the project directory.

Step 6: Create a file containing FTP credentials.
We need to create a file containing the credentials in the .git directory. If you don't create the file then it will ask you for details every time the script runs. If we put the file with credentials in .git directory then the python script will automatically read the details and upload that to the server.

The name of file must be "ftpdata" (without quotes). File name should be "ftpdata" without any extensions like txt etc.
If you are having multiple branches and each branch is deployed to different server the file might look like(name in square bracket is name of branch):

Put this file in ".git" directory.



Step 7: After doing this upload the "git-rev.txt" file to the root directory of the server. Put the sha1 of the last commit in the file.
The upload script knows which files needs to uploaded from this file. This file is changed by the upload script each time it executes.


Now you can execute the git-ftp.py scrip. It will upload all the files that are committed in git to appropriate server (depending on your branch).

Some users might also want to create a ".bat" file that looks like:

Some users might also want to create a ".bat" file with "git gc" command (make sure that git is in your path to do this).



Now you have everything set up. Just run the script and everything works !! :D
Every time you make the commit, you can just run the script and all the files committed will be uploaded to the server. No overwrites by mistake!


Suggestions:
1. If upload does not work then execute "git gc" command on your project repository.
2. If upload fails then make sure that you and all others are in sync with each other through git.
3. Read the error message from script if something goes wrong.
4. The installation is easier on linux machines.
5. See the read-me of project at https://github.com/ezyang/git-ftp.

Limitation: 
Some other protocols are not supported by the tool which we are using.

Friday, March 1, 2013

Debugging !

Lets not talk about debugging first and talk about 2 other things:

 1: 
Have you imagined what might be happening when an engineer decides to create a new plane with a new design ? (We assume that one can do so ;) ) He thinks about the purpose, safety, design etc. He might think about  aerodynamics, propulsion, fuselage, mass, structure etc. The design process would also include the use of Computational Fluid Dynamics (CFD). In short the process before building some physical component takes a long time. Even after they have built some physical model, they need to test it in wind tunnel to be sure about it. Similar amount of effort is given the construction/engineering of other components.
If you want to test your physical component in real, then you might have to rent/buy a wind tunnel at relatively higher price then of an average computer. Also if some other electronic/mechanical component fails at run-time, finding the actual problem and fixing it is a difficult task.

 2: 
Imagine you have a Mercedes-Benz W116. The car was excellent product when it was built and you are not maintaining it properly. It continues to cause problem frequently because you are not maintaining it properly. You have also learned to fix the problems with car as and when they arise.It might take some time some day, but you some how fix it.
On one fine day your mom asks you to drop her to a church and in-between on the road the car causes problem. But, as you have become familiar with problem solving you would be able to solve it and car start again and you would be able to successfully drop your mom to church. In this situation your mom should not be happy thinking that "owww, my son could correct that!"; instead she should think like "oh! how could this happen ? car stopped ?!! ".

Now that we have laid out enough foundations that needs clear out the point that i want to show; we can discuss the main topic of this post. That is "Debugging".

We, the software craftsman/developers write software/applications that people use in day to day life. But we are not able to develop them on the first run. Sometimes things would go wrong with the software that we are developing. And when things go wrong; the bug comes out, we must find the cause and fix it.

To fix the problem we must look "into" the software while it is running. Now compare it with the aircraft system. Imagine what hey might be doing when an issue rises with the engine of aircraft ?

Surely the software craftsmen/developers have more power when compared with aeronautics people. They can not see what is happening in the engine while it is running at 10,000 RPMs while the software developers can pause the execution of software on their machines without any significant amount of investment. Developers do not have to got to wind tunnels in order to see something in action.

A software developer/craftsman can put a break-point and then do the magical things like step in, step out, runt to cursor etc. Recently I have met some some people for whom the debugger does not exists. They do not know about the remote debugger available. They do not know how to configure xDebug with PHP. They do not know that GDB exists. Some people think that they are using exotic languages like Ruby and Python and debugger is not there for their language. But; by thinking wrong directions they are missing something really important.

Sometimes people forget that debuggers exists and we can see what is happening in your code in real time line by line, variable by variable. We can see all the variables, objects etc by putting a watch on them !! If we are doing web development then we can see all the parameters in the variables in the real-time inside our IDE(although non visual-command based debuggers exists,  but i prefer  debugging visually)(eg we can see $_GET, $_POST etc in php while debugging in Netbeans).

We can see what is happening in our software step by step, line by line; Now imagine what people in aeronautics and other industries would had done if they had such power at their fingertips at such low cost ? We are underestimating the power that we have with debugger and in-turn underestimating ourselves.

But make sure that it does not become a daily and routine activity. Debugging is not central activity of development process. It should not be daily activity as it was with our virtual/imaginary car.

Your boss should also think same as your mom. Debugging should not become routine as it was with car. Neither some one should be proud of it!

Also the boss should not be proud of a person with good debugging skills!

We should work in such way that odd situations like these do not rise!

Write such code that no problems get raised and in-turn you do not have to debug. But when the problem gets raised be equipped with debugger of your language and solve the bug well. Do not forget to take advantage of good debugging tool, but make sure that you are not making it continuous activity.

Sunday, February 10, 2013

Difference between layered architecture and tiered architechture

When discussing layering, there's often some confusion over the terms layer and tier. Often the two are used as synonyms, but most people see tier as implementing a physical layer.

- "Patterns of enterprise application architecture" By Martin Fowler. Page No: 19. ISBN: 978-81-317-9402-9

While discussing with a collage mate I found out that the confusion about the "tiered" architecture of the application and the "layered" architecture of the application really needs to be cleared up. So this post is here to make the things clearer. Those already know what the difference is can ignore this post; this post is intended for those who do not understand it well. (However this will not teach you how you should design your layers/tiers; instead it shows the difference)

But before going into the question of layer and tier we need to ask a fundamental question: why tier and layer are required ?
And the answer could be to reduce complexity, increase re-usability, or for standardization etc.

In both the terminologies, they divide the code in different parts like "presentation","domain logic","data source logic"(or even more parts sometimes).

In really simple application one might have one method(i use the term method to indicate a group of callable statement, it might be a function, subroutine etc in context of any other c like language). One might be to get data, second could be for domain logic and third could be for view. But as the application becomes more and more complex you will be required to separate them through some mechanism. In the next iteration of development you might move those methods to different classes. And if the application is even more complex, you might put those classes in different package,or namespace or any other mechanism to separate them.

If it is a java application you might create separate classes, put them in one jar and use them in the upper level abstractions. If you are working on a .Net project you might create a dll in same way. If you are working in some other language there would be some mechanism to achieve the same thing.

Typically one would create a package(or dll or jar) for data source logic (that is for accessing data from the data source - typically it would abstract the data access to higher level layers. the higher level layers should not know from where the data is coming from. you might be able to change the data source from file to relational database and from that to non-relational database without higher level knowing about the change. You get such advantages when designing an application with layering in mind.). You would use the data source logic in the domain logic. And then further use the domain logic in the presentation. What you would be doing is much like shown in the Fig-1 below:

Fig-1
What we are doing here in Fig-1 is logical separation of code. Although you would have programmed the code in different method, different class, different package, different project; at its heart all the code would be running on the same machine. When the code is running on the same machine as shown in the above fig it is known as "layering". 

But sometimes because of some issues the layering of the application does not help, you need to make pieces of you application and put them on different machines to solve those issues. When you put those pieces (e.g., presentation, data source logic and domain logic etc or even more pieces) on different machines, they would communicate with each other over the network in order to complete some activity.

The communication could happen by simply accessing a restful URL, or calling a web-service or calling a WCF service of RMI or any other technology. Typically when you say the architecture is "tiered", the 'pieces' would typically be on different physical(or logical) machine.

Fig - 2
Whenever we use the term tiered the communication between pieces happens through network. While development you might put all the pieces on a single machine, but typically the term tiered means that they can be deployed ever the machine anywhere.

When ever you apply tired architecture, it greatly affects the over all performance when compared with the layered architecture because the communication between two physical machines is always slower than the communication between two pieces on the same machine.

Although one tier itself can have many layers in it.

To conclude we can say that even if you have used methods to separate view, domain model etc; you can call it a layered architecture. Layered architecture is on same machine. Tiered architecture is always on different machine (although you can put them on same machine if you wish).


There are many points that affect the decision abut layered architecture and tiered architecture so a trainee or journey man should never take decision directly. He/She should always consult the "master craftsman" before taking any decision.

Friday, January 18, 2013

Problem 28


//package javaapplication1;

/**
Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is formed as follows:

21 22 23 24 25
20  7  8  9 10
19  6  1  2 11
18  5  4  3 12
17 16 15 14 13

It can be verified that the sum of the numbers on the diagonals is 101.

What is the sum of the numbers on the diagonals in a 1001 by 1001 spiral formed in the same way?
*/

/**
 * this is what one can write with poor tools
 */

/**
 * Timing: 1:01 am to 1:54 am
 @author umang
 */
public class Problem28 {

    /**
     @param args the command line arguments
     */
    public static void main(String[] args) {
        int max = 1001;
        int arr[][] new int[max][max];
        int x = max / 2;
        int y = max / 2;
        int count = 0;
        int increment = 2;

        // initialize first square
        arr[x][y= count++;
        arr[x][y++= count++;
        arr[x++][y= count++;
        arr[x][y--= count++;
        arr[x][y--= count++;
        arr[x--][y= count++;
        arr[x--][y= count++;
        arr[x][y++= count++;
        //arr[x][y++] = count++;
        //arr[x][y++] = count++;
        //   y++;
        //System.out.println(x + " " + y + " " + count + " " + increment);
        while (x != && y != 1) {
            increment++;
            //  System.out.println("start " + x + " " + y + " " + count + " " + increment);
            for (int i = 0; i < increment; i++) {
                arr[x][y++= count++;
                //y++;
            }
            y--;
            x++;

            //System.out.println(x + " " + y + " " + count + " " + increment);
            for (int i = 0; i < increment; i++) {

                arr[x++][y= count++;
                //    System.out.println(x + " " + y + " " + count + " " + increment);
            }
            x--;
            y--;
            increment++;
            //System.out.println(x + " " + y + " " + count + " " + increment);
            for (int i = 0; i < increment; i++) {
                arr[x][y--= count++;
            }
            x--;
            y++;
            ///System.out.println(x + " " + y + " " + count + " " + increment);
            for (int i = 0; i < increment; i++) {
                arr[x--][y= count++;
            }

            x++;
            y++;
            //System.out.println("end" + x + " " + y + " " + count + " " + increment);
        }
        for (int i = 0; i < increment; i++) {
            arr[x][y++= count++;
        }
     /*   for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.printf("%2d ", arr[i][j]);
            }
            System.out.println("");
        }*/
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            //   System.out.println(arr[i][i] + " ");
            sum += arr[i][i];
        }

        int row = 0;
        for (int i = arr.length - 1; i >= && row < arr.length; i--, row++) {
            if (row != i) {
                sum += arr[row][i];
            }
        }
        System.out.println("sum is " + sum);
    }
}

Sunday, January 13, 2013

Refactoring code-1 - breaking complex if...else to simple structure

In order to show how I broke down nested if...else structure into smaller, more manageable pieces, I have to show it with an example. The example might be technology specific but person with a little experience will be able to figure out what I did-and how the very same thing could be done with his/her programming language.

I was working on a web based application on PHP and CodeIgniter framework. Application was simple in the beginning. Admin could do certain things. Obviously the user should be allowed only after logging in through the admin login. If the login was successful the we set certain things in the session. All the admin pages should be accessible only after logging in to the system. I thought of some solution that was like "Aspect Oriented Programming" (or AOP) that i was used to do with Java(Spring AOP / AspjecctJ). The very same thing could be achieved in the CodeIgniter framework through what they call hooks.

We would be seeing the same hook that my team mate wrote and later I refactored for better maintainability (we will take it as an example in order to understand the technique).

We created a controller "login_check" and a method named "checkLogin". The checkLogin function from "login_check" class was invoked before any controller(the entry needed to be made in the hooks.php in application/config in php-CodeIgniter project). By doing this we saved ourselves from writing if/else on all the pages in the admin part.

(This method is executed before any controller - controller method execution)

The class looked something like shown in the snippet-1:
It is a normal CodeIgniter controller with a constructor. The line 11 (in code snippet-1) checks if the class(controller in this case) is 'authenticate' (the method check_login is executed before doing anything in the actual controller.) If the class is the authenticate (the one that renders the form) then we should not be redirecting him/her to the login (through appropriate route) (otherwise it would send us in a redirection loop that does not end). If the user has requested login page or anything that has anything to do with authenticate then we are not redirecting the user(eg if the button click on login page invokes a method from authenticate controller indirectly).


On the line 12 in the snippet-1 we get the CodeIgniter instance that is required in order to access the session.

And on the line 13 we check if the session is set and if not set then we redirect the visitor the the login page.

All the pages for admin were with URI "admin/".

Things we good enough so far. Then we started implementing the Student part. Now we were required to write the pages for Student as well. Student also could see pages only after he/she is authenticated. The student can not see pages for admin that is the student can not see the pages for which he/she is not authorized.

Now we had to write the code that would check if the user is logged in or not also we also had to make sure that the user is accessing the intended pages only(that is admin is accessing pages of admin and the student is accessing the pages of student only). If the student tried to see the pages of admin then he was to be redirected to his home page (that is URI "/student").

Also if the user had requested any URI starting with student/* as was not authenticated then we had redirect the user to user's login page of student. Same way if the user tries to access anything with URI matching :admin/*" then we had to redirect the user to admin's login page.

The code looked as shown in Snippet-2.



To understand what is happening here we need to first know the method _get_root_directory_requested() (that I have written in snippet-2). This method returns the top level directory name from the requested URI (if if user has requested '/admin/students/edit/1' then the method would return 'admin'). That method helped in keeping the "checkLogin" function smaller.

The line 24 in snippet-2 does the same thing discussed earlier.
Then on the line 26 we get the requested directory(eg admin,student).
On line 27 we check if the user is logged in as admin and he has requested for /. In this case we redirect him to admin/dashboard.
On line 42 we redirect the user to student/dashboard if the student has logged in and trying to access / URI.

On line 38 we redirect the user to appropriate login page depending on the top level directory he has requested. And on the 45 onward we redirect the student to student/dashboard and admin to admin/dashboard if he/she is trying to access un-authorized pages.

This also worked fine so far. After this we were asked to write the Super-Admin feature. In super admin we had to create a user who could manage the administrators. This introduced the third User-Type. We had to check the very same things discussed above(that is user should be given access to pages for which he/she is authenticated and authorized).

Because of the third user being added I though of adding some more if...else to make the things work. But if I had done it, it would make the function even bigger[1] and difficult to read and in-turn difficult to maintain. Also the function will not be visible on the screen once on normal displays.

So i applied some refactoring to it. After doing it the code looked as it is shown in scnippet-3.



The method '_get_root_directory_requested' stays as it was in the previous snippet and does the same thing.
checkLogin is the method which would be invoked and it would invoke other methods in order to perform its task.

We would now see what changes I did in order to make things easier to read and maintain.

The line 36 checks if the controller before which the method is invoked is not one of authentication controller. We have replaced a complex condition with a method call. We placed the complex condition inside a method call that is easier to read as well as easier to maintain[1].  The complex condition with two 'and' was encapsulated inside a method named '_is_authentication_controller'. This can also be seen as an abstraction we built. It prevents us from getting to the actual detail of names of the controllers. We can just use the method. We are not required to go into the details. In future if new controller for authentication is added (in case of new user being added) then we would be easily able to make the changes.

At line 39 we call a method that checks for login in the session. It returns true if user is logged in and false if the user is not logged in. On the line 40 we get the user type that is logged in. On the line 41 we call method "_authorize_for_url_with" with argument of user type that we have got from previous line.

The method "_authorize_for_url_with" redirects the user to appropriate path if the user is not authorized for the URI and the method does nothing if user is trying to access intended pages.

In the Else part at line 45 we call the method "_redirect_to_appropriate_login" which redirects the user to the login page. The user is redirected to the URI "student/" if the user has requested for "/" URI. This method uses the "Direct Access Tables[2]"(the array- or the data-structure that holds the details is constructed in the constructor at line 20)(although the data-structure would vary according to the language but the concept would remain the same. You could also put that in a method if you wish.). This method relies on the values in the associative array. The key is top directory requested or user-type(ed admin,student,etc) and the value is the page to which the user needs to be redirected in order to login.

Here in this case the length of method was reduced be introducing some methods. In this structure if a new user type is added then we just need to add its entry in the constructor and add its controller class name to method "_is_authentication_controller". No other changes needs to be done on other part. This makes the class more flexible and ready to adopt new user types.

Although I have made some assumption while writing which you can read in the comments written at the top of the class in snippet-3.

This is the first time i have tried writing something. I have started noticing some problems already; but however I am publishing this post. ;) I hope it is entertaining.

References:
[1] Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin (ISBN: 0132350882 )
[2] Code Complete: A Practical Handbook of Software Construction, Second Edition By Steve McConnell (ISBN: 0735619670 )