Pages

Tuesday, March 28, 2017

Why Good Employees Quit

Ever had an incredible employee, and thought, “This is the one!”  They were smart, engaged, driven, and seemed to really love the job.  You thought, “We’re going to be together forever!” You could really see yourself promoting this person, mentoring them, watching them climb the ranks in your company…

And then one day, they quit.

They might give you the, “It’s not you, it’s me…” speech, but what does it actually mean?

Here are some reasons employees might quit a job (even one they love) — and what you can do to prevent it.

No respect

There’s an old saying that employees don’t leave a company, they leave a manager. No matter how much you like, respect, or appreciate an employee, if they don’t know it, they may leave. Make sure your interactions with employees are always respectful, and that you look for ways to actively value their contribution.

No vision

You or the CEO may have a vision for where the company is going — but do all your employees? Some of the most successful companies are able to attract and retain great employees because they are great at communicating their vision all the way from the top down to the front-line workers. (And don’t confuse vision with financials; it needs to be bigger than that, especially if the employee in question doesn’t have stock options!)

No future

Have you outlined a clear path for advancement for your best employees?  Or are they looking at a dead-end job? They might be the best cashier / phone operator / junior undersecretary you’ve ever had, but that doesn’t mean they want to stay in that position forever. It pays to get to know your employee’s goals and help them see how they can achieve them within your company.

No equality

No one wants to stick around in a workplace that doesn’t treat them fairly. Do a quick gut-check: Are you paying women less than men? How about minorities? Younger workers in particular are not willing to stick around at a company that is racist, sexist, ageist, or otherwise discriminatory in any way.

No morale

Even if a particular employee is positive and energetic, it is draining to be surrounded by people with low morale. Team identity and unity may be key to engaging and retaining those great employees you want. When everyone else is unhappy and not putting in a good effort, no one wants to work there.

No challenge or autonomy

If you aren’t providing the opportunity for challenging, engaging work, you’re naturally going to lose those employees who want to be challenged or have a certain measure of autonomy over their work and lives. Few people are happy being micromanaged or simply toeing the company line when they have ideas for innovation. No one wants to feel infantilized or that they aren’t trusted to make the most basic decisions in their work. People want the opportunity to be the expert in their own job.

So what’s the solution? How can you prevent that perfect employee from jumping ship?

Practice actively listening and engaging with all your employees on a regular basis.  One idea is to implement stay interviews (instead of exit interviews) to ask your current employees why they stay with the company. It helps to build a strong level of trust and engagement with employees when they are allowed to bring both their goals and their concerns to a manager — before it’s too late to identify and solve the problems.

What do you think? What can managers do to help retain their best employees? I’d be interested in reading your contributions in the comments below.

 

Thoughts for Testing

 would believe, without any evidence, that a majority of the test community and product development companies have matured in their view on testing. At conferences you less frequently see the argumentation that testing is not needed. From my own experience and perceiving the local market, there is often new assignments for testers. Many companies try to hire testers or get in new consulting testers. At least looking back a few years and up until now.

At many companies there is an ever increasing focus and interest in Continuous Deployment. Sadly, I see troublesome strategies for testing in many organisations. Some companies intend to focus fully on automation, even letting go of their so called manual testers. Other companies focus on automation by not accepting testers to actually test and explore. This troubles me. Haven’t testers been involved in the test strategy? Here are few of my pointers, arguments and reasoning.

Automation Snake oil
In 1999 James Bach wrote the article Automation Snake Oil [see reference 1], where he brings up a thoughtful list of arguments and traps to be avoided. Close to 17 years later, we see the same problems. In many cases they have increased because of the Continuous Deployment ideas, but also because of those from Agile development. That is, if you ignore all the new ideas gained in the test domain as well as all research done.
The miracle status of automation is not a new phenomenon, together with the lure of saving time and cost it is seducing. In some cases it will probably be true, but it is not a replacement of thinking people. Instead it could be an enabler for speed and quality.

Testing vs. Checking
In 2009, Michael Bolton wrote an article that clarified a distinction between Testing and Checking. Since then the definition has evolved. The latest article Testing vs. Checking Refined [see reference 2] is the last in the series. Most of the testers I know and that I debate with are aware of this concept and agree with the difference or acknowledge the concept.

If you produce test strategies in a CI-environment that put an emphasis on automation, and if it means mostly doing checking and almost no testing (as in exploration), then you won’t find the unexpected. Good testing include both.

Furthermore when developing a new feature, are you focusing on automating checks fulfilling the acceptance criteria or do you try to find things that have not been considered by the team? If you define the acceptance criteria, then only check if that is fulfilled. It will only enable you to reach a small part of the way toward good quality. You might be really happy how fast it goes to develop and check (not test) the functionality. You might even be happy that you can repeat the same tests over and over. But I guess you failed to run that one little test that would have identified the most valuable thing.

