Everything you want to know about Mob Programming

What is Mob Programming?
“All the brilliant people working on the same thing, at the same time, in the same space, on the same computer.” – Woody Zuill
“Mob Programming is continuous integration for ideas.” – Joshua Kerievsky
There are many ways to successfully mob. In general, there is one computer, a keyboard and mouse, one or more monitors, a whiteboard, one Driver and one or more Navigators sharing a work environment like the one below:

Ideal Mob Size The whole team, although teams of 3-6 people is ideal. Beyond 6 people, a Mob may have difficulties keeping everyone engaged. You can counter this with quicker rotation times.

Driver’s Role – The Driver operates the computer to input/implement ideas made by the Navigator(s).

Navigator(s) Role – Navigators direct the Driver. Usually it works to allow everyone in the Mob to interact directly with the Driver. If that causes too much chaos, have one Navigator give directions to the Driver and the Navigator serves as the voice of the Mob. Newbies to mobbing can ask for help on how to navigate.

Driver Dos & Don’ts

  1. Drivers don’t navigate. If the Driver is the only one who knows what to do, they can relinquish their role as Driver to the next person in the rotation.
  2. Each Driver can share how they prefer to be directed, including asking questions about intent, location and details. Ultimately, navigators must communicate in a way that allows the Driver to understand and take action.
  3. If no one is navigating, the Driver must stop typing.

Navigator(s) Dos & Don’ts

  1. Navigator ideas can only be programming by going through the Driver’s hands.
  2. Navigators must pay attention to the Driver’s skill level. If the Driver needs word-by-word instructions, the Mob must explain in detail what the Driver needs to do. If the Driver is more advanced, Navigators give higher-level instructions, like “commit it” or “move that method to the parent class”. Over-navigating entails too much direction, under-navigating too little.
  3. Don’t sit and watch the Driver work. Everyone learns and contributes in a productive Mob.

Mob Responsibilities

  1. Treat everyone with kindness, consideration, and respect
  2. Plan, discuss, research, and work out ideas on the whiteboard
  3. If a Driver begins to navigate and drive simultaneously, someone else in the Mob can call them out on it.
  4. Keep the Mob going as people join or leave
  5. Stakeholders, Managers, Subject Matter Experts, etc. are welcome to join a Mob, but are not required to drive or navigate.

Leaving/Joining the Mob – It is fine for someone to leave or join the Mob for whatever reason. If they are a Driver, they relinquish that role to the next person in line. The person leaving should tell the team when or if they’ll return so that the team can adjust the rotation schedule.

Switching Drivers – The Driver switch over shouldn’t take more than a few seconds. The teams should determine the best way to accomplish that goal. Switching Drivers is easiest when the Mob shares a single station and settings. If individuals in the Mob have their own preferred tools and settings, consider switching machines using a hardware HDMI switch, or use a system like WebEx or Zoom.

Physical Space – Here are some suggestions for the physical space and equipment setup:

  1. At least one large screen (big enough so that people can easily read code at a distance) is necessary. Some teams use two or more screens. Projectors can work, but are less desirable.
  2. Consider using wireless keyboards and mice to make it easier to switch Drivers.
  3. Mobbing can be noisy. Ideally, the team is in a room with a door that closes or is somewhat apart from other’s work areas. Conference rooms are usually suboptimal. They are designed for people to sit around a table and talk, not to program. You need to face the screen (without turning your head) as you work, and it’s best if participants can sit side by side to facilitate discussions.
  4. You need chairs or couches that are comfortable for longer than an hour.
  5. You need a large whiteboard and plenty of sticky notes.

Mob Timing and Breaks

  1. Use an automated timer (e.g., Dillon Kearns’ Mobster App) to initiate role changes and breaks.
  2. Switch roles every 7 minutes on average (beginners should switch every 2-4 minutes).
  3. The whole Mob should take regularly scheduled breaks. The pomodoro method, a proven method of taking regular breaks to increase efficiency, suggests taking breaks every 48 minutes.

Bias for Action – When discussing how to solve a problem, get out of the abstract as soon as possible.

  1. Do not argue for more than 10 minutes.
  2. If there are 2 ideas, try both, then decide which the Mob likes better.
  3. Keep the Mob moving with this quote from Brian Marick: “An example would be handy right about now”.

The Value of Mobbing – When done well, mobbing helps a team:

  1. Deliver solutions faster by increasing focus, building skills and sharing knowledge.
  2. Produce better quality code because the entire team reviews the code as it is being written.
  3. Feel the pain of tedious tasks. This is good, as it biases you toward fool-proofing and automation.
  4. Cross train it’s members and remove knowledge silos by learning together.
  5. Deliver results faster by reducing the team’s “work in progress” and by eliminating delays from handoffs with the whole team present.

