Friday, August 25, 2017

SOLID - 2. The Open/Closed Principle

In this article, I am describing the Open/Closed Principle. Another principle from the group of five principles that make up the SOLID acronym:


You can read up on my other articles on SOLID here:


The Open/Closed Principle

Its definition says: "Software entities (classes, modules, functions, etc.) must be open for extension but closed for modification."

When the software grows and different classes start to depend on each other, the risk of a change made in one class breaking code in some other class increases. The Open/Closed principle tries to address this problem.

To adhere to the OCP, your application should be build in a way that allows new functionality to be added to it without changing existing code, especially when the existing code is already used in multiple places in your application. 

Applications build without this principle in mind tend to become more and more fragile over their lifecycle until the cost of maintaining the application reaches a point at which it is just cheaper to rewrite it complelty.

Let's look at an example:

public class Actor { };

public class Player : Actor { };
public class Enemy : Actor { };

public class Playfield
{
    IList<Actor> _actors;
    Canvas _canvas;
    // ..

    public void DrawActors()
    {            
        foreach (Actor actor in _actors)
        {
            if (actor is Player)
            {
                // Code to draw the player sprite
            }
            else if (actor is Enemy)
            {
                // Code to draw the enemy sprite
            }
        }
    }
}

This is a code-snippet for a small game. There is a Player and an Enemy actor as well as a Playfield class for drawing the playfield to the screen. Different routines are required to draw the sprites for the Player and the Enemy actor which is handled by the “DrawActors” method.

This implementation violates the Open/Closed principle. Whenever we want to add new types of Actors to the game, the method DrawActors must be changed. It is not closed for modification. 

Let’s look at an implementation that follows the OCP:


public abstract class Actor
{
    public abstract void Draw(Canvas canvas);
}

public class Player : Actor
{
    public override void Draw(Canvas canvas)
    {
        // Code to draw the player sprite
    }
}

public class Enemy : Actor
{
    public override void Draw(Canvas canvas)
    {
        // Code to draw the enemy sprite
    }
}

public class Playfield
{
    IList<Actor> _actors;
    Canvas _canvas;
    // ..

    public void DrawActors()
    {            
        foreach (Actor actor in _actors)
        {
            actor.Draw(_canvas);
        }
    }
}

By moving the drawing logic to an abstract method of the actor base class, new actors can now be added to the game without the risk of breaking existing code. 


This implementation is much more robust and easy to extend.

Tuesday, August 15, 2017

SOLID - 1. The Single Responsibility Principle

With this article I am starting a series about five of the most important principles in software development.

These 5 principles came to be called SOLID after their popularization through Robert C. Martin ("Uncle Bob"). They are part of his famous book "Agile Principles, Patterns and Practices".

But after all, why FIVE principles? Because SOLID is an acronym. It stands for:



These principles, when properly applied, help to eliminate the design smells of your code, allowing greater ease of maintenance and extension. In this first post, I will explain the Single Responsibility Principle, sometimes also referred to as “Separation of concern”.

You can read up on my other articles on SOLID here:


The Single Responsibility Principle

This principle is nothing more than a different perspective on one of the most fundamental principles of object oriented software design: cohesion. Its definition says: A class must have only one reason to change.

We will try to understand what this means and any problems caused by violation of this principle.

A class with more than one reason to change has more than one responsibility, that is, it is not cohesive. This introduces serveral problems:

  • It is difficult to understand and therefore difficult to maintain.
  • It cannot easily be reused.
  • With responsibilities intertwined in the same class, it can be difficult to change one of these responsibilities without compromising others (rigidity) and it may end up breaking other parts of the software (fragility).
  • The class ends up having an excessive number of dependencies, and therefore is more subject to changes due to changes in other classes aswell.

Let's take a look at a common violation of SRP. Imagine a class "ShoppingList":

public class ShoppingList
{
    // ..
    public void AddProduct(Product product) { }

    public void RemoveProduct(Product product) { }

    public MemoryStream GenerateExcelExport() { }
}

This example shows an evident violation of the Single Responsibility Principle. It mixes responsibilities that should be distinct components of the software. While the first two methods make sense in the context of the shopping list’s responsibilities, the latter is related to exporting data in a particular format, which this class should not be concerned with at all.

