CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeffrey Palermo [MVP]

Software management consultant and CTO, Headspring Systems

Utility methods, utility classes, common classes - a blob is not an abstraction

This morning, I was reading the blog of J. Michael Palermo IV, and in his recent blog post, "utility methods - are they the devil", he asks whether utility methods are evil, and he concludes with "no".  I don't know about the evil part, but it caused me to reflect on my past.  While Mike is talking about utility _methods_, I'd like to address utilty _classes_.

I remember a time when I created a "Util" class and put in methods that contained everything from reading the contents of a file to putting a log message in the event viewer.  Essentially, anything I couldn't jam into a screen went into a utility method since I wanted to share this code.

I paused and reflected because I haven't written one of these classes in several years.  I can trace it back to my adoption of the Domain Model pattern and domain-driven design in general.  DDD stresses separation of concerns and giving each class a single responsibility.  Domain classes represent a single concept in the domain, and domain services provide one service to the application. 

When I look at a "Util" class and search for the concept it represents or its responsibility, I struggle.  I see it might be writing to files, writing to the event log, transforming XML with a provided XSLT stylesheet, etc.  When I see all these things going on, the only name that is general enough is "Util", and that's not an abstraction.   It's not meaningful.  It doesn't say anything about what's going on inside or what the responsibility is. 

I don't even think about it these days, but I like to create abstractions for everything (ok, not EVERYTHING).  I think it makes the application so much more maintainable, and the folks who have worked with me agree.  These aren't my ideas, by the way.  I'm very good at stealing ideas from others:  Martin Fowler, Robert C. Martin, Michael Feathers, Kent Beck, Eric Evans, Jimmy Nielson, and many others.

Consider the following needs that might be in a "Util" class:

  • File reading/writing - I have an IFileSystem interface for when my application needs to know it is using a file.  On the other hand, if I'm reading xml data from a file, and the xml is data for system logs, IFileSystem isn't an appropriate abstraction.  Here, I'd use ISystemLogRepository since my abstraction is a data store for SystemLog.  My application doesn't care that it's in xml, just that it can be retrieved.
  • Writing to event log - I'd have a ILogWriter interface with a WriteToEventLog method if my application really needed to know about the event log.  More often, my application only needs to care about logging _something_, and I'd configure Log4Net to pipe the message into the event log as one of the appenders.
  • Transform xml - I'd use an IXmlTransformer interface to front this concept for my application.  This interface would be used on the extremities of the application since in the core, there is no need for xml, only domain objects.

When I think back to my use of Util classes, I have to say it was before I was unit testing my code, before I had heard of Inversion of Control containers, and when I wrote my code very tightly coupled.  I'm not making the statement, "if you use Util classes, you are type XXXX", that would be absurd, but since I adopted testing, loose coupling, and DDD, I haven't written a single Util class.

Exception:  I HAVE written a util class in my integration test project called TestData.  It has static methods that populate common domain objects and save them to the database as a method to set up the context for an integration test that makes use of the the database.  In production code, I can't find a Util class by any name.



Comments

J. Michael Palermo IV said:

Jeffrey,

My response would be that I never suggested a utility class - just utility methods.  Even in your scenarios with interface implementations - they all need a concrete method to do the job.

I personally do not have a massive "Util" class filled with methods.  I do have a class called "Strings" that deals with common string scenarios I run into.

That said, I admittedly have not embraced your methodologies as you  have.  Perhaps upon further investigation I could see your viewpoint clearer...

# July 17, 2007 10:56 AM

Jeffrey Palermo said:

@Michael,

You are exactly right.  I've updated the post.  Your post just got me thinking.  You post gave me the INSPIRATION!! :-)

# July 17, 2007 11:10 AM

Jimmy Bogard said:

Don't forget Util's evil twin, the "Manager".  If you have class "Xyz", you'll see the "XyzManager".

What does it do?  Manage, of course!  That's not ambiguous at all!  Need persistence?  Go to the Manager.  Need to attach behavior to "Xyz"?  That's what the "XyzManager" is for!

The Manager knows all, sees all, and provides a dumping ground for any behavior that just so happens to touch the related Xyz class.  Personally, the Manager was my intermediate anti-pattern before understanding true separation of concerns.

