Tuesday, July 4, 2017

The Ultimate Oldschool PC Font Pack

The Ultimate Oldschool PC Font Pack is a collection of Creative Commons Attribution-ShareAlike 4.0 International License fonts that cover quite a huge selection of the original hardware PC fonts. No wonder it's the ultimate!

They could be useful in terminals or IDEs, I'm sure, but I could also see this used in some sort of video game where the classic look-and-feel is desired.

Monday, February 20, 2017

Static Methods vs. Constructors

Recently I had a discussion with a colleague about static factory methods vs. constructors. Specifically, this was about using static factory methods or constructors to convert from one type of object into another type. I argued that, if given the choice, constructors should rarely be used for converting from one type to another, and in fact, having many constructors is usually the least desirable of several different strategies of obtaining an object instance. I will only discuss one of those strategies here, which is the previously mentioned static factory method.

I won't start with why static factory methods are good and when they should be used. Instead I'll start with the list of negatives about static factory methods that my friend provided, and discuss them one-by-one:
  • Static factory methods do not fall into the constructor area of the JavaDoc therefore a user must read down the doc or code to find a method that constructs the class.
  • A constructor is allowed to set variables directly at construction time. During this time if an overridable (non-final) method is used it will generate a warning.
  • None of the restrictions or benefits of constructors are available.
  • It is less efficient. It requires the memory for a static method but saves no time. A new class must still be constructed, and then extra steps are required to set each class variable. Assuming there are any optimizations for construction we get none of them.
  • There is no way to enforce immutability.
  • The calling method will not have the new keyword visible: Thing a = fromSomeOtherThing(SomeOtherThing sot)

Static factory methods do not fall into the constructor area of the JavaDoc therefore a user must read down the doc or code to find a method that constructs the class

No disagreements there. I vaguely remember encountering this multiple times when starting out with Java, like with Calendar. I couldn't see how to create a Calendar easily, because when I used new Calendar() it was abstract and I'd need to fill in methods to make it work. Then I found out that I should use Calendar.getInstance(). Pretty easy after that, and as a bonus I didn't even need to know if what it created was a GregorianCalendar or something even more spiffy.
So yes, it is "hidden", but this happens so much in Java (for valid reasons) that it'll only trip up novices. Or, the class is so HUGE that it is buried in the JavaDoc or in the IDE autocomplete list. In that case, the class has other problems.

[Update: I saw some code from a different colleague who, instead of using Calendar.getInstance(), created a new GregorianCalendar. So there may be more to this point than I initally gave credit. Also: if you're coding in Java and the project allows it, stop using Date and Calendar and switch to the new date and time methods provided in Java 8, or use the JSR-310 backport if you're still stuck in Java 7 for whatever legitimate, but still lame, reason.]


A constructor is allowed to set variables directly at construction time. During this time if an overridable (non-final) method is used it will generate a warning.

But we can set fields with other methods, provided the field isn't final. And even if the field is final we can still modify it, providing the field isn't one of the primitives (int, double, boolean, etc) and the field's class provides setters. In Java, the only thing that final provides you as a field modifier is that it prevents you from pointing that field to a different object in a different memory location. (Yes, this means that just because a class's fields are all marked private final doesn't mean the class is truly immutable. You must also look at the type of each field: those too much also be all primitives or immutable classes (and are immutable all the way down). Only then is it considered immutable.)

The issue with why it is unsafe to call a non-final setter method from a constructor is because if the child class overrides the setter, then the parent class's variable might not get set if the overridden setter doesn't call super.setX() too.

The straightforward answer may be "then don't use setters in the ctor, set the values directly", but that is pretty tedious if the setter had some complex logic in it: that complex logic would need to be repeated in the ctor too, and if you change one, you'd need to remember to change the other. Thankfully, the solution is straightforward enough without resorting to copypasted code: put the complex logic into a private setXInternal(...) and have the ctor and the setter call into that. Granted, we can only do this if we still want the class to be mutable. If the class, or that field specifically, is to be immutable, then there's no choice but to use a constructor... but this can still be worked around somewhat. I'll explain later.


None of the restrictions or benefits of constructors are available

