Avoiding Herd Mentality by Asking “Why?”

My two-year-old daughter is in a phase of her development where she questions everything she  doesn’t understand. She throws questions at us faster than a 90mph curve ball. I’ll admit there are times where the incessant “why is this blue?” and “why did you open the bottle?” become hard to tolerate but this is an important stage of her development which we really need to encourage and not suppress.

You see, her search for deeper understanding of things is helping to build her internal decision-making engine. She’ll be able to make better choices once she understands “the why”. I guess this is something that I learned from my father who would hammer this point to me over and over again, “If you don’t know why you’re doing something, then there is a strong likely hood that you’re making a bad choice”.

 

 

The field of social psychology presents us with a very potent example. Soccer fans often breakout into fights before games for the most silliest reasons. What originally started as a misunderstanding between between two opposing fans might turn into a big riot. Why? Because people just jumped into the fight without understanding why they were even fighting. In psychology this is known as mob psychology or herd mentality.

As developers, we’re faced with similar but different choices. When you get that dream job you’ve been waiting for you’re whole life and you’re asked to build  a new feature, we often don’t question why things are being done the way they are and jump in head first. Let’s be honest, it’s easy to follow existing conventions without asking questions.

The problem with this approach is that, we become like soccer fans who start vandalizing existing structures without understanding why they’re doing it in the first place.

Questioning or seeking deeper understanding from your colleague,manager,wife or friend can sometimes come across as being rude or even disrespectful. When I first began my career I used to harbor feelings of animosity toward our team lead who would incessantly question my code choices. I later learned how beneficial this was in being able to make better choices.

Developing complex applications will always present tough challenges and choices. However, understanding why you’re choosing one development approach as opposed to another will definitely go a long way to enhance your chances of success. In code reviews it’s important that we not follow a “herd mentality” way of thinking and simple nod our heads. We must question and seek clarity in order to drive us on the path to success.

Eliminating If-else statements using a rule engine

Nearly every developer at some time in their career has run into the dreaded long chain of if-else statements. The chain of conditional statements makes code difficult to read and debug. While working on a recent project, I discovered a new way to clean things up. I’ll first take you through the old approach with a simple example:

private static void Getgrade()
        {
            //Classic grade program
            double finalGrade = 86.4;
            if (finalGrade >= 95)
            {
                Console.WriteLine("Dan has obtained an A+, which is Outstanding");
            }
            else if (finalGrade >= 90 && finalGrade < 95)
            {
                Console.WriteLine("Dan has obtained an A-, which is Excellent");
            }
            else if (finalGrade >= 85 && finalGrade < 90)
            {
                Console.WriteLine("Dan has obtained a A, which is very good");
            }
            else if (finalGrade >= 70 && finalGrade < 85)
            {
                Console.WriteLine("Dan has obtained a B+, which is good");
            }
            else if (finalGrade >= 60 && finalGrade < 70)
            {
                Console.WriteLine("Dan has obtained a B, which is a pass");
            }
            else
            {
                Console.WriteLine("Dan has obtained an F, which is poor");
            }
        }

Now let’s take a look at how we can improve this with our rule engine. I’ll define two classes.

public class Rule<T>
    {
        public Func<T, bool> Test { get; set; }
        public string DisplayMessage { get; set; }
    }
 
public class Student
    {
        public string Name { get; set; }
        public double Grade { get; set; }
    }

The first class provides us with our template to generate rules for our engine. It comprises of two properties that make use of the Func delegate.