We can solve this by moving the export logic into its own class:

public class ShoppingList
{
    // ..
    public void AddProduct(Product product) { }

    public void RemoveProduct(Product product) { }
}


public class ShoppingListExporter : AbstractExcelExport<ShoppingList>
{
    public override MemoryStream GenerateExport(ShoppingList entity)
    {
        // Export logic..
    }
}

Now, changes can be applied independently. 

Both classes only have one reason to change. A revision to the business rules of handling the shopping list will only impact the “ShoppingList” class and changes related to the export format will only leave the “ShoppingListExporter” class subject to change. As a result, the code is much better to maintain and each component can be easily exchanged.

Ignorance of the Single Responsibility Principle sometimes leads to so called “God”-classes with thousands of lines of code, gigantic methods and a huge number of dependencies that make them almost impossible to maintain.

Other common examples of violations against SRP include classes that mix business and persistence logic or view models that present business rules.


Beware, some examples are less obvious...

Even if a class is only doing tasks related to its domain, it may still be concerned with too many things. When implementing a class, ask yourself: "How can I further split up the responsibilies of this class?" If you cannot find an answer to this question, your class (propably) follows the Single Responsibilty Principle pretty well.

Look at the whole picture...

But don't stop there. The SRP should be applied throughout all layers of your software, from methods to classes to namespaces to projects to the solution itself.


Conclusion

SRP is one of the most important (and also most violated) principles that exists in object oriented programming. By remembering it and applying it thoughfully, you will design smaller, more cohesive, easier-to-understand code that is highly maintainable.

Friday, August 11, 2017

Thoughts on how to build and retain a strong team

Over the course of my professional career, I have come to believe that behind every strong company is a strong team. From Disney’s legendary team of core animators, known as the Nine Old Men, to Google’s founding team to Squarespace and its praiseworthy company culture—the examples of strong teams achieving remarkable things are plentiful. 

Companies with high-performing teams can turn the odds in their favor and move toward success where others would fall and crumble. But as Sadhan Choudhury writes in his comprehensive book on the subject of project management, "Team building is the most difficult part of organizing human resources." 

Instead of reinventing the wheel, it is wiser to learn from those who have built successful teams and decided to share their wisdom with others. One methodology that sparked my interest comes from the team consultant guru Jon Gordon and the former head coach of the NFL’s Atlanta Falcons Mike Smith.

In their book titled "You Win in the Locker Room First: The 7 C’s to Build a Winning Team in Business, Sports, and Life", Gordon and Smith talk about how strong teams are cultivated by the right culture, beliefs, relationships, and other factors. They summarize their principles as seven attributes that teams must foster in order to become successful.

Here they are:




1. Culture

"Culture drives expectations and beliefs; expectations and beliefs drive behavior; behavior drives habits; and habits create the future. It all starts with culture."

Jon Gordon and Mike Smith have taught me that strong team culture is the foundation upon which formidable teams are built. Such culture can be established only when it is shared by everyone in the organization - not just the individual team members. It must reflect the shared beliefs, goals, and habits of everyone working at the company.
The current state of company culture can be evaluated by asking questions such as, "What do we stand for?" and "What do we want to be known for?" If the answers vary, the company culture is misaligned. In order to transform an existing culture or create a new one from scratch, a strong vision for change must be developed and effectively communicated to awaken the inner fire in others that makes it into reality.


2. Contagious   

"Leadership is a transfer of purpose, passion, optimism, and belief."

As natural leaders, Gordon and Smith intuitively understand the power of a simple, compelling vision statement presented by a team leader who broadcasts positive energy that inspires other to overcome challenges and achieve success. 
Kim Cameron and Wayne Baker of U-M’s Ross School of Business and colleagues Brad Owens of Brigham Young University and Dana Sumpter of California State University-Long Beach found that, "the more relational energy a leader exudes, the better employees on that team perform in terms of productivity, absenteeism, engagement, and job retention."
  
But the influence of positive mindset is not limited to team leaders. When everyone in the organization shares the same positive mindset, great ideas can spread like a wildfire, igniting success. 


3. Consistent

"If you are not consistent, you will lose the trust your team has in you. When you lose trust, you lose the locker room."