Mobbing Pitfalls – A poorly functioning Mob will produce value slowly. The following are some signs of poor mobbing and what do to if you observe these behaviors:

  1. Excessive discussion or arguing – Run some experiments, then decide which the Mob likes better.
  2. Zoning out – Take a break from the Mob
  3. Ignoring Mob roles/timers – Team members should hold each other accountable
  4. Producing poor designs or not valuing good design – A Mob that lacks people with good design skills won’t magically produce good designs. To improve the design, the Mob should get expert help.
  5. Conflict between team members – In order to be a well-functioning Mob, everyone must be treated with kindness, consideration, and respect.

Don’t Stop the Mob – The Mob can temporarily delegate a member as a researcher, to find solutions to something they cannot easily figure out. Meanwhile, the Mob can work elsewhere in the code. It is important that people feel comfortable enough to ask questions, but if the Mob is moving slowly due to a lot of questions, it is better to set aside some time outside of the Mob for someone to have questions answered. Fast throughput is an important goal.

Invite Experts – If a Mob gets stuck, they may invite an expert to join them to help resolve a problem. Be sure it is an invitation and not a demand (they are not required to drive).

An obsolete reference is one that is kept around but will never be used, preventing the object it refers to from being eligible for garbage collection, thus causing a memory leak.

Manually Setting to NULL
Nulling out a reference to remove obsolete references to an object is good, but one must not overdo it. The best way to eliminate an obsolete reference is to reuse the variable in which it was contained or to let it fall out of scope.

Lets take a Simple Stack implementation as in effective Java

public Object pop() {
    if (size == 0)
        throw new EmptyStackException();
    Object result = elements[--size];
    elements[size] = null; // Eliminate obsolete reference
    return result;
}

In the above code you can see that the stack size is shrinked when ever a pop operation is carried out and is set to null allowing the garbage collector to access the unused space to reclaim

Using WeakHashMap
WeakHashMap is an implementation of the Map interface. WeakHashMap is almost same as HashMap except in case of WeakHashMap, if object is specified as key doesn’t contain any references- it is eligible for garbage collection even though it is associated with WeakHashMap. i.e Garbage Collector dominates over WeakHashMap.

How HashMap Works

// Java program to illustrate 
// Hashmap 
import java.util.*;
class HashMapDemo
{
    public static void main(String args[])throws Exception
    {
        HashMap m = new HashMap();
        Demo d = new Demo();
         
        // puts an entry into HashMap
        m.put(d," Hi "); 
         
        System.out.println(m); 
        d = null;
         
        // garbage collector is called
        System.gc();
         
        //thread sleeps for 4 sec
        Thread.sleep(4000); 
         
        System.out.println(m);
        }
    }
    class Demo
    {
        public String toString()
        {
            return "demo";
        }
         
        // finalize method
        public void finalize()
        {
            System.out.println("Finalize method is called");
        }
}

Output

{demo=Hi}
{demo=Hi}

How WeakHashMap Works

// Java program to illustrate 
// WeakHashmap 
import java.util.*;
class WeakHashMapDemo
{
    public static void main(String args[])throws Exception
    {
        WeakHashMap m = new WeakHashMap();
        Demo d = new Demo();
         
        // puts an entry into WeakHashMap
        m.put(d," Hi "); 
        System.out.println(m);
         
        d = null;
         
        // garbage collector is called
        System.gc(); 
         
        // thread sleeps for 4 sec
        Thread.sleep(4000); .
         
        System.out.println(m);
    }
}
 
class Demo
{
    public String toString()
    {
        return "demo";
    }
     
    // finalize method
    public void finalize()
    {
        System.out.println("finalize method is called");
    }
}

Output

{demo = Hi}
finalize method is called
{ }

There could not be any class which conform to both Same type comparison and Mixed type comparison

Same-Type Comparison
With such an implementation of equals() you can store an Employee(“Hanni Hanuta”) and a Student(“Hanni Hanuta”) into the same HashSet , but retrieval from the collection will not work as expected. You will not find any of these two contained objects when you ask the HashSet whether it contains a Person(“Hanni Hanuta”) , because all three object are unequal to each other.

Mixed-Type Comparison
In a class hierarchy, where Employee and Student are subclasses of a Person , representing roles of a person, it may make sense to compare an Employee to a Student to see whether they are the same Person . With an implementation of equals() that only allows same-type comparison an Employee and a Student would not be comparable.So mixed type comparison allows comparison between parent and child object.With this type of equals() implementation you will have problems storing an Employee(“Hanni Hanuta”) and a Student(“Hanni Hanuta”) in the same HashSet . The HashSet will reject the second add() operation, because the collection already contains an element that compares equal to the new element.

Lets see an example of Mixed-Type comparison

class BaseClass {
    private int field1 = 0;

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof BaseClass) {
            return field1 == ((BaseClass) obj).field1;
        }
        return false;
    }
}

class BadSubClass extends BaseClass {
    private int field2 = 0;

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof BadSubClass) {
            return super.equals(obj) 
                    && field2 == ((BadSubClass) obj).field2;
        }
        return false;
    }
}
BaseClass baseClass = new BaseClass();
BadSubClass subClass = new BadSubClass();

System.out.println(baseClass.equals(subClass)); // prints 'true'
System.out.println(subClass.equals(baseClass)); // prints 'false'