private static void GetGradeFromRuleEngine(Student freshman)
{
   var rules = new List<Rule<Student>>
                 {
                 new Rule<Student>
                 {
                  Test = e => e.Grade >= 95,
                   DisplayMessage =string.Format("{0} has obtained an A+, Which is Outstanding", freshman.Name)
                 },
                 new Rule<Student>
                 {
                   Test = e => e.Grade >= 90 && e.Grade < 95,
                   DisplayMessage =string.Format("{0} has obtained an A-, which is Excellent", freshman.Name)
                 },
                 new Rule<Student>
                 {
                  Test = e => e.Grade >= 85 && e.Grade < 90,
                  DisplayMessage =string.Format("{0} has obtained a A, which is very good", freshman.Name)
                 },
                 new Rule<Student>
                 {
                  Test = e => e.Grade >= 70 && e.Grade < 85,
                  DisplayMessage =string.Format("{0} has obtained a B+, which is good", freshman.Name)
                 },
                 new Rule<Student>
                 {
                  Test = e => e.Grade >= 60 && e.Grade < 70,
                  DisplayMessage = string.Format("{0} has obtained a B, which is a pass", freshman.Name)
                 },
                  new Rule<Student>
                 {
                   Test = e => e.Grade >= 60 && e.Grade < 70,
                   DisplayMessage =string.Format("{0} has obtained an F, which is poor", freshman.Name)
                 },
 
               };
 
            bool isValid = rules.Any(r => r.Test(freshman));
            if (isValid)
            {
                var validRules = rules.Where(r => r.Test(freshman));
 
                string message = validRules.SingleOrDefault().DisplayMessage;
 
                Console.WriteLine(message);
            }
 
        }

We then create a method that accepts a student object called GetGradeFromRuleEngine. The next thing we do is to build our rule engine. This structure makes it very easy to modify and even add new rules to our engine. Below is how you will run this and voila.

class Program
    {
        static void Main(string[] args)
        {
            var dan = new Student()
            {
                Name = "Dan",
                Grade = 86.4
            };
 
            GetGradeFromRuleEngine(dan);
        }
 
}

Breaking down Interfaces

I often hear heated debates between developers about the usage of interfaces. Unfortunately, many of these debates are skewed toward the personal preferences of developers who fail to understand what an interface is and what it does.

So let me use a couple of minutes to break it down for you…..

Take a Digital Video interface (DVI) port, which is used to connect a computer and a display device. The DVI port doesn’t need to know whether the display device is a Samsung flat screen monitor or Acer LCD monitor.Neither does it need to know how the Samsung monitor will connect internally to the computer. All the interface provides is a means of connecting any computer to any display device. Essentially, it says “Hey Computer, connect to this monitor” and ‘Hey Presto!’ they’re connected.

In the realm of programming, an interface does exactly the same thing. It provides a way for objects to interact without each object having to specify the inner details of how they intend to interact with another object. Here is a brief summary of the role of an interace

  • An interface allows us to separate the usage of something from how it is implemented
  • Interfaces are like contracts which define what operations should be performed
  • An interface constitutes a declaration about intentions
Benefits of Interfaces
  • Code readability: Using interfaces will improve your code readability because you’re interfaces will define and state your intentions. If you implement ISortable you’re clearly stating that your class can be sorted, same for IRenderable or IConvertible.
  • Code Semantics: By providing interfaces and implementing them you’re actively separating concepts in a similar way HTML and CSS does
  • Code maintainability: Interfaces helps to reduce coupling and therefore allow you to easily interchange implementations for the same concept without the underlying code being affected
Things you should know
  • A class can implement multiple interfaces
  • Interface members are all implicitly abstract
  • An interface can contain only methods, properties, events and indexers
Example

In this example, we define a very simple interface called IConnectable. IConnectable defines a new contract which states that any class which implements me must define a method called connect. In a real world application, the connect method in the Lenovo and series9 objects would then provide the necessary details about how to connect.

namespace InterfaceExample
{
      public interface IConnectable
      {
            void Connect();
      }
 
      public class Computer : IConnectable
      {
            public void Connect()
            {
 
                  Console.WriteLine("I can connect to any display device attached to me");
            }
      }
      public class SamsungMonitor : IConnectable
      {
            public void Connect()
            {
                  Console.WriteLine("I can connect to any Computer attached to me");
            }
      }
 
      class Program
      {
            static void Main(string[] args)
            {
                  Computer lenovo = new Computer();
                  SamsungMonitor series9 = new SamsungMonitor();
 
                  lenovo.Connect();
                  series9.Connect();
 
                  Console.Read();
 
            }
      }
}