I know from first-hand experience that things do not always go according to plan. Sometimes, bad outcomes happen regardless of how committed everyone was or how much preparation went into the project. In those cases, frustration and even anger are justifiable, but the absence of consistency is not.

Any company culture with a strong vision can be undermined by inconsistency. Those who are committed enough not to abandon their original vision the moment a challenge arrives are those who can achieve greatness.


4. Communicate   

"When there is a void in communication, negativity will fill it. Fill the void with great communication."

It is evident to me that communication is paramount for ideas to be shared, problems solved, and objectives set. Where there is an absence of communication, productivity decreases as negativity fills in. 

Effective communication is characterized by openness, friendliness, and focus. Everyone should be allowed to voice their opinion, and no opinion should be dismissed before being properly evaluated. History teaches us, that the soldiers in the trenches can often provide more valuable insight than the generals in the tents. 


5. Connect

"Team beats talent when talent isn’t a team."

While there are many examples in the IT world of rogue teams working alone to come up with groundbreaking products and solutions, I see such examples as rare exceptions and not something to strive for. My experience aligns with the view of Jon Gordon and Mike Smith, who stress the importance of connections. 

A team should be connected not only internally but also to other teams and to the larger work organization. Connected teams share ressources, communicate, and understand the wider implications of their decisions.


6. Commitment

"It’s not about you. It’s about committing yourself to your team."

I have seen many times the extent, to which strong team connections nurture commitment. When team members understand how their work fits into the company goals, and how the goals, in turn, impact them, they are more willing to commit to the common goal and make personal sacrifices to achieve it. 

Committed teams face difficult challenges with the same resolution and relentless desire to succeed as players coached by Mike Smith face their opponents. 


7. Care

"Relationships are the foundation upon which winning teams are built, and all great relationships are based on value, respect, love, trust, and care."

I have never seen members of a strong team that do not deeply care about one another. People who spend a considerable amount of time with like-minded individuals who share the same values and goals as they do tent to form strong bonds based on mutual understanding, respect, and comradery. 

It’s great to see team members helping one another to overcome professional hurdles as well as personal tragedies. Members of such teams are stronger as individuals because they can draw strength from the team’s collective pool of energy. 


Conclusion

Building strong teams is a complex process that requires a comprehensive approach. It is also a process with tremendous potential benefits for the individual team members and the organization that employs them alike. 

The 7 C’s methodology created by Jon Gordon and Mike Smith describes foundational principles for effective team building and team maintenance. The methodology can be easily adopted to suit the needs of software development teams working in both agile and traditional environments.


Sources







Friday, August 4, 2017

Microservice-driven Software Architectures

Over the last few years, software development techniques have evolved to match the ever-changing present day requirements. These emerging technological trends present a few approaches to choose from when building new software solutions. In this article, we consider Microservice driven software architecture and Monolithic architecture. Which is the best choice for the system you are working on?

Monolithic Architecture

Monolithic software architectures have been around since the invention of computers. They implement a design that tends to bundle all the functionalities needed to achieve a task into one single application. This is the simplest form of design because it does not involve many modular end points fitting together.
For small applications, Monolithic architecture works quite well with a minimum of complexity. The codebase is also quite small and centralized hence easy to deploy an application. However, whenever there's a need to scale up, a problem arises. This is because the modules are highly dependent on each other and refactoring a code in a single part of the monolith will impact the whole system.

Many enterprise applications are built in three parts: the database holding the records, a server-side application, and client-side application. In this case, the server-side application reads and updates the database, and then populates the views in the client-side application. Making changes to such a system will involve changing the server-side application and changing the views in the client-side application. This is a single application – a good example of a monolith. Over time, as the application grows, it becomes increasingly hard to make changes. Monolithic Architecture is suitable when building small applications with no foreseeable need to scale up.


Microservice Architecture

Microservice-driven software architectural design has been a major topic in software conferences in the recent years. As Martin Fowler - a renowned software developer and speaker puts it: 
The design has been there for a while only that it didn't have a name to identify it. 
While there’s no precise definition of Microservice architecture, we can describe it as a way of designing software applications as modules of independent services that can function on their own. As aptly named, Microservice architecture states that a service should be minimal, else be split into multiple services. 

