4

I was reading on this software engineering page about the use of static methods. However, I'm confused, and maybe it's about the context in which it talks about static. The idea is, that static is really bad for testing and shouldn't be used.

When creating immutable class, sometimes the constructor is private and a static factory is used to create the object. Even Java's own documentation supports the use of a factory when creating immutable objects.

A more sophisticated approach is to make the constructor private and construct instances in factory methods

2
  • 2
    Beware dogmatism.
    – jpmc26
    Commented Oct 23, 2017 at 11:08
  • You should probably edit this and make the question more explicit - while I am pretty sure I know what you are asking here, it is somewhat unclear. Commented Oct 23, 2017 at 11:42

3 Answers 3

3

If you are making an immutable DTO, where you simply bundle up a bunch of properties and that's it, such as your example, then just use a public constructor.

Factories are for situations where object construction is complicated, expensive, where you return different types based on the input values, or other "logic intensive" situations. Simply storing a handful of values is not one of those situations.

2
  • See my edit, I think "where you return different types based on the input values" is what I do in my example.
    – user286462
    Commented Oct 23, 2017 at 1:34
  • 1
    @S.R.: that's not what I'm seeing. I don't see anything besides "Weapon" being returned. Commented Oct 23, 2017 at 4:23
2

The idea is, that static is really bad for testing and shouldn't be used.

Yes static code makes unit testing harder (sometime impossible). But I would not go as far as saying static should not be used. There are some cases where static methods are fine to use.

Here is why it makes testing harder. Consider this code you have in your question:

public static Weapon Sword(String name, damage){
    return new Weapon(name, damages);
}

Wherever that code is written is permanently coupled to Weapon. Without the Weapon class, no one can compile the above code. No one can substitute a mock object instead of Weapon to test the class where this code appears.

The easiest rule to remember is that as soon as you you use new keyword to instantiate an object of class X, you have made your class coupled to X and unit testing will be not be possible unless you were to change the code in class X (but that would be a very odd unit test because you would need to change the code in class X back to the real code before sending it to production). Please read more here about unit testing static code.

15
  • Would it then be better then to make the constructor public and use that for creating objects? In my case make the weapon constructor public?
    – user286462
    Commented Oct 22, 2017 at 23:48
  • @S.R. no that would not be better. You can leave it as is but if you are interested in why static code is harder to unit test then read the article I referred in my answer. Then try to unit test your code and you will run into obstacles and you will then clearly understand why static code is harder to test. It is really hard to explain this without a lengthy article or discussion. Also, if someone does not fully understand unit testing and mocking, then it further complicates the explanation. Is there a specific part you do not understand and perhaps I can try and explain that part? Commented Oct 22, 2017 at 23:56
  • I'm still learning, so for you to explain, is going take some time and go beyond the scope of the question. For example, If I wanted to keep weapon immutable, but have different types, so sword and gun, I could still keep the constructor private and use a static factory to return those types, correct?
    – user286462
    Commented Oct 23, 2017 at 1:31
  • 3
    @S.R. You do not need a factory to create immutable objects. I suggest you throw away the factory and only use it if you ever need it. Using design patterns can (often it does) complicate your code. Only use it if you have a need. I honestly do not think you need it in this case. Please do a quick read of Factory design pattern. Commented Oct 23, 2017 at 1:46
  • 1
    @S.R., well you can't. But a slightly different question, "how would you supply an object without new?", then the answer would be, eg use an object pool, or with C# for example, you could use stack based structs to avoid hitting the heap. But as I said previously, that's all pointless pendanticism, so just ignore what I said ;)
    – David Arno
    Commented Oct 23, 2017 at 15:43
1

The idea that static instances (or static functions that have some state associated with them) are bad comes from the argument that says that having those is the same as having global variables (global state - see this for more info on why that's bad).

A constructor is just a special kind of function - it's not something that manipulates global state in this sense. You don't need to have a reference to an instance to call it (even in prototype-based languages), so in a way, you can think of it as being static, or behaving as if it's static. From that point of view, having a static factory method is no different. So the global state argument doesn't apply here.

5
  • So, it's fine to use a static method as a way of creating and returning an immutable object? As stated in the JavaDocs
    – user286462
    Commented Oct 23, 2017 at 13:01
  • IMO - yes. As far as I'm aware, it's a relatively common thing to do. Also, there's an advantage of being able to give a more meaningful name to your static factory method (or methods). Now, as the JavaDocs say, this is one way to prevent inheritance, and it's one that generalizes fairly well to other languages. I wouldn't necessarily agree that it's "a more sophisticated approach" compared to marking the class final (or sealed, the C# equivalent). Commented Oct 23, 2017 at 13:21
  • @S.R.: no, it's not fine. It'll compile and execute, but it violates the Principle of least astonishment. If you want to create an object, you should normally use new. Commented Oct 23, 2017 at 14:40
  • @S.R. (C.C. @whatsisname): For the record, I actually agree with whatsisname when it comes to when you should use constructors vs factory methods (Principle of least astonishment). My answer and my previous comment were made under the assumption that you are asking specifically if the reasoning behind the advice to avoid static (global) methods/state applies to static factory methods, as I get the impression that you are looking to understand the "why" behind it all. Commented Oct 23, 2017 at 15:39
  • @FilipMilovanović - You read my question, I meant with regards to static factory methods. I wanted to know the why
    – user286462
    Commented Oct 23, 2017 at 15:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.