Class with single method -- best approach?

92,121

Solution 1

I used to love utility classes filled up with static methods. They made a great consolidation of helper methods that would otherwise lie around causing redundancy and maintenance hell. They're very easy to use, no instantiation, no disposal, just fire'n'forget. I guess this was my first unwitting attempt at creating a service oriented architecture - lots of stateless services that just did their job and nothing else. As a system grows however, dragons be coming.

Polymorphism
Say we have the method UtilityClass.SomeMethod that happily buzzes along. Suddenly we need to change the functionality slightly. Most of the functionality is the same, but we have to change a couple of parts nonetheless. Had it not been a static method, we could make a derivate class and change the method contents as needed. As it's a static method, we can't. Sure, if we just need to add functionality either before or after the old method, we can create a new class and call the old one inside of it - but that's just gross.

Interface woes
Static methods cannot be defined through interfaces for logic reasons. And since we can't override static methods, static classes are useless when we need to pass them around by their interface. This renders us unable to use static classes as part of a strategy pattern. We might patch some issues up by passing delegates instead of interfaces.

Testing
This basically goes hand in hand with the interface woes mentioned above. As our ability of interchanging implementations is very limited, we'll also have trouble replacing production code with test code. Again, we can wrap them up but it'll require us to change large parts of our code just to be able to accept wrappers instead of the actual objects.

Fosters blobs
As static methods are usually used as utility methods and utility methods usually will have different purposes, we'll quickly end up with a large class filled up with non-coherent functionality - ideally, each class should have a single purpose within the system. I'd much rather have a five times the classes as long as their purposes are well defined.

Parameter creep
To begin with, that little cute and innocent static method might take a single parameter. As functionality grows, a couple of new parameters are added. Soon further parameters are added that are optional, so we create overloads of the method (or just add default values, in languages that support them). Before long, we have a method that takes 10 parameters. Only the first three are really required, parameters 4-7 are optional. But if parameter 6 is specified, 7-9 are required to be filled in as well... Had we created a class with the single purpose of doing what this static method did, we could solve this by taking in the required parameters in the constructor, and allowing the user to set optional values through properties, or methods to set multiple interdependent values at the same time. Also, if a method has grown to this amount of complexity, it most likely needs to be in its own class anyways.

Demanding consumers to create an instance of classes for no reason
One of the most common arguments is, why demand that consumers of our class create an instance for invoking this single method, while having no use for the instance afterwards? Creating an instance of a class is a very very cheap operation in most languages, so speed is not an issue. Adding an extra line of code to the consumer is a low cost for laying the foundation of a much more maintainable solution in the future. And finally, if you want to avoid creating instances, simply create a singleton wrapper of your class that allows for easy reuse - although this does make the requirement that your class is stateless. If it's not stateless, you can still create static wrapper methods that handle everything, while still giving you all the benefits in the long run. Finally, you could also make a class that hides the instantiation as if it was a singleton: MyWrapper.Instance is a property that just returns new MyClass();

Only a Sith deals in absolutes
Of course, there are exceptions to my dislike of static methods. True utility classes that do not pose any risk to bloat are excellent cases for static methods - System.Convert as an example. If your project is a one-off with no requirements for future maintenance, the overall architecture really isn't very important - static or non static, doesn't really matter - development speed does, however.

Standards, standards, standards!
Using instance methods does not inhibit you from also using static methods, and vice versa. As long as there's reasoning behind the differentiation and it's standardised. There's nothing worse than looking over a business layer sprawling with different implementation methods.

Solution 2

I prefer the static way. Since the Class is not representing an object it doesn't make sense to make an instance of it.

Classes that only exist for their methods should be left static.

Solution 3

If there is no reason to have an instance of the class created in order to execute the function then use the static implementation. Why make the consumers of this class create an instance when one is not needed.

Solution 4

If you don't need to save the state of the object, then there's no need to instantiate it in the first place. I'd go with the single static method that you pass parameters to.

I'd also warn against a giant Utils class that has dozens of unrelated static methods. This can get disorganized and unwieldy in a hurry. It's better to have many classes, each with few, related methods.

Solution 5

I would say the Static Method format would be the better option. And I would make the class static as well, that way you wouldn't have to worry about accidentally creating an instance of the class.

Share:
92,121

Related videos on Youtube

JW.
Author by

JW.

Updated on May 15, 2020

