This article was originally published at Codeproject
Toy example
Wandering through codebases I've encountered some examples of code where ReSharper issues warning "Method can be made static". Although fix seems straightforward the warning itself may hide more subtle issue connected to object responsibility assignment.If you've never used ReSharper still stay with me. I hope you'll find easy to catch up.
Let's take a look at the following code
public class EmailConstructor
{
private const string Signature = "Regards";
public string Construct(User recipient, string body)
{
var builder = new StringBuilder();
builder.Append($"Hello {GetNiceUserName(recipient)}");
builder.Append(Environment.NewLine);
builder.Append(body);
builder.Append(Environment.NewLine);
builder.Append(Signature);
return builder.ToString();
}
private string GetNiceUserName(User user)
{
return $"{user.Name} {user.Surname}";
}
}
public class User
{
public string Name { get; set; }
public string Surname { get; set; }
}
Indeed ReSharper issues the warning.
Feature envy
Although things may seem obvious at the first glance actually the code above is the example of Feature envy. As the rule of thumb which would help you to spot such cases without using tools such as ReSharper, you may use one of the principles postulated by Craig Larman in his book "Applying UML and patterns".
Information expert will lead to placing the responsibility on the class with the most information required to fulfill it.
According to this principle, you can fix the warning my moving method inside theUser
class as follows as the User is the one who has more information to represent his name in one or another way
public class EmailConstructor
{
private const string Signature = "Regards";
public string Construct(User recipient, string body)
{
var builder = new StringBuilder();
builder.Append($"Hello {recipient.GetNiceUserName()}");
builder.Append(Environment.NewLine);
builder.Append(body);
builder.Append(Environment.NewLine);
builder.Append(Signature);
return builder.ToString();
}
}
public class User
{
public string Name { get; set; }
public string Surname { get; set; }
public string GetNiceUserName()
{
return $"{Name} {Surname}";
}
}
High cohesion
Naturally, the question arises from the example above: "Won't this lead to bloating User class with lots of responsibilities such as, for example, working with persistent storage?". The answer is that Information expert principle should be used together with High Cohesion principle.
High cohesion is generally used in support of low coupling. High cohesion means that the responsibilities of a given element are strongly related and highly focused. Breaking programs into classes and subsystems is an example of activities that increase the cohesive properties of a system. Alternatively, low cohesion is a situation in which a given element has too many unrelated responsibilities. Elements with low cohesion often suffer from being hard to comprehend, hard to reuse, hard to maintain and averse to change.
Thus if we, for example, would like to extend our toy code with persistent storage interaction we would likely extract highly cohesive functions dedicates to that into some sort of Unit of Work pattern.
Conclusion
Static members have some disadvantages such as they complicate unit testing. That's why static should be considered with care. Craig Larman's GRASP patterns in combining with SOLID allow us to examine such cases in order to reduce support cost of our codebases.
Top comments (0)