views:

271

answers:

3

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...

+1  A: 

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
+6  A: 

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
+1 Extension methods are perfect for this kind of problem
Diadistis
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
what about class NormalizedIList extends IList?
atk
I may be wrong here, but if `Utilities.Segment(points, 50)` is fine, what's wrong with `points.Segment(50)`?
Håvard S
@HåvardS: Good point.
John Gietzen
+1  A: 

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
Notice that all the examples from the BCL are grouped around a particular responsibility. There's no generic `Utils` class anywhere.
Ben Voigt
What is BCL? Do you mean Base Class Libraries (BCL)?
AMissico
Open *.NET Reflector*. Search for "util". There are 256 examples using the default (BCL) 4.0 assemblies loaded by *.NET Reflector*.
AMissico