Now, while Monolithic architecture is easy to design and deploy, Microservice architecture brings in a lot of complexities just from the design level. There are many small actors involved to make a solution work. All these actors are independent of each other and only communicate through simple interfaces. Despite these complexities in setup, Microservice architecture has many advantages as we will find out soon enough. 

Microservice architecture brings together some of the thoughts of Service Oriented Architecture (SOA), only that the services are much smaller. Microservice architecture is simply a better implementation of SOA. The high abstraction between services makes this the best option for designing large and scalable applications. The implementation of the services is completely hidden from the interface. This means, the services can be used in multiple contexts or other business processes. Additionally, developers can modify the services which lie behind interfaces without any downstream impact. Big tech companies such as Netflix, Twitter, PayPal, Amazon, Soundcloud and many other large-scale websites have moved from monolithic to microservice architecture. 

An article published by Martin Fowler and James Lewis introduces microservice architectural style as:

"An approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies."


So, when it comes to choosing an architectural design for your application, there are tradeoffs to consider. Here are the benefits and drawbacks of Microservice driven software architectures over monolithic software architectures.



Benefits

Reliability: 
Since services in a microservice architecture are highly independent, a fault in a microservice affects it alone while other services continue to work. While in a monolithic architecture, a fault in one part of the system is likely to bring down the whole monolith.

Availability: 
In a microservice architecture, making improvements to the codebase of a service requires little downtime only for consumers that depend on that particular service. In a monolithic setup, it will require a complete shutdown of the whole system and subsequent slower restart.

Scalability: 
Since services are independent, with each one having its own codebase, microservices can be scaled independently. Microservices are thus perfect for large applications with a large a growing user base.

Design autonomy: 
The development team is free to employ different technologies and frameworks they are well familiar with to implement each microservice. It’s also easy to change each microservice independently. Whereas in a monolithic architecture, since it’s a single application setup, frameworks used must be able to match.

Management: 
The application design and development effort is divided across teams with each team managing and documenting its service. It’s easier to manage smaller teams than one big team working on one large monolithic driven software.


Drawbacks

Complexity: 
In a microservice architecture, there are many services which need to communicate. The operation effort increases because more runtime components have to fit in place for the system to function properly. Whereas in a monolithic setup, it’s only a single application hence complexities of integrating modules are avoided.

Memory use: 
Codebases are often replicated in each microservice bundle and the overall memory footprint increases. In a monolithic setup, there’s no replication of services hence a lower memory footprint. 

Latency: 
Microservices usually communicate with each other through Web API’s (for example REST or SOAP). This introduces additional network latency in comparison to monolithic applications. Depending how distributed the microservices are being deployed, this can have a noticeable effect on the overall performance.


Conclusion

Time to draw the line. Do you consider scalability? Is a smaller memory footprint important to you? How about improving the codebase in future? These two software design architectures have their pros and cons. You need to understand functional and non-functional requirements of the application in question to make an informed decision. 

Microservice architecture is certainly an interesting option. It allows for flexibility and scalability which are major requirements of modern applications. 


Sources


Wednesday, August 2, 2017

Welcome to my blog!

The tide of change sweeping over the world today is unbridled. In fact, new technologies and thinking models are being developed every day. Have you ever wondered why it is becoming increasingly difficult to keep up with all the recent updates in software development techniques, strategies and procedures? Yes! Continue reading.

Thirty years ago, software developers were mostly limited by their ability to gain access to resources and the constrained processing power of the computers of that time. Today, resources are available for free to anyone with internet access. We can become an expert in any topic if only we are willing to devote enough of our precious time into learning all the intricate details of it. For a few bucks, anyone can rent a server cluster and perform excessive computations that were just unimaginable in the earlier years of computing.

The price we pay for this opulence is complexity. Dealing with all the new frameworks, methodologies and design practices that surface every day can be challenging. But it’s also a lot of fun.

I want to invite you to take on these challenges, keep learning and advance your skillset. With more than 15 years of work experience and almost 30 years of “life experience”, starting developing software in my early childhood, I hope to share with you some of my thoughts on interesting principles, methods and technologies in a way that benefits you and to grow within you the same passion for great software that drives me every day.