Many years ago a tester came to me with a problem. He said, “We have 16000 automated tests, still our customers have problems and we do not find their problems”. I told him that he might need to change strategy and focus more on exploration. Several years later another tester came to me with the same problem, from the same product and projects. He said, “We have 24000 automated tests, still our customers have problems and we do not find their problems!”. I was a bit surprised that the persistence in following the same strategy for automation while at the same time expecting a different outcome.

In a recent argument with a development manager and Continuous Deployment enthusiast. They explained their strategy and emphasis on automation. They put little focus on testing and exploration. Mostly hiring developers who needed to automate tests (or rather checks). I asked how they do their test design? How do they know what they need to test? One of my arguments was that they limited their test effort based on what could be automated.

We know that there is an infinite amount of tests. If you have done some research, you have an idea what different stakeholders value and what they are afraid will happen. If that is so, then you have an idea what tests would be valuable to do or which areas you wish to explore. Out of all those tests, you probably only want to run part of these tests only once, where you want to investigate something that might be a problem, learn more about the systems behavior or try a specific, very difficult setup or configuration of the system. This is not something that you would want to automate because it is too costly and it is enough to learn about it just once, as far as you know. There are probably other tests that you want to repeat, but most probably with variation in new dimensions, and do more often. It could be tests that focus on specific risks or functionality that must work at all times. Out of all those that you actually want to test several times, a part of those you plan and want to automate. Out of those that you have planned to automate, only a fraction can be automated. Since automation takes a long time and is difficult, you have probably only automated a small part of those.

If you are a stakeholder, how can you consider this to be ok?

Rikard Edgren visualized the concept of what is important and what you should be in focus in a blog post called “In search of the potato” [see reference 3].

His main points are that the valuable and important is not only in the specification or requirements, you need to go beyond that.

Another explanation around the same concept of the potato is that of mapping the information space by knowns and unknowns.

The majority of test automation focus on checking an aspect of the system. You probably want to make repeatable tests on things that you know or think you know, thus the Known Knowns. In making this repeatable checking you will probably save time in finding things that you thought you knew, but that might change over time by evolving the system, thus evaluating the Unknown Knowns. In this area you can specify what you expect, would a correct result would be. With limitation on the Oracle problem, more on that below.

If you are looking beyond the specification and the explicit, you will identify things that you want to explore and want to learn more about. Areas for exploration, specific risks or just an idea you wish to understand. This is the Known Unknowns. You cannot clearly state your expectations before investigating here. You cannot, for the most part, automate the Known Unknowns.

While exploring/testing, while checking or while doing anything with the system, you will find new things that no one so far had thought of, thus things that fall into the Unknown Unknowns. Through serendipity you find something surprisingly valuable. You rarely automate serendipity.

You most probably dwell in the known areas for test automation. Would it be ok to ignore things that are valuable that you do not know of until you have spent enough time testing or exploring?

The Oracle Problem
A problem that is probably unsolvable, is that there are none (or at least very few) perfect or true oracles [see reference 4, 5, 6].

A “True oracle” faithfully reproduces all relevant results for a SUT using independent platform, algorithms, processes, compilers, code, etc. The same values are fed to the SUT and the Oracle for results comparison. The Oracle for an algorithm or subroutine can be straightforward enough for this type of oracle to be considered. The sin() function, for example, can be implemented separately using different algorithms and the results compared to exhaustively test the results (assuming the availability of sufficient machine cycles). For a given test case all values input to the SUT are verified to be “correct” using the Oracle’s separate algorithm. The less the SUT has in common with the Oracle, the more confidence in the correctness of the results (since common hardware, compilers, operating systems, algorithms, etc., may inject errors that effect both the SUT and Oracle the same way). Test cases employing a true oracle are usually limited by available machine time and system resources.
Quote from Douglas Hoffman in A taxonomy of Test Oracles [see reference 6].

Here is a the traditional view of a system under test is like the figure 1 below.

In reality, the situation is much more complex, see figure 2 below.

This means that we might have a rough idea about the initial state and the test inputs, but not full control of all surrounding states and inputs. We get a result of a test that can only give an indication that something is somewhat right or correct. The thing we check can be correct, but everything around it that we do not check or verify can be utterly wrong.

So when we are saying that we want to automate everything, we are also saying that we put our trust in something that is lacking perfect oracles.

With this in mind, do we want our end-users to get a system that could work sometimes?

Spec Checking and Bug Blindness

In an article from 2011, Ian McCowatt expresses his view on A Universe of behavior connected to Needed, Implemented and Specified based on the book Software Testing: A Craftsman’s Approach” by Paul Jorgensen.

For automation, I would expect that focus would be on area 5 and 6. But what about unimplemented specifications in area 2 and 3? Or unfullfilled needs in area 1 and 2? Or unexpected behaviors in area 4 and 7? Partly undesired behaviors will be covered in area 6 and 7, but enough?

As a stakeholders, do you think it is ok to limit the overall test effort to where automation is possible?

Concluding thoughts

It seems like we have been repeating the same things for a long time. This article is for those of you who are still fighting battles against strategies for testing which state automate everything.

 

