Change FieldType to an interface inside index.* and use it for the source of properties about an IndexableField.
+1, I think we should have an oal.index.FieldType interface, that
exposes (get-only) methods. Ie, we'd just move the getters out of
IndexableField into this new FT interface (likewise for
This interface should be marked as experimental, ie, we are free to
Add a builder for FieldType to document.* which will create FieldType instances.
I don't think we should use a builder API here; I think either
big-ctor-takes-all-settings and so all fields are final, or what we
have today (.freeze()) is better.
There are two things I don't like about the builder pattern: setter
chaining and the object overhead of hard immutability.
On setter chaining:
- It's two ways to do the same thing (chaining or not); generally an
API (and a PL) should offer one (obvious) way to do things.
Suddenly we'll see tutorials and articles etc. online, some with
chaining, some without, and some mixed.
- Code is less readable w/ chaining: it makes it easy to sneak in
multiple statements per line, embed them into other statements,
etc., vs unchained where you always have one statement per line
- I don't like .indexed() as a name; I prefer .setIndexed() so it's
clear you setting something about the object.
- In encourages inefficient code, because it's easy to inline new
X().this().that() when in fact the app really should create &
reuse FieldType up front. This is trappy – the app doesn't
realize they're creating N+1 objects.
I also don't like the hard immutability (every field is final so every
setter returns a new object) since this will mean the typical use is
creating tons of objects per field per doc. Yes we can have a mutable
builder with a .build() in the end but that's making the API even more
In contrast, the "soft" immutability we have now (freeze) is very
effective, and creates no additional objects: it will prevent you from
altering a FT instance once any Field uses it. Really the
immutability is a minor detail of the implementation here; we only
need it to prevent this trap.
Generally we should try to keep Lucene's core APIs as
plain/simple/straightforward as possible. Someone can always later
layer on a builder API on top of the simpler setter+freeze or
all-properties-to-ctor API, but, not vice/versa (efficiently anyway).