Now the above implementation does not comply to symmetric property of equals
x and y, x.equals(y) should return true if and only if y.equals(x) returns true.

The work around for this is

class BaseClass {
    private int field1 = 0;

    @Override
    public boolean equals(Object obj) {
        if (obj != null && obj.getClass() == getClass()) {
            return field1 == ((BaseClass) obj).field1;
        }
        return false;
    }
}

class GoodSubClass extends BaseClass {
    private int field2 = 0;

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof GoodSubClass) {
            return super.equals(obj) && field2 == ((GoodSubClass) obj).field2;
        }
        return false;
    }
}

Reusing Immutable Object

 
              //Dont Use this
              String strName = new String("Mugil");

              //Use this
              String strName = "Mugil";
         

The Best Example of Immutable Object Reuse is Integer Caching in Java.Lets take the following Example

public class Scratch
{
   public static void main(String[] args)
    {
        Integer a = 1000, b = 1000;  //1
        System.out.println(a == b);

        Integer c = 100, d = 100;  //2
        System.out.println(c == d);
   }
}

Output

false
true

Integer class keeps a cache of Integer instances in the range of -128 to 127, and all autoboxing, literals and uses of Integer.valueOf() will return instances from that cache for the range it covers.

Note that the cache only works if you use auto-boxing or the static method Integer.valueOf(). Calling the constructor will always result in a new instance of integer, even if the value of that instance is in the -128 to 127 range. Integer.valueOf(int). It will return the same Integer object for inputs less than 256.

Reusing Mutable Object

package com.mugil.org.ej;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Item5 
{
	public static void main(String[] args) throws ParseException 
	{
		Person objPerson = new Person();
		objPerson.initializeDates();
		
		
		SimpleDateFormat sdf = new SimpleDateFormat("dd-M-yyyy");
		String endDate = "31-03-2019";
		Date financialYrEndDate = sdf.parse(endDate);
		
		if(financialYrEndDate.after(objPerson.getFinancialYrStartDate()))
		{
			System.out.println("Valid End Date");
		}
	}
}


class Person
{
	private Date financialYrStartDate;	
	
	public void initializeDates() throws ParseException
	{
		SimpleDateFormat sdf = new SimpleDateFormat("dd-M-yyyy");
		String dateInString = "01-04-2018";
		financialYrStartDate = sdf.parse(dateInString);
	}

	public Date getFinancialYrStartDate() {
		return financialYrStartDate;
	}

	public void setFinancialYrStartDate(Date financialYrStartDate) {
		this.financialYrStartDate = financialYrStartDate;
	}	
}

In the above example I know for Sure that the Financial Year End Date should be after Start Date and the Start Date is going to be same for Every Year

package com.mugil.org.ej;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Item5 
{
	public static void main(String[] args) throws ParseException 
	{			
		SimpleDateFormat sdf = new SimpleDateFormat("dd-M-yyyy");
		String endDate = "31-03-2019";
		Date financialYrEndDate = sdf.parse(endDate);
		
		if(financialYrEndDate.after(Person.financialYrStartDate ))
		{
			System.out.println("Valid End Date");
		}
	}
}


class Person
{
	static Date financialYrStartDate;
	
	static
	{	
		SimpleDateFormat sdf = new SimpleDateFormat("dd-M-yyyy");
		String dateInString = "01-04-2018";		
		try {
			financialYrStartDate = sdf.parse(dateInString);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}		
}

Since financialYrStartDate is going to be same it is made as Class Variable which helps to prevent unnecessary Object Creation.

Use Primitives instead of Wrapper Class

public static void main(String[] args) {
    Long sum = 0L; // uses Long, not long
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    System.out.println(sum);
}

It takes 43 seconds to run as Long and long primitive brings it down to 6.8 seconds.

Noninstantiable classes are those which can be invoked using object creation.We prefer classes to be Noninstantiable if you want the class to be Utility class with static methods and variables in it.

public final class Useless {
    private Useless() {}
}

A private constructor is the normal object-oriented solution. However, it would still be possible to instantiate such a class using reflection, like this:

Constructor<Useless> con = Useless.class.getDeclaredConstructor();
con.setAccessible(true); // bypass "private"
Useless object = con.newInstance();

To prevent even reflection from working, throw an exception from the constructor:

public final class Useless {
    private Useless() {
        throw new UnsupportedOperationException();
    }
}

Dont Use absract class for NonInstantiable classes

Attempting to enforce noninstantiability by making a class abstract does not work. The class can be subclassed and the subclass instantiated. Furthermore, it misleads the user into thinking the class was designed for inheritance

While Implementing Singleton the following things should be answered

