Whitewashing is the blog of Benjamin Eberlei and covers topics in software development. Benjamin works for Qafoo and you can book him for consulting and trainings.

Follow me on twitter Subscribe to RSS My Github Profile

Spotting Feature Envy and Refactoring

I was following Aki’s on the SoCraTes2014 conference last week about Legacy Code and Refactoring. In the session a piece of real-world code was shown that contained one of most common code smells in LegacyCode: Feature Envy.

Martin Fowler describes this smell as “a method that seems more interested in a class other than the one it is in. The most common focus of the envy is the data.”

This code smell causes two very similar problems in a code base:

  • Duplication of rules related to their data throughout the code base.
  • Spreading domain concepts throughout the whole code-base.

A simple example can show this problem with DateTime is wide-spread in many PHP projects. We often see code such as the following computation to create a range of dates for a reporting function:

<?php

function calculateReport(DateTime $start, $days)
{
    if ($days < 0) {
        throw new InvalidArgumentException($days);
    }

    $endDate = clone $start;
    $endDate->modify('+' . $days . ' day');

    // calculation code here
}

This is a really simple example for Feature Envy: The computation and validation of creating an end date some days in the future of a start date can easily be duplicated throughout the whole code base and implements business rules that belong to the class DateTime itself:

<?php

class DateTime
{
    // ... other methods

    public function getDateDaysInFuture($days)
    {
        if ($days < 0) {
            throw new InvalidArgumentException($days);
        }

        $endDate = clone $this;
        $endDate->modify('+' . $days . ' day');

        return $endDate;
    }
}

function calculateReport(DateTime $start, $days)
{
    $endDate = $start->getDateDaysInFuture($days);

    // calculation code here.
}

(Note: You cant extend the builtin DateTime this way and need to subclass).

This is a great way to improve your code base massively and achieve what Object-Oriented and Domain-Driven Design is about: Modelling concepts of the domain by encapsulating data and behavior.

Learning to spot this kind of Feature Envy is a very good way to incrementally improve your legacy code base towards better models. I find it very interesting that the focus on fixing technical code-smells duplication and feature envy actually leads to a better domain model. As a side effect it massively deemphasizes DDD building blocks like Entity or Value Object, which in my opinion are a big cause for confusion. Testability increases as well, because data objects with behavior are much simpler to setup for testing.

That is why I recommend learning about Feature Envy. For me it is a very simple approach to find improvements.

blog comments powered by Disqus