Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Naming convention and structure for utility classes and methods

Do you have any input on how to organize and name utility classes?

Whenever I run in to some code-duplication, could be just a couple of code lines, I move them to a utility class.

After a while, I tend to get a lot of small static classes, usually with only one method, which I usualy put in a utility namespace that gets bloated with classes.

Examples:

ParseCommaSeparatedIntegersFromString( string ) CreateCommaSeparatedStringFromIntegers( int[] ) CleanHtmlTags( string ) GetListOfIdsFromCollectionOfX( CollectionX ) CompressByteData( byte[] ) 

Usually, naming conventions tell you to name your class as a Noun. I often end up with a lot of classes like HtmlHelper, CompressHelper but they aren't very informative. I've also tried being really specific like HtmlTagCleaner, which usualy ends up with one class per utility method.

Have you any ideas on how to name and group these helper methods?

like image 532
Bjorn Avatar asked Aug 13 '09 10:08

Bjorn


People also ask

What should be the naming convention for methods?

Methods should be verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized. Except for variables, all instance, class, and class constants are in mixed case with a lowercase first letter. Internal words start with capital letters.

What type of methods are used by a utility class?

Utility Class, also known as Helper class, is a class, which contains just static methods, it is stateless and cannot be instantiated. It contains a bunch of related methods, so they can be reused across the application. As an example consider Apache StringUtils, CollectionUtils or java. lang.

What is naming convention and example?

What Does Naming Convention Mean? Naming conventions are general rules applied when creating text scripts for software programming. They have many different purposes, such as adding clarity and uniformity to scripts, readability for third-party applications, and functionality in certain languages and applications.


2 Answers

I believe there is a continuum of complexity, therefore corresponding organizations. Examples follow, choose depending of the complexity of your project and your utilities, and adapt to other constraints :

  1. One class (called Helper), with a few methods
  2. One package (called helper), with a few classes (called XXXHelper), each class with a few methods. Alternatively, the classes may be split in several non-helper packages if they fit.
  3. One project (called helper), with a few packages (called XXX), each package with ... Alternatively, the packages can be split in several non-helper packages if they fit.
  4. Several helper projects (split by tier, by library in use or otherwise)...

At each grouping level (package, class) :

  • the common part of the meaning is the name of the grouping name
  • inner codes don't need that meaning anymore (so their name is shorter, more focused, and doesn't need abbreviations, it uses full names).

For projects, I usually repeat the common meaning in a superpackage name. Although not my prefered choice in theory, I don't see in my IDE (Eclipse) from which project a class is imported, so I need the information repeated. The project is actually only used as :

  • a shipping unit : some deliverables or products will have the jar, those that don't need it won't),
  • to express dependencies : for example, a business project have no dependency on web tier helpers ; having expressed that in projects dependencies, we made an improvement in apparent complexity, good for us ; or finding such a dependency, we know something is wrong, and start to investigate... ; also, by reducing the dependencies, we may accelerate compilation and building ....
  • to categorize the code, to find it faster : only when it's huge, I'm talking about thousands of classes in the project

Please note that all the above applies to dynamic methods as well, not only static ones. It's actually our good practices for all our code.


Now that I tried to answer your question (although in a broad way), let me add another thought
(I know you didn't ask for that).

Static methods (except those using static class members) work without context, all data have to be passed as parameters. We all know that, in OO code, this is not the preferred way. In theory, we should look for the object most relevant to the method, and move that method on that object. Remember that code sharing doesn't have to be static, it only has to be public (or otherwise visible).

Examples of where to move a static method :

  1. If there is only one parameter, to that parameter.
  2. If there are several parameters, choose between moving the method on :
    • the parameter that is used most : the one with several fields or methods used, or used by conditionals (ideally, some conditionnals would be removed by subclasses overriding) ...
    • one existing object that has already good access to several of the parameters.
    • build a new class for that need

Although this method moving may seem for OO-purist, we find this actually helps us in the long run (and it proves invaluable when we want to subclass it, to alter an algorithm). Eclipse moves a method in less than a minute (with all verifications), and we gain so much more than a minute when we look for some code, or when we don't code again a method that was coded already.

Limitations : some classes can't be extended, usually because they are out of control (JDK, libraries ...). I believe this is the real helper justification, when you need to put a method on a class that you can't change.

Our good practice then is to name the helper with the name of the class to extend, with Helper suffix. (StringHelper, DateHelper). This close matching between the class where we would like the code to be and the Helper helps us find those method in a few seconds, even without knowledge if someone else in our project wrote that method or not.

like image 90
KLE Avatar answered Oct 20 '22 12:10

KLE


Helper suffix is a good convention, since it is used in other languages (at least in Java, IIRC rails use it).

The intent of your helper should be transported by the method name, and use the class only as placeholder. For example ParseCommaSeparatedIntegersFromString is a bad name for a couple of reasons:

  • too long, really
  • it is redundant, in a statically typed language you can remove FromString suffix since it is deduced from signature

What do you think about:

CSVHelper.parse(String) CSVHelper.create(int[]) HTMLHelper.clean(String) ...    
like image 28
dfa Avatar answered Oct 20 '22 11:10

dfa