You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@freemarker.apache.org by Daniel Dekany <dd...@freemail.hu> on 2017/01/11 23:05:15 UTC

Re: [FM3] To TemplateModel or not, also ?foo vs standard Java API methods (Was: [FM3] Package structure changes)

I have changed the subject to avoid derailing the original thread. See
my comments below...


Wednesday, January 11, 2017, 7:46:22 PM, David E Jones wrote:

> On Wed, 2017-01-11 at 11:55 +0100, Daniel Dekany wrote:
>> 
>> (3) Move TemplateModel interfaces and standard implementations from
>> o.a.f to o.a.f.model
>> 
>> Template models is a topic that's easy to understand for the users
>> (mentally and technically separate from the other concerns), so we
>> could decrease the surface area of the o.f package API with this.
>> 
>> As of the TemplateModel implementations, let's say for now that we
>> move them over from o.a.f too. Though there will be some more moving
>> around in that department, together with BeansWrapper and its friends,
>> but that's for another day.
>
> This may also be a topic for another day, but IIRC there was some
> discussion about getting rid of many of these interfaces in FM3.

Yes, and some day I meant to bring that up too. But that's high risk
thing, as it's a quite brutal change. The code base (and indeed the
mental model) is full of playing around with TemplateModels. So for
now (in the original thread), I just want to move the "model" and
object wrapper stuff somewhere into it's own package.

> I like the idea of more generally using standard interfaces such as
> java.util.List and java.util.Map, and even more
> generally avoiding the object wrapping that FreeMarker currently does.

I prefer the idea of using some kind of "navigator" (or MOP
implementator or whatever we call it). That means that I don't care if
it's a List or array or what, as far as the Navigator (coming from the
Configuration) can tell me how to iterate through it (for #list,
?join, etc.), or how to get the nth item of it (for val[n]). Then
object wrapping is avoided, but, this also means that the decision of
the Navigator (how to do this and that with the particular object) is
not memorized, or at least not as directly as with object wrapping.
But a Navigator can decide quite quickly if it only cares about the
class of the object, and so it can look up the implementation of the
requested operation in a cache keyed with the class name. Not to
mention the remote possibility of using "indy" (invoke dynamic),
because unlike with object wrapping, you decide what to do based on
class, not on instance, so you can use some custom call place that has
the cases for the most frequent classes hard wired (and so
JIT-optimized).

> This may complicate some of the internal introspection code and
> possibly even make certain things slower, but overall
> avoiding object wrapping helps a lot with memory and garbage
> collection overhead and makes the template engine more
> flexible.
>
> On the topic of using more standard Java interfaces and API: many
> built-ins can be eliminated in favor of existing API
> methods, though perhaps some current FreeMarker users prefer the
> ?foo syntax of built-ins versus the .foo() syntax of
> API calls.

There are some problems with relying on the Java API-s of the Java
objects of the data-model.

You might not want to expose all methods to the template authors, but
with an ever expanding set of methods, how to decide which one is OK
to expose to a template?

Also, you might want to use multiple classes (like List VS array is
the most common one) behind the scenes but don't want the templates to
be affected.

Also, many functions are missing from the standard API-s that you want
in templates (like the String API is very minimalist), and it's
confusing for some users if in one case you have to look up things in
some standard Java API, and in another case in the FreeMarker Manual.
Actually, we have this problem with the most basic things too, like
string `?length`; the Java API provides String.length() too. (And if I
want to allow str.length() in templates, then note that now you can
use `.` with something that's not a map-like-value, unlike in FM2.
Solvable, just a note, for now.)

Also there's the problem with Java versions. If Java 8 provides
something that's often needed in templates, and hence we don't add a
built-in for it, the users on Java 5-7 are out of luck, despite that
that 8 isn't the required minimum version. If we add it as a built-in,
then sooner or later (as Java 8+ becomes the norm) it will become to a
duplicate, which can't be removed for backward compatibility.

> For any new built-ins, like the date/time ones recently discussed,
> they could at least be inspired by the more standard Java APIs like
> the java.time classes as opposed to the Joda Time ones.

To be inspired by them is certainly a good idea.

> Joda Time is a great little package, but for stuff I've been doing
> lately it has been very nice to migrate to the
> java.time stuff. Not that Joda Time inspired built-ins would
> actually require Joda Time, but it is great that many open
> source libraries I use have moved to java.time to eliminate the
> Joda Time dependency, enough that I've been able to
> remove that dependency completely (speaking the Moqui Framework project).
>
> All of this falls into the category of avoiding redundant code and
> standards (interfaces and such). IMO when something in the standard
> Java API is available and adequate it should be preferred over
> alternatives. This lowers the learning curve and has the potential
> to make things run faster and more efficiently as well.

Sure, but FTL isn't a generic JVM programming language, so I don't see
how to apply this on it (see problems above).

> -David

-- 
Thanks,
 Daniel Dekany