I'm not entirely sure what my friend was getting at here. We can still have the static factory method call the constructor if we wanted and get all them tasty restrictions and benefits. The thing is, sometimes we don't need the restrictions that a constructor has. With a static factory method, we could even return null to indicate a failure state (which I wouldn't advise doing, but this option is still available to those that want it).If the class was abstract, we could even implement the missing part we need, which the caller might actually like if they don't care what exact implementation of the class they get, as long as it adheres to the interface. This has a name of "static factory method" and it is widely used in the OO space, and it is beautiful. Admittedly, it can get overused if every class does this; simple constructors for simple classes are good enough.
I'm breaking the next one apart because it is several items:
it is a less efficient[sic].
In the basic case, yes, it is less efficient because instead of one call to make an object, it now requires two. But it can be more efficient, which I'll explain later.


It is less efficient. It requires the memory for a static method but saves no time. A new class must still be constructed, and then extra steps are required to set each class variable. Assuming there are any optimizations for construction we get none of them.

Okay, so the classloader part of memory has one extra method to store, which isn't a big deal. It consumes the same amount of memory whether there is one object instance in memory, or 5000. In other words, the memory load per object is zero.
As for saving time, true, in the basic case it saves no time because it is calling a constructor, which the caller could do directly. But it can be faster than constructors. I promise I'll answer this shortly!
A new class must still be constructed, and then an extra steps are required to set each class variable. Assuming there is any optimization for construction we get none of it.
Again, in the basic case, a new class must still be constructed. But since this static method is part of the class code, we could directly set the values if we wanted, but might as well use a constructor at that point anyway.
As for optimization for construction: because we're using setters here, and because I'm not privy to how "optimizy" the HotSpot VM will make a frequently called operation, I will agree that we lose out on the optimization because I have no idea what it would do.


There is no way to enforce immutability

True dat! It's the constructor's bread and butter. But we'll get back to immutability in a little bit, because believe it or not, that is where static factory methods can have the most benefit.

The calling method will not have the new keyword visible: Thing a = fromSomeOtherThing(SomeOtherThing sot)

I think the claim here is that...
Thing a = new Thing(sot);
...is a more beneficial, visible cue to the reader that we have a new object, and...
Thing a = fromSomeOtherThing(sot);
...is not as good of a cue. This is an issue of preference. My preference: if the class is simple, and there aren't any objects we'd like to convert into this class, then use a constructor. If we're converting from another class, I prefer that a static factory method is used for the conversion, because we can read right there what we're converting from, and what we get.


The counterpoints...

Constructors can't have different names for one class, which might look funny if they all must do different things in order to return the instance.
 
Sure, you won't have any problem with your constructors if you only need to pass in different complex objects. You won't have any problem with these constructors:

public MutantAnimal(Dog dog) {
     // make a mutant animal from a dog input
}
public MutantAnimal(Cat cat) {
    // make a mutant animal from a cat input
}

But what if you need to take in animals from different serialized data, like this:

// Won't compile (and bad for other reasons anyway)
public MutantAnimal(String xml) {...}
public MutantAnimal{String json) {...} // ERROR!

Can't do it. If we MUST do this only with constructors, and not static factory methods, we can pull this ugly trick:

// Ugly and not recommended, but doable
// Handles both xml and json! Yay?
public MutantAnimal(String text, boolean isXml) {
    if (isXml) {...}
    else {...}
}

Gross. What if we want to handle yaml too? We could use an enum instead:

// Still ugly, still not recommended, but doable
public MutantAnimal(String text, SerializedType type) {...}
 
Yep, still gross. Perhaps instead we could make it a single public SomeClass(String text), and then have it cascade the attempts to convert it from xml, then json, then yaml. So inefficient! Even uglier!

If we give up on the "everything is better as a constructor" idea and use static methods that know how to do the conversion for us, things become much more simple and straightforward:

// Better than the previous examples

public static MutantAnimal fromXml(String xml) {...}
public static MutantAnimal fromYaml(String yaml) {...}
public static MutantAnimal fromJson(String json) {...}
 
It is so much easier to read, and more efficient. Another benefit of these static methods is that we don't have to keep it with the class. We could move it out to a utility class somewhere if we wanted.
 
Notes: Before anyone goes off and creates their own fromXml/Yaml/Json methods, you should know that I created these as a simple example of how constructors can fail you if you want multiple constructors but one or more have the same parameter list. I wouldn't recommend anybody create these from... methods. Instead, go find a nice library like Jackson and use the features it comes with in order to create your object.

Static factory methods don't have to consume more memory, but a constructor always does


One of the nice things (YES, it is nice) about using a static method to return an instance is that it could hand back an already created instance. This is something that constructors simply can't do. The best that a constructor can do is create a lightweight wrapper that wraps around a previously created massive object, but this is still consuming the tiny amount of memory for that wrapper.

There's all sorts of reasons we might want to hand back a previously created object rather than always returning a brand new object each time, but the biggest benefits can be:
  • speed, because we aren't wasting time allocating memory and then eventually GC'ing it, and
  • less memory consumption.
Caching previously created objects like this are great when you have a few large immutable objects you need to use all the time, or lots and lots of tiny immutable objects.

"But wait! What if we wanted a mutable object instead? If you hand back a mutable object, then who knows if another thread is using it too! You could have race conditions!" Yep, don't do it. In that case, always hand back a new instance, or use some other fancy tricks I won't go into here.

Using constructors as the only means of creating an immutable object becomes tedious and confusing if the class has many fields

When it comes to those immutable objects, the constructors can get pretty gnarly sometimes, because if the field isn't initialized where it is declared, then the constructor has to assign a value to the field, otherwise the code will fail to compile. For example:

public class MutantAnimal {
    private final int numArms;
    private final int numLegs;
    private final Species originalSpecies;
    ...more fields...

    public MutantAnimal(int arms, int legs, Species species, ...params for other fields) {
        numArms = arms;
        numLegs = legs;
        originalSpecies = species;
        ...other assignments...
    }
}

Studies have shown that it is difficult for the average person to keep more than seven items in their head at any one time. The same goes for programmers and params. If you've tried calling a method with more than seven params, you know it isn't the most straightforward, even with the help of an IDE.

I bring this up because, for immutable objects, if all you allow to create that object are constructors, including that massive constructor, then other programmers using your code will not be pleased. You're closing off the potential for so many other ways to make it easier to build this class, including, but not limited to, static factory methods.

Another pattern we can use to reduce the number of params, and is actually my favorite for this scenario of creating a largish immutable object, is the builder pattern, but that's outside of the scope of this discussion.

And yes, there are even patterns available which can reduce the number of params you'd need to pass to the constructor, it depends on the situation. But why restrict ourselves to those patterns only, all so that we can keep using a constructor?

In fact, now that we have these other, easier ways of creating these large immutable classes, we don't even need to publicly expose that lengthy constructor at all! We could make it private, and force the creation of the class to only go through our static methods or our builders, which in turn would do the heavy lifting of calling the aforementioned private constructor. But we can leave the constructor public too if we like.


Using static factory methods to create or convert, instead of constructors, is more common than you think, and is already used in Java
 
There are several examples of this in the Java language already. Calendar.newInstance() is one. A better example is Long Long.valueOf(long value). I like using Long, Integer, Boolean, and the other boxed primitives here because they have several static method converters (and the constructor is still available). Long (and others) do exactly what I described in the previous points:
  • Long is immutable
  • Java has a LongCache which stores precreated versions of Long between -128 and 127, inclusively
  • If the client calls Long.valueOf(10), then a new Long isn't created, a previously created one is handed back.
  • If the client calls Long.valueOf(1000), then in that case, a new Long is always created.
  • If the client calls new Long(10), then a new Long is always created, there is no way around it.
And this is why Long.valueOf(long) should be used instead of new Long(long). It is faster and takes less memory for the most commonly used values of between -128 and 127. In fact, we don't even use Long.valueOf(long) anymore, we use Long x = 10L and the compiler will autobox it to be Long x = Long.valueOf(10L) for us!


Static factory methods are recommended over constructors by Java experts

Effective Java, 2nd ed, Joshua Bloch, Item 1: "Consider static factories instead of constructors"
Yes, I know it isn't a valid argument to say "But these 'smart' people are doing it, we should too" because the answer, invariably, is "If they all jumped off a bridge, would you follow?" Well done. Check mate. Slow golf clap.
But, it wouldn't hurt to find out the reason behind why they're all jumping off of said bridge:
  • A fire is consuming the bridge from both sides, the only escape is by water that is only 20 feet down, oh no!
  • They're all taking turns jumping off, and it turns out they had a device called a "bungee cord" attached so that they wouldn't plummet to their death.
  • Turns out some weird cosmic radiation made everybody invincible, and you and everybody else has jumped off of even more dangerous bridges with no harm.
  • Fill in your own reason, it's fun!
So yes, just because an expert said it, it doesn't mean you should blindly follow it, but it doesn't mean he is immediately wrong either.

Summary

Constructors have their use, but don't go overboard with them. Use static factory methods instead, where possible, and consider other patterns to pure constructors.