1

there are two questions with microstream database and its class StorageConfiguration:

1) What ist the difference of the methods New() and Builder() and the DEFAULT construct?

2) Why the methods are writting uppercased? That does not seem to be Java naming convention.

Thanks for any answers!

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Christian
  • 576
  • 1
  • 4
  • 16

1 Answers1

1

I am the MicroStream lead developer and I can gladly answer those questions.

To 1)

"New" is a "static factory method" for the type itself.
"Builder" is a static factory method for a "builder" instance of the type.

Both terms can be perfectly googled for more information about them.
A quick service as a starting point:

"static factory method": https://www.baeldung.com/java-constructors-vs-static-factory-methods

"builder pattern": https://en.wikipedia.org/wiki/Builder_pattern

--

To your actually second question, about the "DEFAULT" construct:

If I may, there is no "DEFAULT" construct, but "Default".
(Conventions are important ... mostly. See below.)

"Default" is simply the default implementation (= class) of the interface StorageConfiguration.
Building a software architecture directly in classes quickly turns out to be too rigid and thus bad design. Referencing and instantiating classes directly creates a lot of hardcoded dependencies to one single implementation that can't be changed or made more flexible later on. Inheritance is actually only very rarely flexible enough to be a solution for arising architecture flexibility problems. Interfaces, on the other hand, only define a type and the actual class implementing it hardly matters and can even be easily interchangeable. For example, by only designing via interfaces, every instance can easily be "wrapped" by any desired logic via using the decorator pattern. E.g. adding a logging aspect to a type.

There is a good article with an anecdote about James Gosling (the inventor of Java) named "Why extends is evil" that describes this:
https://www.javaworld.com/article/2073649/why-extends-is-evil.html

So:
"Default" is just the default class implementing the interface it is nested in. It makes sense to name such a class "Default", doesn't it? There can be other classes next to it, like "Wrapper" or "LazyInitializing" or "Dummy" or "Randomizing" or whatever.

This design pattern is used in the entire code of MicroStream, giving it an incredibly flexible and powerful architecture. For example:
With a single line of code, every part of MicroStream (every single "gear" in the machine) can be replaced by a custom implementation. One that does things differently (maybe better?) or fixes a bug without even needing a new MicroStream version. Or one that adds logging or customized exception handling or that introduces object communication where there normally is none. Maybe directly with the application logic (but at your own risk!). Anything is possible, at least inside the boundaries of the interfaces.

Thinking in interfaces might be confusing in the beginning (which is why a lot of developers "burn mark" interfaces with a counterproductive "I" prefix. It hurts me every time I see that), but THEY are the actual design types in Java. Classes are only their implementation vehicles and next to irrelevant on the design level.

--

To 2)

I think a more fitting term for "static factory method" is "pseudo constructor". It is a method that acts as a public API constructor for that type, but it isn't an actual constructor. Following the argumentation about the design advantages of such constructor-encapsulating static methods, the question about the best, consistent naming pattern arose to me. The JDK gives some horribly bad examples that should not be copied. Like "of" or "get". Those names hardly carry the meaning of the method's purpose.
It should be as short but still as descriptive as possible. "create" or "build" would be okay, but are they really the best option? "new" would be best, but ironically, that is a keyword associated with the constructors that should be hidden from public API. "neW" or "nEw" would look extremely ugly and would be cumbersome to type. But what about "New"? Yes, it's not strictly Java naming conventions. But there already is one type of methods that does is an exception to the general naming rule. Which one? Constructors! It's not "new person(...") but "new Person(...)". A method beginning with a capital letter. Since the beginning of Java. So if the static method should take the place of a constructor, wouldn't it be quite logical and a very good signal to apply that same exception ... or ... "extension" of the naming convention to that, too? So ... "New" it is. Perfectly short, perfectly clear. Also not longer and VERY similar to the original constructors. "Person.New" instead of "new Person".
The "naming convention extension" that fits BOTH naming exceptions alike is: "every static method that starts with a capital letter is guaranteed to return a new instance of that type." Not a cached one. Always a new one. (this can be sometime crucial to guarantee the correctness of algorithms.)

This also has some neat side effects. For example:

  • The pseudo-constructor method for creating a new instance of "StorageConfigurationBuilder" can be "StorageConfiguration.Builder()". It is self-explaining, simple, clear.
  • Or if there is a method "public static Vector Normalized(Vector v)", it implicitely tells that the passed instance will not be changed, but a new instance will be returned for the normalized vector value. It's like having the option to give constructors proper names all of a sudden. Instead of a sea of different "Vector(...)" methods and having to rely on the JavaDoc to indirectly explain their meaning, the explanation is right there in the name. "New(...)", "Normalized(...)", "Copy(...)" etc.

  • AND it also plays along very nicely with the nested-Default-class pattern: No need to write "new StorageConfiguration.Default()" (which would be bad because too hardcoded, anyway), but just "StorageConfiguration.New" suffices. It will internally create and return a new "StorageConfiguration.Default" instance. And should that internal logic ever change, it won't even be noticable by the API user.

Why do I do that if no one else does? If one thinks about it, that cannot be a valid argument. I stick VERY closely to standards and conventions as far as they make sense. They do about 99% of the time, but if they contain a problem (like forbidding a static method to be called "new") or lacking a perfectly reasonable feature (like PersonBuilder b = Person.Builder()" or choosing properly speaking names for constructors), then, after careful thought, I br... extend them as needed. This is called innovation. If no one else had that insight so far, bad for them, not for me. The question is not why an inventor creates an improvment, but why no one else has done it so far. If there is an obvious possibility for improvement, it can't be a valid reason not to do it just because no one else did it. Such a thinking causes stagnation and death of progress. Like locking oneself in a 1970ies data storing technology for over 40 years instead of just doing the obviously easier, faster, direct, better way.

I suggest to see the capital letter method naming extension as a testimony to innovation: If a new idea objectively brings considerably more advantages than disadvantages, it should - or almost MUST - be done.

I hereby invite everyone to adopt it.

MSTM
  • 366
  • 2
  • 2