75

I generally live by the rule that Global variables / functions are evil and that every piece of code should live in the class to which it pertains.

This is a very easy rule to follow, and I believe that I haven't ever run into an issue with this rule until now.

Today, however, I need to add a function to my assembly rather than to a specific class. That is, almost all of my classes could have a use for this particular function.

Where should I put this function (+1 overload)?

If I put it in a "Utilities" class, I feel dirty. If I tack it on to a semi-related class, and let other classes call it directly, I feel worse.

This particular piece of code basically chops a IList<PointF> into a normalized list. I feel right now that adding it as an extension method on IList<PointF> may be the best bet...

John Gietzen
  • 48,783
  • 32
  • 145
  • 190
  • 1
    I agree, global variables are evil. They seem to have minds of their own devoted to undermining your code. – Rafe Kettler Jul 27 '10 at 00:31
  • 26
    Global state is problematic, but global functions are just logic that's reusable with too few ins/outs to be worth encapsulating in a class. I don't see any problem at all with Helper or Utility methods grouped into appropriately named Helper or Utility static classes. – Dan Bryant Jul 27 '10 at 00:58
  • I prefer using "Pull Up Method" instead of Utility/Helper class - [Pull Up Method](https://refactoring.guru/pull-up-method) – Sumeet Patil Dec 10 '17 at 07:28

3 Answers3

35

If this is an operation on an IList<PointF>, then it should be an extension method on IList<PointF>.

Generally, Utils and Helper type classes should be avoided. More often than not, you will find that what you may think is a utility method, is actually a rather specific method that probably belongs in a class of its own (just like you say). However, there will be domain specific cases where Util-like classes (classes which group related useful methods) are valid entities.

Håvard S
  • 23,244
  • 8
  • 61
  • 72
  • 3
    +1 Extension methods are perfect for this kind of problem – Diadistis Jul 27 '10 at 00:33
  • 1
    Yeah, but my reservation here is that if it is an extension, then it needs to have a fluent sounding name... something like `points.NormalizeIntoSegments(50)`, instead of my preferred `Utilities.Segment(points, 50)`. – John Gietzen Jul 27 '10 at 00:34
  • 1
    what about class NormalizedIList extends IList? – atk Jul 27 '10 at 00:38
  • 6
    I may be wrong here, but if `Utilities.Segment(points, 50)` is fine, what's wrong with `points.Segment(50)`? – Håvard S Jul 27 '10 at 00:39
  • @Diadistis What is an extension method? – Koray Tugay Dec 18 '15 at 20:09
  • @KorayTugay [Extension methods](https://msdn.microsoft.com/en-us/library/bb383977.aspx) enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. – Diadistis Dec 18 '15 at 20:47
  • 5
    Extension methods and static utility methods are actually the same thing. The **only** difference is the method call syntax, where the first argument to a extension method is placed before the `.` operator. The way you use extension methods and static utility methods to design software is exactly the same. I find it confusing that this answer seems to imply that there is a difference. – Lii Jul 27 '17 at 18:39
  • I am from Java world. I have a rule. If I want to add functionalities to a API class e.g Date, String I create a specific Util class. like DateUtil, StringUtil. Otherwise, as you said most of the util method are later found it's belong to a class. – seal Nov 10 '19 at 17:30
13

There is nothing wrong with "global" variables and methods. You use them all the time. The framework likes to call them "static" classes or "static" methods.

I rarely need to, but I usually add an internal static class Util in the namespace that the method/variable is needed for C# and a module for VB.NET.

Samples from .NET Framework

  • System.Collections.Specialized.CollectionsUtil
  • System.Net.WebUtility
  • Check Microsoft's source code for .NET Framework. You will find numerous internal utility classes.
AMissico
  • 21,470
  • 7
  • 78
  • 106
  • 2
    Notice that all the examples from the BCL are grouped around a particular responsibility. There's no generic `Utils` class anywhere. – Ben Voigt Jul 27 '10 at 04:09
  • What is BCL? Do you mean Base Class Libraries (BCL)? – AMissico Jul 27 '10 at 14:42
  • 1
    Open *.NET Reflector*. Search for "util". There are 256 examples using the default (BCL) 4.0 assemblies loaded by *.NET Reflector*. – AMissico Jul 27 '10 at 14:46
4

You should put it into a 'ListUtilities' or PointListUtilities class, of course. Then you aren't breaking the single responsibility principle, which is the primary problem with a catch-all 'Utilities' class.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720