Comments

  • JW.
    JW. about 4 years

    Say I have a class that's meant to perform a single function. After performing the function, it can be destroyed. Is there any reason to prefer one of these approaches?

    // Initialize arguments in constructor
    MyClass myObject = new MyClass(arg1, arg2, arg3);
    myObject.myMethod();
    
    // Pass arguments to method
    MyClass myObject = new MyClass();
    myObject.myMethod(arg1, arg2, arg3);
    
    // Pass arguments to static method
    MyClass.myMethod(arg1, arg2, arg3);
    

    I was being intentionally vague about the details, to try to get guidelines for different situations. But I didn't really have in mind simple library functions like Math.random(). I'm thinking more of classes that perform some specific, complex task, but only require one (public) method to do it.

  • Paul Tomblin
    Paul Tomblin over 15 years
    I somewhat disagree. In projects I'm involved with, your Utilities class could have hundreds of unrelated methods in it.
  • John Rudy
    John Rudy over 15 years
    @Paul: Generally agreed. I hate to see classes with dozens (or yes, hundreds) of totally unrelated methods. If one must take this approach, at least split these into smaller, related sets of utilities (EG, FooUtilities, BarUtilities, etc).
  • Bill the Lizard
    Bill the Lizard over 15 years
    What if you need to return anything besides an object of type MyClass?
  • Martin Schulz
    Martin Schulz over 15 years
    I consider it bad practice to put execution logic in a constructor. Good development is about semantics. Semantically, a constructor exists to construct an object, not to perform other tasks.
  • Andreas Petersson
    Andreas Petersson over 15 years
    one class- one resposibility.
  • Admin
    Admin over 15 years
    bill, if you need return value, pass reference to the ret vvalue: MyClass myObject(arg1, arg2, arg3,retvalue); mstrobl,if the object is not needed, why create it? and this trick can actualy help you in some instances.
  • Martin Schulz
    Martin Schulz over 15 years
    If an object has no state, i.e. no vars, then instancing it will not produce any allocation - neither on heap nor stack. You can think of objects in C++ as just C function calls with a hidden first parameter pointing to a struct.
  • Admin
    Admin over 15 years
    mstrobl, it like a c function on steroids because you can define private functions that the ctor can use. you can also use the class member variables to help pass data to the private functions.
  • Martin Schulz
    Martin Schulz over 15 years
    Your argument was that if you would not need an object, "why create it". As you are talking of state, you are talking of needing an object. Using a constructor for anything other than constructing is a hack imho. Think functors. If you need to use an object implicitly, do so: MyClass().foo()
  • Rookian
    Rookian almost 13 years
    -1 "Classes that only exist for their methods should be left static."
  • jjnguy
    jjnguy almost 13 years
    @Rookian why do you disagree with that?
  • Rookian
    Rookian almost 13 years
    an example would be the repository pattern. The class contains only methods. Following your approach does not allow to use interfaces. => increase coupling
  • jjnguy
    jjnguy almost 13 years
    @Rook, in general people shouldn't be creating classes that are used just for methods. In the example you gave static methods aren't a good idea. But for simple utility methods the static way is best.
  • Rookian
    Rookian almost 13 years
    Absolutely correct :) With your conditon "for simple utility methods" I agree with you completely, but you did make a general rule in your answer which is wrong imo.
  • Thomas W
    Thomas W about 11 years
    As Mark says, polymorphism, being able to pass the methods as 'strategy' parameters, and being able to configure/ set options are all reasons to use an instance. For example: a ListDelimiter or DelimiterParser could be configured as to what delimiters to use/accept, whether to trim whitespace from the parsed tokens, whether to bracket the list, how to treat a blank/ null list.. etc.
  • Rodney Gitzel
    Rodney Gitzel over 10 years
    "As a system grows..." you refactor?
  • Ela782
    Ela782 about 10 years
    I don't know about C# and Java, but in C++ you could also declare a free function, which is as a matter of fact often preferable. This is a good read: gotw.ca/publications/mill02.htm
  • OneHoopyFrood
    OneHoopyFrood over 9 years
    @Ela782, Just thought I'd mention that C# and Java are pure O.O. languages and thus do not have free functions. Thus the need for static methods.
  • Ela782
    Ela782 over 9 years
    @colepanike Oh, thank you for refreshing my knowledge on that. It's been a long time since I last programmed in Java.
  • Anestis Kivranoglou
    Anestis Kivranoglou almost 9 years
    "Since the Class is not representing an object it doesn't make sense to make an instance of it." One case i would disagree with that, is when a general helper method which is going to be used multiple times(on the same thread) needs a Database connection, it does make sense to keep an instance of the class with a reference to the connection , if you don't want to create new connections all the time, or litter your method parameters injecting the connection reference.
  • user3667089
    user3667089 over 8 years
    @Mark S. Rasmussen Great post. Would you pass arguments to method or initialize arguments in constructor?
  • Mark S. Rasmussen
    Mark S. Rasmussen over 8 years
    @user3667089 General arguments that are needed for the class to exist logically, those I would pass in the constructor. These would typically be used in most/all methods. Method specific arguments I'd pass in that specific method.
  • user3667089
    user3667089 over 8 years
    @MarkS.Rasmussen Just to clarify, in the case of a class with a single method, you will pass it in as a constructor because it is used for all (that single one) method?
  • Engineer
    Engineer over 8 years
    Really what you're doing with a static class is going back to raw, non-object-oriented C (albeit memory-managed) - all functions are in a global space, there is no this, you have to manage global state etc. So if you like procedural programming, do this. But appreciate that you then lose many of the structural benefits of OO.
  • Justin J Stark
    Justin J Stark almost 5 years
    Most of these reasons have to do with bad code management, not from using static methods. In F# and other functional languages we use what are basically static methods (functions with no instance-state) everywhere and don't have these problems. That said, F# provides a better paradigm for using functions (functions are first class, functions can be curried and partially applied) which makes them more feasible than in C#. A bigger reason to use classes is because that's what C# is built for. All of the Dependency Injection constructs in .NET Core revolve around instance classes with deps.
  • fernacolo
    fernacolo over 4 years
    This answer violates KISS and YAGNI principles. Today, with abundant availability of automated refactoring tools in IDEs, we should stick to simplicity and keep static until polymorphism, mocks, etc are actually needed.
  • don
    don about 4 years
    Can someone provide a TLDR version of this response? I have read this answer several times and I think it touches on a number of issues but it is meandering and a bit unclear to me. Can someone rephrase this like jinguy's answer. I thought jinguy's answer was concise and a good explanation of his rationale. This doesn't seem to address the 3 methods and the pros and cons in a clear way