  1. Reflection
  2. Serialization
  3. Cloning

Objects for Singleton Classes implemented using private Constructor can be invoked by Reflection as below

Item3.java

package com.mugil.org.ej;

import java.lang.reflect.Constructor;

public class Item3 {
	public static void main(String[] args) 
	{
		// reflection concept to get constructor of a Singleton class.  
		Constructor<Singleton> constructor;
		
		try {			
			constructor = Singleton.class.getDeclaredConstructor();
			
			// change the accessibility of constructor for outside a class object creation.
			constructor.setAccessible(true);
			
			// creates object of a class as constructor is accessible now.
			Singleton secondOb = constructor.newInstance();
			System.out.println(secondOb.getName());
			
			// close the accessibility of a constructor.
			constructor.setAccessible(false);
		} catch (Exception e){
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}
}


class Singleton {

    private static Singleton instance = new Singleton();

    /* private constructor */
    private Singleton() {}

    public static Singleton getDefaultInstance() {
        return instance;
    }
    
    public String getName()
    {
    	return "MyName";
    }
}

Output

MyName

Singleton and Serialization
Without readResolve() Method

// Java code to explain effect of 
// Serilization on singleton classes
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
 
class Singleton implements Serializable 
{
    // public instance initialized when loading the class
    public static Singleton instance = new Singleton();
     
    private Singleton() 
    {
        // private constructor
    }
}
 
 
public class GFG 
{
 
    public static void main(String[] args) 
    {
        try
        {
            Singleton instance1 = Singleton.instance;
            ObjectOutput out
                = new ObjectOutputStream(new FileOutputStream("file.text"));
            out.writeObject(instance1);
            out.close();
     
            // deserailize from file to object
            ObjectInput in 
                = new ObjectInputStream(new FileInputStream("file.text"));
             
            Singleton instance2 = (Singleton) in.readObject();
            in.close();
     
            System.out.println("instance1 hashCode:- "
                                                 + instance1.hashCode());
            System.out.println("instance2 hashCode:- "
                                                 + instance2.hashCode());
        } 
         
        catch (Exception e) 
        {
            e.printStackTrace();
        }
    }
}

Output

instance1 hashCode:- 1550089733
instance2 hashCode:- 785945

With readResolve() Method

// Java code to remove the effect of 
// Serialization on singleton classes
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
 
class Singleton implements Serializable 
{
    // public instance initialized when loading the class
    public static Singleton instance = new Singleton();
     
    private Singleton() 
    {
        // private constructor
    }
     
    // implement readResolve method
    protected Object readResolve()
    {
        return instance;
    }
}
 
public class GFG 
{
 