# July 17, 2007 11:24 AM

Luke Foust said:

I find this topic very interesting and think it would be very helpful if you could do another post (or series of posts) with concrete code examples.

I usually have some sort of Util classes in most projects I work on. In fact, many open source projects I study have at least some form of the Util classes. For example, what are your thoughts on things like the Subsonic projects "Sugar" utilities?

blog.wekeroad.com/.../subsonic-sugary-sticky-stuff.aspx

I think many developers (including myself) can recognize the code smell that comes from these utility classes but are not sure exactly how to make better abstractions for things like StringHelper.Chop()

# July 17, 2007 11:49 AM

Karthik said:

Great post, Jeff.  I've also thought recently as I get more into DDD that Utility classes tend to break the model quite a bit.  Your method of using interfaces to support that Utility functionality sounds intriguing.

# July 17, 2007 12:15 PM

Joe said:

Are you two related?

# July 17, 2007 12:31 PM

Joe said:

@Jimmy

Evans' book touches on this -- those "Managers" end up being Services, and often part of the application or infrastructure layer outside of the problem domain.

# July 17, 2007 1:04 PM

Michael Feathers said:

I don't like Util classes much, but people continue to make them.  

The one thing I wish, though, is that they would stop making methods on Util classes static.  If you ever want to test code that uses static utility methods and those methods do something you wouldn't like to see happen in a test, you have to work around it, and it's a pain.

# July 17, 2007 5:01 PM

Jeffrey Palermo said:

@Michael,

Yes.  The static part leaves no room for a seam.  Especially if the static utility method expect a certain file to read from the file system.  Now that's something extra to set up just to run an integration test.  At lest  an instance of Utility leaves room to "inherit and override" to stub out that method.

# July 17, 2007 5:07 PM

Tristian Barrett said:

Yeah I've got quite a few utility or helper classes, but they are all pretty much to cover gaps in provided types. StringUtil, ArrayListUtil, FormUtil, etc.

One of the things I like about ruby is that if you do find something missing in one of the core classes its simple just to add to it yourself. In c# the only real way around it is a helper class. Inheritance isn't a viable answer when dealing with basic types.

# July 17, 2007 8:26 PM

Christopher Steen said:

Materials from "Using Behaviors to Flex Your WCF Muscles" posted [Via: tom.fuller ] MSDN Nuggets and...

# July 18, 2007 1:16 AM

Josh said:

I see it as step one. Eventually your Util class becomes bloated or you have uses for certain represented domains and not others on another project. At this point refactor.

Recognizing when it is approaching unmaintainability or causing slow down in development is when it becomes evil.

# July 18, 2007 8:50 AM

KBac said:

It is great to get this subject under scrutiny. I have noticed that utilities are the next evil indeed if handled badly.

Normally you write your code and have a few methods you want to share -> utilities are born. Then you refactor your code and notice that over time you have created even more methods worth sharing -> the questions start appearing. If you keep adding to the utilities you might cause them to bloat (I have seen projects with utilities grown to over 40% of the total project size). If the functionality is not general enough you have potential to create a highly coupled blob...

It is great to hear the suggestion to couple utilities' development to principles facilitating proper class design and layering. How about changing the mindset from common utilities developer to a developer of public API? - as this would stress the need for different quality and concerns.

# July 19, 2007 5:17 AM

Jeremy D. Miller -- The Shade Tree Developer said:

I'm awful at returning emails. It was even one of my new year's resolutions to reply to emails

# July 22, 2007 5:57 PM

About Jeffrey Palermo

Jeffrey Palermo is a software management consultant and the CTO of Headspring Systems in Austin, TX. Jeffrey specializes in Agile coaching and helps companies double the productivity of software teams. Jeffrey is an MCSD.Net , Microsoft MVP, Certified Scrummaster, Austin .Net User Group leader, AgileAustin board member, INETA speaker, INETA Membership Mentor, Christian, husband, father, motorcyclist, Eagle Scout, U.S. Army Veteran, and Texas A&M University graduate. Check out Devlicio.us!

This Blog

Syndication