Friday, March 3, 2017

Sealed Class in C#

Sealed classes are used to restrict the inheritance feature of object oriented programming. Once a class is defined as a sealed class, the class cannot be inherited. 

In C#, the sealed modifier is used to define a class as sealed. In Visual Basic .NET theNotInheritable keyword serves the purpose of sealed. If a class is derived from a sealed class then the compiler throws an error.

If you have ever noticed, structs are sealed. You cannot derive a class from a struct. 

The following class definition defines a sealed class in C#:



// Sealed class
sealed class SealedClass
{

}
 

In the following code, I create a sealed class SealedClass and use it from Class1. If you run this code then it will work fine. But if you try to derive a class from the SealedClass, you will get an error.


using System;
class Class1
{
    static void Main(string[] args)
    {
        SealedClass sealedCls = new SealedClass();
        int total = sealedCls.Add(45);
        Console.WriteLine("Total = " + total.ToString());
    }
}
// Sealed class
sealed class SealedClass
{
    public int Add(int x, int y)
    {
        return x + y;
    }
} 

MSDN Updated

Sealed Methods and Properties

You can also use the sealed modifier on a method or a property that overrides a virtual method or property in a base class. This enables you to allow classes to derive from your class and prevent other developers that are using your classes from overriding specific virtual methods and properties. 

class X
{
  protected virtual void F() { Console.WriteLine("X.F"); }
  protected virtual void F2() { Console.WriteLine("X.F2"); }
}

class Y : X
{
  sealed protected override void F() { Console.WriteLine("Y.F"); }
protected override void F2() { Console.WriteLine("X.F3"); }
}

class Z : Y
{
  // Attempting to override F causes compiler error CS0239. 
  // protected override void F() { Console.WriteLine("C.F"); }
// Overriding F2 is allowed. 
  protected override void F2() { Console.WriteLine("Z.F2"); }
}

Why Sealed Classes?


We just saw how to create and use a sealed class. The main purpose of a sealed class is to take away the inheritance feature from the user so they cannot derive a class from a sealed class. One of the best usage of sealed classes is when you have a class with static members. For example, the "Pens" and "Brushes" classes of the "System.Drawing" namespace. 

The Pens class represents the pens for standard colors. This class has only static members. For example, "Pens.Blue" represents a pen with the blue color. Similarly, the "Brushes" class represents standard brushes. "Brushes.Blue" represents a brush with blue color.
 

So when you're designing your application, you may keep in mind that you have sealed classes to seal the user's boundaries. 

In the next article of this series, I will discuss some usage of abstract classes. 

Builder pattern

The builder pattern is an object creation software design pattern. Unlike the abstract factory pattern and the factory method pattern whose intention is to enable polymorphism, the intention of the builder pattern is to find a solution to the telescoping constructor anti-pattern. The telescoping constructor anti-pattern occurs when the increase of object constructor parameter combination leads to an exponential list of constructors. Instead of using numerous constructors, the builder pattern uses another object, a builder, that receives each initialization parameter step by step and then returns the resulting constructed object at once.


Definition

The intent of the Builder design pattern is to separate the construction of a complex object from its representation. By doing so the same construction process can create different representations. [2]

Advantages

<![if !supportLists]>·        <![endif]>Allows you to vary a product’s internal representation.
<![if !supportLists]>·        <![endif]>Encapsulates code for construction and representation.
<![if !supportLists]>·        <![endif]>Provides control over steps of construction process.

Disadvantages               

<![if !supportLists]>·        <![endif]>Requires creating a separate ConcreteBuilder for each different type of Product.

Structure

Builder
Abstract interface for creating objects (product).
ConcreteBuilder
Provides implementation for Builder. It is an object able to construct other objects. Constructs and assembles parts to build the objects.



/// <summary>
/// Represents a product created by the builder
/// </summary>
public class Car
{
    public Car()
    {
    }

    public int Wheels { get; set; }

    public string Colour { get; set; }
}

/// <summary>
/// The builder abstraction
/// </summary>
public interface ICarBuilder
{
    // Adding NotNull attribute to prevent null input argument
    void SetColour([NotNull]string colour);

    // Adding NotNull attribute to prevent null input argument
    void SetWheels([NotNull]int count);

    Car GetResult();
}

/// <summary>
/// Concrete builder implementation
/// </summary>
public class CarBuilder : ICarBuilder
{
    private Car _car;

    public CarBuilder()
    {
        this._car = new Car();
    }

    public void SetColour(string colour)
    {
        this._car.Colour = colour;
    }

    public void SetWheels(int count)
    {
        this._car.Wheels = count;
    }

    public Car GetResult()
    {
        return this._car;
    }
}

/// <summary>
/// The director
/// </summary>
public class CarBuildDirector
{
    public Car Construct()
    {
        CarBuilder builder = new CarBuilder();

        builder.SetColour("Red");
        builder.SetWheels(4);

        return builder.GetResult();
    }
}
The Director assembles a car instance in the example above, delegating the construction to a separate builder object.