    public static void main(String[] args) 
    {
        try
        {
            Singleton instance1 = Singleton.instance;
            ObjectOutput out 
                = new ObjectOutputStream(new FileOutputStream("file.text"));
            out.writeObject(instance1);
            out.close();
         
            // deserailize from file to object
            ObjectInput in 
                = new ObjectInputStream(new FileInputStream("file.text"));
            Singleton instance2 = (Singleton) in.readObject();
            in.close();
         
            System.out.println("instance1 hashCode:- "
                                           + instance1.hashCode());
            System.out.println("instance2 hashCode:- "
                                           + instance2.hashCode());
        } 
         
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

Output

instance1 hashCode:- 1550089733
instance2 hashCode:- 1550089733

Refer https://codethataint.com/blog/singleton-and-serialization/

// JAVA code to explain cloning 
// issue with singleton
class SuperClass implements Cloneable
{
  int i = 10;
 
  @Override
  protected Object clone() throws CloneNotSupportedException 
  {
    return super.clone();
  }
}
 
// Singleton class
class Singleton extends SuperClass
{
  // public instance initialized when loading the class
  public static Singleton instance = new Singleton();
 
  private Singleton() 
  {
    // private constructor
  }
}
 
public class GFG
{
  public static void main(String[] args) throws CloneNotSupportedException 
  {
    Singleton instance1 = Singleton.instance;
    Singleton instance2 = (Singleton) instance1.clone();
    System.out.println("instance1 hashCode:- "
                           + instance1.hashCode());
    System.out.println("instance2 hashCode:- "
                           + instance2.hashCode()); 
  }
}

Output

Output :- 
instance1 hashCode:- 366712642
instance2 hashCode:- 1829164700

Two different hashCode means there are 2 different objects of singleton class.

To overcome this issue, override clone() method and throw an exception from clone method that is CloneNotSupportedException. Now whenever user will try to create clone of singleton object, it will throw exception and hence our class remains singleton.

// JAVA code to explain overcome 
// cloning issue with singleton
class SuperClass implements Cloneable
{
  int i = 10;
 
  @Override
  protected Object clone() throws CloneNotSupportedException 
  {
    return super.clone();
  }
}
 
// Singleton class
class Singleton extends SuperClass
{
  // public instance initialized when loading the class
  public static Singleton instance = new Singleton();
 
  private Singleton() 
  {
    // private constructor
  }
 
  @Override
  protected Object clone() throws CloneNotSupportedException 
  {
    throw new CloneNotSupportedException();
  }
}
 
public class GFG
{
  public static void main(String[] args) throws CloneNotSupportedException 
  {
    Singleton instance1 = Singleton.instance;
    Singleton instance2 = (Singleton) instance1.clone();
    System.out.println("instance1 hashCode:- "
                         + instance1.hashCode());
    System.out.println("instance2 hashCode:- "
                         + instance2.hashCode()); 
  }
}

Output

Output:-
Exception in thread "main" java.lang.CloneNotSupportedException
	at GFG.Singleton.clone(GFG.java:29)
	at GFG.GFG.main(GFG.java:38)

If you don;t want to throw exception you can also return the same instance from clone method.

// JAVA code to explain overcome 
// cloning issue with singleton
class SuperClass implements Cloneable
{
  int i = 10;
 
  @Override
  protected Object clone() throws CloneNotSupportedException 
  {
    return super.clone();
  }
}
 
// Singleton class
class Singleton extends SuperClass
{
  // public instance initialized when loading the class
  public static Singleton instance = new Singleton();
 
  private Singleton() 
  {
    // private constructor
  }
 
  @Override
  protected Object clone() throws CloneNotSupportedException 
  {
    return instance;
  }
}
 
public class GFG
{
  public static void main(String[] args) throws CloneNotSupportedException 
  {
    Singleton instance1 = Singleton.instance;
    Singleton instance2 = (Singleton) instance1.clone();
    System.out.println("instance1 hashCode:- "
                           + instance1.hashCode());
    System.out.println("instance2 hashCode:- "
                           + instance2.hashCode()); 
  }
}

Output

Output:-
instance1 hashCode:- 366712642
instance2 hashCode:- 366712642

The Best way to implement Singleton is by using ENUM which takes care of Serialization and Other Issues on its own.

Whenever you submit a form to download a file the response sent back is a file. In this case the setter called after the method which does the download has no effect.

 if(form.getDownloadForm != null && form.getDownloadForm.equals("Y"))
 {
   downloadForm(form, request);

   //The Below Setter has No Effect
   form.setDownloadForm("Y");
 }
 class RegisterForm()
 {
   public String downloadForm;

    public void setDownloadForm(String p_download) 
    {
	  this.downloadForm= p_download;
    }
    
    public String getDownloadForm() 
    {
	  return downloadForm;
    }
 } 

The Setter had no effect since the request sent to the downloadForm(form, request); will end up with response of file download and not response which has new values to form set by setter(in our case downloadForm(form, request)) and Page reload.

There are 2 simple fix for this.

Fix 1
One simple fix is to set form hidden property in java script to N after the form get submitted. Note though the form is submitted it is not reloaded with new response since the response sent back is a file.

The Page will be reloaded only when response is sent back to the same URL of browser. Not to the browser as file.

 function downloadWFSetup(pWaterfallId) 
 {	
    $('#downloadForm').val('Y');
    document.WaterfallTriggerForm.submit();

    //This part of code runs even after the form submission since the 
    //response sent is file which does not require page reload
    $('#downloadForm').val('N');			
 }

In our case the page is not going to get reloaded so the java script continues its execution even after form submission setting property of downloadForm to N.

Fix 2
The Other way is to send request in Link with downloadForm=Y. In this case there is no need to to reset the form values as we get the values by request.getParameter() Method.

The Software development can be grouped in to three phase.
1.Meeting Customer Requirement
2.Applying OOAD Principles
3.Design Patterns

We need to create an app which does search of cars in garage.The search is going to take specification of cars as input and display the matching cars.

Phase 1:

Car.java

 public class Car {

	private String serialNumber;
	private String model;
	private String builder;
	private String price;
	private String type;	

	Car(String pserialNumber, String pmodel, String pbuilder, String pprice, String ptype)
	{
		serialNumber=pserialNumber;
		model=pmodel;
		builder=pbuilder;
		price=pprice;
		type=ptype;
	}

	public String getSerialNumber() {
		return serialNumber;
	}
	public void setSerialNumber(String serialNumber) {
		this.serialNumber = serialNumber;
	}
	public String getModel() {
		return model;
	}
	public void setModel(String model) {
		this.model = model;
	}
	public String getBuilder() {
		return builder;
	}
	public void setBuilder(String builder) {
		this.builder = builder;
	}
	public String getPrice() {
		return price;
	}
	public void setPrice(String price) {
		this.price = price;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}

	public enum Type {
		PETROL, DIESEL;

		public String toString() {

			switch (this) {
			case PETROL:
				return "petrol";

			case DIESEL:
				return "diesel";

			}
			return null;
		}
	}

	public enum Builder {
		FORD, HONDA, TOYOTA;

		public String toString() {
			switch (this) {
			case FORD:
				return "ford";

			case HONDA:
				return "honda";

			case TOYOTA:
				return "toyota";

			}

			return null;
		}

	}
}

Garage.java

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Garage {
	private List<Car> carList = new ArrayList<Car>();

	public void addCar(String pserialNumber, String pmodel, String pbuilder, String pprice, String ptype)
	{
		Car objCar = new Car(pserialNumber, pmodel, pbuilder, pprice, ptype);
		carList.add(objCar);
	}

	//The guitar will be returned only when all Search Criteria Match
	public List<Car> searchCar(Car searchCar)
	{
		List<Car> resultCarList = new ArrayList<Car>(); 

		for (Iterator iterator = carList.iterator(); iterator.hasNext();) {
			Car Car = (Car) iterator.next();

			if(!searchCar.getType().equals(Car.getType()))
				continue;

			if(!searchCar.getBuilder().equals(Car.getBuilder()))
				continue;

			resultCarList.add(Car);
		}

		return resultCarList;
	}

	public Car getCar(String SerialNo)
	{
		return null;
	}
}

SearchCar.java

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

public class SearchCar {
	public static void main(String[] args) throws IOException {
		Garage objGarage = new Garage();
		initializeCar(objGarage);

		Car searchCar = new Car("", "A1", Car.Builder.FORD.toString(), "",
				Car.Type.PETROL.toString());
        List<Car> searchResult  =  objGarage.searchCar(searchCar);

        if(searchResult != null)
        {
        	System.out.println("Search Result");

        	System.out.println("-------------------------------");

			for (Iterator iterator = searchResult.iterator(); iterator.hasNext();) {

				Car Car = (Car) iterator.next();

	        	System.out.println("Model : "+ Car.getModel());
	        	System.out.println("Builder : "+ Car.getBuilder());
	        	System.out.println("Type : "+ Car.getType());
	        	System.out.println("-------------------------------");
			}
        }else
        {
        	System.out.println("Sorry! We are unable to Find Car...");
        }
	}

	public static void initializeCar(Garage pobjGarage) {
		//pserialNumber, pmodel, pbuilder, pprice, ptype
		pobjGarage.addCar("", "Mustang", Car.Builder.FORD.toString(), "", Car.Type.PETROL.toString());
		pobjGarage.addCar("", "Corolla", Car.Builder.TOYOTA.toString(), "", Car.Type.DIESEL.toString());
		pobjGarage.addCar("", "Endevadour", Car.Builder.FORD.toString(), "", Car.Type.PETROL.toString());
		pobjGarage.addCar("", "Civic", Car.Builder.HONDA.toString(), "", Car.Type.PETROL.toString());
	}
}

Points to Note:

  1. When specifications contains less number of search criteria like Fuel Type which can be either petrol or diesel use ENUM.By doing this we are avoiding String comparison and other overheads like converting to lowercase, uppercase before comparison
  2. The searchCar method in Garage will return Cars only when all specs matches the car in the garage.

Phase 2
Object Orientation

  1. Objects should do what their name Indicate
  2. Each Object should represent a Single Concept
  3. Unused properties are dead give away

In the above code the Search criteria used can be split separately.
This includes Type, Model and Builder.
The Price and Serial No are not moved to new class since they are unique.

CarSpec.java

public class CarSpec {

	private String model;
	private String builder;
	private String type;

	public CarSpec(String pbuilder, String pmodel,String ptype){
		model=pmodel;
		builder=pbuilder;
		type=ptype;
	}

	public String getModel() {
		return model;
	}
	public void setModel(String model) {
		this.model = model;
	}
	public String getBuilder() {
		return builder;
	}
	public void setBuilder(String builder) {
		this.builder = builder;
	}

	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
}

Now the car class is going to be replaced with CarSpec variable as property.


public class Car {

	private String serialNumber;
	private String price;
	private CarSpec carSpecification;

	Car(String pserialNumber, String pprice, CarSpec pcarSpec)
	{
		serialNumber=pserialNumber;
		price=pprice;
		carSpecification = pcarSpec;
	}

	public String getSerialNumber() {
		return serialNumber;
	}
	public void setSerialNumber(String serialNumber) {
		this.serialNumber = serialNumber;
	}

	public String getPrice() {
		return price;
	}
	public void setPrice(String price) {
		this.price = price;
	}

	public CarSpec getCarSpecification() {
		return carSpecification;
	}

	public void setCarSpecification(CarSpec carSpecification) {
		this.carSpecification = carSpecification;
	}

	public CarSpec getCarSpec(){
		return carSpecification;
	}
}

Since the Specification of the car are moved separately they can be used for both searching and storing car details.

Now the searchCar() method in Garage.java should be allowed to take car Specification as argument instead of whole car object which contains redundant Price and Serial No which are unique.

Garage.java

 import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Garage {
	private List<Car> carList = new ArrayList<Car>();

	public void addCar(String pserialNumber, String pprice, CarSpec pcarSpec)
	{
		Car objCar = new Car(pserialNumber, pprice, pcarSpec);
		carList.add(objCar);
	}

	//The guitar will be returned only when all Search Criteria Match
	public List<Car> searchCar(CarSpec searchCarSpec)
	{
		List<Car> resultCarList = new ArrayList<Car>(); 

		for (Iterator iterator = carList.iterator(); iterator.hasNext();) {
			Car objCar = (Car) iterator.next();

			CarSpec objCarSpec = objCar.getCarSpec();

			if(!objCarSpec.getBuilder().equals(searchCarSpec.getBuilder()))
			 continue;

			if(!objCarSpec.getType().equals(searchCarSpec.getType()))
			  continue;

			resultCarList.add(objCar);
		}

		return resultCarList;
	}
}

Searchcar.java

public class SearchCar {
	public static void main(String[] args) throws IOException {
		Garage objGarage = new Garage();
		initializeCar(objGarage);

		CarSpec searchCar = new CarSpec(Builder.FORD.toString(), "", Type.PETROL.toString());
        List<Car> searchResult  =  objGarage.searchCar(searchCar);

        if(searchResult != null)
        {
        	System.out.println("Search Result");

        	System.out.println("-------------------------------");

			for (Iterator iterator = searchResult.iterator(); iterator.hasNext();) {

				Car objCar = (Car) iterator.next();
				CarSpec objSpec = objCar.getCarSpec();

				System.out.println("Car Name : "+ objCar.getSerialNumber());
				System.out.println("Car Name : "+ objCar.getPrice());
	        	System.out.println("Model : "+ objSpec.getModel());
	        	System.out.println("Builder : "+ objSpec.getBuilder());
	        	System.out.println("Type : "+ objSpec.getType());
	        	System.out.println("-------------------------------");
			}
        }else
        {
        	System.out.println("Sorry! We are unable to Find Car...");
        }
	}

	public static void initializeCar(Garage pobjGarage) {
		//pserialNumber, pmodel, pbuilder, pprice, ptype
		pobjGarage.addCar("101", "Mustang", new CarSpec(Builder.FORD.toString(), "3200", Type.PETROL.toString()));
		pobjGarage.addCar("201", "Corolla", new CarSpec(Builder.TOYOTA.toString(), "3500", Type.DIESEL.toString()));
		pobjGarage.addCar("102", "Endevadour", new CarSpec(Builder.FORD.toString(), "5200", Type.PETROL.toString()));
		pobjGarage.addCar("301", "Civic", new CarSpec(Builder.HONDA.toString(), "3000", Type.PETROL.toString()));
	}
}

Now we are going to move the Search Car Code from Garage.java to CarSpec.java.By doing this we are delegating the job to highly coherent class.
In case any code to be added in future the changes to be done are only confined within this class.We are also going to perform object to object comparison.

Garage.java

.
.
.

public List<Car> searchCar(CarSpec searchCarSpec)
	{
		List<Car> resultCarList = new ArrayList<Car>(); 

		for (Iterator iterator = carList.iterator(); iterator.hasNext();) {
			Car objCar = (Car) iterator.next();

			CarSpec objCarSpec = objCar.getCarSpec();

			if(objCarSpec.findMatchingCar(searchCarSpec))
			 resultCarList.add(objCar);
		}

		return resultCarList;
	}

.
.
.

we are calling findMatchingCar method of CarSpec.java instead of doing the comparison in the same class.

CarSpec.java

.
.
.
public boolean findMatchingCar(CarSpec objCarsPEC)
	{
		if(builder !=  objCarsPEC.getBuilder())
		 return false;

		if(type !=  objCarsPEC.getType())
		 return false;

		return true;
	}
.
.
.

————————————————————————————————

Things Learned

  1. Objects should do what their name indicate and should represent a single concept(high cohesion).
    By Moving the specifications on which the search is made into new class CarSpec.java instead of keeping them in Car.java we have achieved high cohesion.
  2. By Delegating the search functionality to class CarSpec.java we have achieved flexibility. In case there
    is new property say four wheel drive or power window added as search criteria the only class file to be changed is CarSpec.java
  3. High cohesion achieved is also evident from the fact that we can do object to object comparing to match the search criteria. findMatchingCar() Method is doing the same.
  4. If object is used with null value or no value you are using object for more than one job.Simple example is doing a null check on a object property which is not a good business code implementation

An aspect is a software entity implementing a specific non-functional part of the application.

Using AOP has 2 Benefits

  1. The logic for each concern is now in one place, as opposed to being scattered all over the code base.
  2. Classes are cleaner since they only contain code for their primary concern (or core functionality) and secondary concerns have been moved to aspects.

OOP and AOP are not mutually exclusive. AOP can be good addition to OOP. AOP is especially handy for adding standard code like logging, performance tracking, etc. to methods without clogging up the method code with this standard code.

Assume you have a graphical class with many “set…()” methods. After each set method, the data of the graphics changed, thus the graphics changed and thus the graphics need to be updated on screen. Assume to repaint the graphics you must call “Display.update()”. The classical approach is to solve this by adding more code. At the end of each set method you write

 void set...(...) {
    :
    :
    Display.update();
}

If you have 3 set-methods, that is not a problem. If you have 200 (hypothetical), it’s getting real painful to add this everywhere. Also whenever you add a new set-method, you must be sure to not forget adding this to the end, otherwise you just created a bug.

AOP solves this without adding tons of code, instead you add an aspect:

after() : set() {
   Display.update();
}

And that’s it! Instead of writing the update code yourself, you just tell the system that after a set() pointcut has been reached, it must run this code and it will run this code. No need to update 200 methods, no need to make sure you don’t forget to add this code on a new set-method. Additionally you just need a pointcut:

pointcut set() : execution(* set*(*) ) && this(MyGraphicsClass) && within(com.company.*);

What does that mean? That means if a method is named “set*” (* means any name might follow after set), regardless of what the method returns (first asterisk) or what parameters it takes (third asterisk) and it is a method of MyGraphicsClass and this class is part of the package “com.company.*”, then this is a set() pointcut. And our first code says “after running any method that is a set pointcut, run the following code”.

See how AOP elegantly solves the problem here? Actually everything described here can be done at compile time. A AOP preprocessor can just modify your source (e.g. adding Display.update() to the end of every set-pointcut method) before even compiling the class itself.

However, this example also shows one of the big downsides of AOP. AOP is actually doing something that many programmers consider an “Anti-Pattern”. The exact pattern is called “Action at a distance”.

Action at a distance is an anti-pattern (a recognized common error) in which behavior in one part of a program varies wildly based on difficult or impossible to identify operations in another part of the program.

As a newbie to a project, I might just read the code of any set-method and consider it broken, as it seems to not update the display. I don’t see by just looking at the code of a set-method, that after it is executed, some other code will “magically” be executed to update the display. I consider this a serious downside! By making changes to a method, strange bugs might be introduced. Further understanding the code flow of code where certain things seem to work correctly, but are not obvious (as I said, they just magically work… somehow), is really hard.

OOP and AOP are not mutually exclusive. AOP can be good addition to OOP. AOP is especially handy for adding standard code like logging, performance tracking, etc. to methods without clogging up the method code with this standard code.

AOP addresses the problem of cross-cutting concerns, which would be any kind of code that is repeated in different methods and can’t normally be completely refactored into its own module, like with logging or verification

function mainProgram()
{  
   var x =  foo();
   doSomethingWith(x);
   return x;
 }

 aspect logging
 { 
    before (mainProgram is called):
    { 
       log.Write("entering mainProgram");
    }

     after (mainProgram is called):
    {  
      log.Write(  "exiting mainProgram with return value of "
                + mainProgram.returnValue);
    }
 } 

 aspect verification
 { 
  before (doSomethingWith is called):
  { 
       if (doSomethingWith.arguments[0] == null) 
       { 
         throw NullArgumentException();
       }

      if (!doSomethingWith.caller.isAuthenticated)
      { 
         throw Securityexception();
      }
    }
 }

And then an aspect-weaver is used to compile the code into this:

function mainProgram()
 { 
   log.Write("entering mainProgram");

   var x = foo();   

   if (x == null) throw NullArgumentException();
   if (!mainProgramIsAuthenticated()) throw Securityexception();
   doSomethingWith(x);   

   log.Write("exiting mainProgram with return value of "+ x);
   return x;
 }

Cross Cutting Concerns

  1. Database Access
  2. Data Entities
  3. Email/Notification
  4. Error Handling
  5. Logging

A Wrapper class is any class which “wraps” or “encapsulates” the functionality of another class or component.These are useful by providing a level of abstraction from the implementation of the underlying class or component.

A wrapper class is a class that “wraps” around something else, just like its name.

In general a wrapper is going to expand on what the wrappee does, without being concerned about the implementation of the wrappee, otherwise there’s no point of wrapping versus extending the wrapped class. A typical example is to add timing information or logging functionality around some other service interface, as opposed to adding it to every implementation of that interface.

For example
Wrapper classes provides a way to use the primitive types as objects. For each primitive , we have wrapper class such as for

int Integer
byte Byte 

Integer and Byte are the wrapper classes of primitive int and byte. There are times/restrictions when you need to use the primitives as objects so wrapper classes provide a mechanism called as boxing/unboxing.

Concept can be well understood by the following example as

double d = 135.0 d;

Double doubleWrapper = new Double(d);

int integerValue = doubleWrapper.intValue();
byte byteValue = doubleWrapper.byteValue();
sting stringValue = doubleWrapper.stringValue();

So this is the way , we can use wrapper class type to convert into other primitive types as well. This type of conversion is used when you need to convert a primitive type to object and use them to get other primitives as well.Though for this approach , you need to write a big code . However, the same can be achieved with the simple casting technique as code snippet can be achieved as below

double d = 135.0;
int integerValue = (int) d ;

In general a wrapper is going to expand on what the wrappee does, without being concerned about the implementation of the wrappee, otherwise there’s no point of wrapping versus extending the wrapped class. A typical example is to add timing information or logging functionality around some other service interface, as opposed to adding it to every implementation of that interface.

This then ends up being a typical example for Aspect programming. Rather than going through an interface function by function and adding boilerplate logging, in aspect programming you define a pointcut, which is a kind of regular expression for methods, and then declare methods that you want to have executed before, after or around all methods matching the pointcut. Its probably fair to say that aspect programming is a kind of use of the Decorator pattern, which wrapper classes can also be used for, but that both technologies have other uses.

A boilerplate is a unit of writing that can be reused over and over without change.

A pointcut is a set of join points.