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/02/25 09:16:36 UTC

Re: Alternatives to the ObjectWrapper/TemplateModel approach (Was: [FM3] Remove BeansWrapper and some of its settings)

Saturday, February 25, 2017, 7:59:55 AM, David E Jones wrote:

> These all sound like good changes, and clarify what is really going on.

(Basically, I'm decreasing code size and complexity before the more
interesting changes are started.)

> Removing object wrapping IMO is more important than removing the
> *Template*Model* interfaces.

(The two come hand in hand really. If we had no TemplateModel-s, we
had no ObjectWrappers either.)

> These interfaces don't have the same runtime and
> GC overhead as object wrapping and they can be nice for type checking to make
> sure the operation in the template can actually be done on the object. Still,
> with those interfaces it would be nice to use more standard ones where they
> exist (Java collection interfaces for example).
>
> On the object wrapping topic there might be some useful things to learn from
> Groovy, though as FTL doesn't compile to a class not all of the same applies.
> The biggest performance overhead in Groovy is all the type conversions that it
> does to be a type optional scripting language. I've done a lot of work on
> optimizing Groovy code since I made a decision years ago to write a big
> framework mostly in Groovy.
>
>   
>
> I don't know that this is directly applicable to the discussion, but here is
> an article I wrote last year on some stuff I learned about Groovy
> optimization, and it may be that we can avoid some of these issues:
>
>   
>
> https://dzone.com/articles/how-to-make-groovy-as-fast-as-java  
>
>   
>
> Even Groovy has a sort of object wrapper, ie its meta class. It's one thing
> that would be great to disable when you're not using the Groovy features that
> rely on it... maybe someday I'll even look into this in Groovy itself or open
> the discussion in that community (for now I'm up to my neck in work :) ).

Luckily, I don't think this kind of performance is priority for a
template engine like FreeMarker, or at least that it's a high enough
priority to trump easy extendibility and such. That's because it's not
a programming language. Its a kind of domain specific language
basically. For something that generates output, hopefully you don't
have lines that are executed for millions and millions of times,
unless you also generate heck of a lot of output, which has to be
stored or sent, which will then (hopefully...) dominate your
performance anyway.

Also, for us, a key difficulty is that in general we can't have
assumptions about the data-model content. It's outside the template. I
just don't know that in ${user.name}, what `user` will be. Sometimes
though, the data-model is a bean, so if that's declared inside the
template, then you have better chances. But... what if User has no
fullName property, but some User subclass has, and you write
`${user.fullName!'unknown'}`? Should now I also require the user to do
an explicit type cast? Anyway, one thing is sure, templates must be
able to operate in non-static mode. Adding an alternative static mode
is way out of reach (given the resources we can burn). And without
that... our performance options are rather limited. Well, we can pull
some tricks, like with indy, even if you don't know what the type of
`user` will be, you can during execution learn that it's in practice
always an User, and then you can link User.getName() as if it was a
"static" invocation (with a guard condition so if it's not an User
after all, you can take the slow route).

> A good step in the right direction might be to start with the use of standard
> Java interfaces. For example when you do a #list it could be required that the
> object you are iterating over implements either the List or Iterator
> interfaces (perhaps with optimization to detect RandomAccess lists like
> ArrayList to avoid creating an Iterator).
> This doesn't get us all the way down
> the road, but is a start.

What I consider instead of ObjectWrapper+TemplateModel-s is the
following. We don't wrap values into anything. Instead we will have an
interface called MOPImplementation (where MOP stands for Meta Object
Protocol), which declares methods for each *operations* that FTL is
interested in, such as `int getSize(env, v)`, `boolean isEmpty(v,
env)`, `Iterator<Object> getListItemIterator(v, env)`, `Object
getParent(v, env)` (for XML DOM-s and such), etc. So if you, for
example, need to #list a value, you get the MOPImplementation instance
based on the class of the value (it's the class of the "raw" value,
not a TemplateMode), and then call getListItemIterator on it, which
either gives you the Iterator or throws an
TemplateOperationNotSupportedException. A key idea behind this is that
you do not have a MOPImplementation per value instance. Like if you
have two List-s, they all will use the same shared MOPImplementation
instance (something like
o.a.f.core.mop.impl.ListMOPImplementation.INSTANCE) to access those
lists. The MOPImplementation isn't bound to a value, it's only bound
to the class of the value (i.e. you have different MOPImplementation
instance for List-s and another for arrays, another for DOM node sets,
etc.). In comparison, with ObjectWrapper-s you have to create at least
as many TemplateSequenceModel instances as many distinct List
instances you will touch, because TemplateModel-s are bound to a
certain value instance. (It's "at least" as many, because if you
access the same List instance for the second time, you often has
re-create the TemplateModel, because caching the TemplateModel-s
doesn't worth it usually. If you assign the list to an FTL variable,
and then access the variable for multiple times, then no such
re-wrapping will happen of course, because you store the TemplateModel
in the variable, not the List directly.)

So, as you see, it's practically as flexible as ObjectWrapper-s. We
don't hard-wire what's listable, etc., because it all depends on the
set of MOPInterface classes added to the Configuration. So you can
still make classes that we have never seen to be listable, or change
the standard behavior (without changing the source code), etc.

But, I don't think it's a huge win in performance... it's hopefully
some though:

- You will generate less garbage to be GC-ed for sure, and that's good.

- If you just pass through values the template, like in
  `obj.m(theValuePassedThrough)`, you don't have to do anything extra
  with it. (Currently, you have to wrap `theValuePassedThrough`, only
  to unwrap later... ouch!)

- But... if you assign a value to an FTL variable, it won't keep the result
  of the "introspection" anymore (because you just store the original
  object, not a TemplateModel that already knows all about it), so
  each time you try to do something with it, the MOPImplementation
  has to be chosen based on the class of the value. There are tricks
  to mitigate this effect, such as side-storing MOPImplementation next
  to the variable, but it brings code complexity, and some constant
  overhead.

- Using indy might becomes feasible, as now what to do only depends on
  the class of the value, not on the value itself.

But my real agenda with this is to make the code base less daunting
(because, we need attract contributors, not only users... this is
marked like that), and to make the API more user friendly.
TemplateModel-s, if you have them, are all over the place. For
example, when a user wants to implement a directive in Java, he gets
TemplateModel-s. The first thing they want to do is, quite invariable
I pressume, unwrapping them to the classes they know. But because of
the freedom ObjectWrapper-s and TemplateModel-s have, it's not even
guaranteed that that's possible. Basically, I don't want FTL to have
its own type system (as it has with TemplateModel-s). I just want it
to define a set operations (listing something, getting the size of
something, etc.) instead. That's much easier to grasp. And if you want
your Java code to behave like FTL, you can get a MOPImplementation.

> -David
>
>   
>
> ![](https://link.nylas.com/open/5xm8m568zhx9qyloglsg31huz/local-
> 178b2039-1688?r=ZGV2QGZyZWVtYXJrZXIuaW5jdWJhdG9yLmFwYWNoZS5vcmc=)
>
>   
> On Feb 24 2017, at 9:18 pm, Daniel Dekany <dd...@freemail.hu> wrote:
>
>> In FM3, I propose removing some legacy complexity:
>
>>
>
>> \- Remove BeansWrapper, which is the super class of  
> ��DefaultObjectWrapper, and add its functionality directly to  
> ��DeafultObjectWrapper. That we have this class hierarchy has purely  
> ��historical reasons. (Even if FM2, using pure BeansWrapper is  
> ��deprecated, and causes lot of pain and confusion because it's still
> ��possible.)
>
>>
>
>> \- Remove the following BeansWrapper/DefaultObjectWrapper  
> ��settings, because they just exist in FM2 so that you can chose  
> ��between FM 2.3.0 compatibility and a better functionality:
>
>>
>
>> ��- BeansWrapper.simpleMapWrapper (DefaultObjectWrapper ignores it)  
> ��- DefaultObjectWrapper.forceLegacyNonListCollections (will be in  
> ����effect false)  
> ��- DefaultObjectWrapper.iterableSupport (will be in effect true)
>>
>
>> PS I know that there's an idea of removing  
> ObjectWrapper-s/TemplateModel-s altogether, and using a MOP instead,  
> but that's a fairly brutal change and who knows if it will be  
> affordable. So while I try not to invest much into  
> ObjectWrapper-s/TemplateModel-s until we figure that out, I do at  
> least want to remove stuff that we won't need for sure. And also, baby
> steps, easy things first... keep FM3 working all the time.
>
>>
>
>> \--  
> Thanks,  
> �Daniel Dekany
>

-- 
Thanks,
 Daniel Dekany


Re: Alternatives to the ObjectWrapper/TemplateModel approach (Was: [FM3] Remove BeansWrapper and some of its settings)

Posted by Daniel Dekany <dd...@freemail.hu>.
Tuesday, February 28, 2017, 7:06:45 PM, Woonsan Ko wrote:

> On Sat, Feb 25, 2017 at 4:16 AM, Daniel Dekany <dd...@freemail.hu> wrote:
>> Saturday, February 25, 2017, 7:59:55 AM, David E Jones wrote:
>>
>>> These all sound like good changes, and clarify what is really going on.
>>
>> (Basically, I'm decreasing code size and complexity before the more
>> interesting changes are started.)
>>
>>> Removing object wrapping IMO is more important than removing the
>>> *Template*Model* interfaces.
>>
>> (The two come hand in hand really. If we had no TemplateModel-s, we
>> had no ObjectWrappers either.)
>>
>>> These interfaces don't have the same runtime and
>>> GC overhead as object wrapping and they can be nice for type checking to make
>>> sure the operation in the template can actually be done on the object. Still,
>>> with those interfaces it would be nice to use more standard ones where they
>>> exist (Java collection interfaces for example).
>>>
>>> On the object wrapping topic there might be some useful things to learn from
>>> Groovy, though as FTL doesn't compile to a class not all of the same applies.
>>> The biggest performance overhead in Groovy is all the type conversions that it
>>> does to be a type optional scripting language. I've done a lot of work on
>>> optimizing Groovy code since I made a decision years ago to write a big
>>> framework mostly in Groovy.
>>>
>>>
>>>
>>> I don't know that this is directly applicable to the discussion, but here is
>>> an article I wrote last year on some stuff I learned about Groovy
>>> optimization, and it may be that we can avoid some of these issues:
>>>
>>>
>>>
>>> https://dzone.com/articles/how-to-make-groovy-as-fast-as-java
>>>
>>>
>>>
>>> Even Groovy has a sort of object wrapper, ie its meta class. It's one thing
>>> that would be great to disable when you're not using the Groovy features that
>>> rely on it... maybe someday I'll even look into this in Groovy itself or open
>>> the discussion in that community (for now I'm up to my neck in work :) ).
>>
>> Luckily, I don't think this kind of performance is priority for a
>> template engine like FreeMarker, or at least that it's a high enough
>> priority to trump easy extendibility and such. That's because it's not
>> a programming language. Its a kind of domain specific language
>> basically. For something that generates output, hopefully you don't
>> have lines that are executed for millions and millions of times,
>> unless you also generate heck of a lot of output, which has to be
>> stored or sent, which will then (hopefully...) dominate your
>> performance anyway.
>>
>> Also, for us, a key difficulty is that in general we can't have
>> assumptions about the data-model content. It's outside the template. I
>> just don't know that in ${user.name}, what `user` will be. Sometimes
>> though, the data-model is a bean, so if that's declared inside the
>> template, then you have better chances. But... what if User has no
>> fullName property, but some User subclass has, and you write
>> `${user.fullName!'unknown'}`? Should now I also require the user to do
>> an explicit type cast? Anyway, one thing is sure, templates must be
>> able to operate in non-static mode. Adding an alternative static mode
>> is way out of reach (given the resources we can burn). And without
>> that... our performance options are rather limited. Well, we can pull
>> some tricks, like with indy, even if you don't know what the type of
>> `user` will be, you can during execution learn that it's in practice
>> always an User, and then you can link User.getName() as if it was a
>> "static" invocation (with a guard condition so if it's not an User
>> after all, you can take the slow route).
>>
>>> A good step in the right direction might be to start with the use of standard
>>> Java interfaces. For example when you do a #list it could be required that the
>>> object you are iterating over implements either the List or Iterator
>>> interfaces (perhaps with optimization to detect RandomAccess lists like
>>> ArrayList to avoid creating an Iterator).
>>> This doesn't get us all the way down
>>> the road, but is a start.
>>
>> What I consider instead of ObjectWrapper+TemplateModel-s is the
>> following. We don't wrap values into anything. Instead we will have an
>> interface called MOPImplementation (where MOP stands for Meta Object
>> Protocol), which declares methods for each *operations* that FTL is
>> interested in, such as `int getSize(env, v)`, `boolean isEmpty(v,
>> env)`, `Iterator<Object> getListItemIterator(v, env)`, `Object
>> getParent(v, env)` (for XML DOM-s and such), etc. So if you, for
>> example, need to #list a value, you get the MOPImplementation instance
>> based on the class of the value (it's the class of the "raw" value,
>> not a TemplateMode), and then call getListItemIterator on it, which
>> either gives you the Iterator or throws an
>> TemplateOperationNotSupportedException. A key idea behind this is that
>> you do not have a MOPImplementation per value instance. Like if you
>> have two List-s, they all will use the same shared MOPImplementation
>> instance (something like
>> o.a.f.core.mop.impl.ListMOPImplementation.INSTANCE) to access those
>> lists. The MOPImplementation isn't bound to a value, it's only bound
>> to the class of the value (i.e. you have different MOPImplementation
>> instance for List-s and another for arrays, another for DOM node sets,
>> etc.). In comparison, with ObjectWrapper-s you have to create at least
>> as many TemplateSequenceModel instances as many distinct List
>> instances you will touch, because TemplateModel-s are bound to a
>> certain value instance. (It's "at least" as many, because if you
>> access the same List instance for the second time, you often has
>> re-create the TemplateModel, because caching the TemplateModel-s
>> doesn't worth it usually. If you assign the list to an FTL variable,
>> and then access the variable for multiple times, then no such
>> re-wrapping will happen of course, because you store the TemplateModel
>> in the variable, not the List directly.)
>>
>> So, as you see, it's practically as flexible as ObjectWrapper-s. We
>> don't hard-wire what's listable, etc., because it all depends on the
>> set of MOPInterface classes added to the Configuration. So you can
>> still make classes that we have never seen to be listable, or change
>> the standard behavior (without changing the source code), etc.
>>
>> But, I don't think it's a huge win in performance... it's hopefully
>> some though:
>>
>> - You will generate less garbage to be GC-ed for sure, and that's good.
>>
>> - If you just pass through values the template, like in
>>   `obj.m(theValuePassedThrough)`, you don't have to do anything extra
>>   with it. (Currently, you have to wrap `theValuePassedThrough`, only
>>   to unwrap later... ouch!)
>>
>> - But... if you assign a value to an FTL variable, it won't keep the result
>>   of the "introspection" anymore (because you just store the original
>>   object, not a TemplateModel that already knows all about it), so
>>   each time you try to do something with it, the MOPImplementation
>>   has to be chosen based on the class of the value. There are tricks
>>   to mitigate this effect, such as side-storing MOPImplementation next
>>   to the variable, but it brings code complexity, and some constant
>>   overhead.
>>
>> - Using indy might becomes feasible, as now what to do only depends on
>>   the class of the value, not on the value itself.
>>
>> But my real agenda with this is to make the code base less daunting
>> (because, we need attract contributors, not only users... this is
>> marked like that), and to make the API more user friendly.
>> TemplateModel-s, if you have them, are all over the place. For
>> example, when a user wants to implement a directive in Java, he gets
>> TemplateModel-s. The first thing they want to do is, quite invariable
>> I pressume, unwrapping them to the classes they know. But because of
>> the freedom ObjectWrapper-s and TemplateModel-s have, it's not even
>> guaranteed that that's possible. Basically, I don't want FTL to have
>> its own type system (as it has with TemplateModel-s). I just want it
>> to define a set operations (listing something, getting the size of
>> something, etc.) instead. That's much easier to grasp. And if you want
>> your Java code to behave like FTL, you can get a MOPImplementation.
>
> +1 on considering MOP as an alternative. Sounds interesting and more
> easily understandable and usable to me. Could you give a reference
> link to indy? I'm curious about how it can be used and something
> specific like how it handles a dynamic proxy object for instance.

I don't know which article is the best. Of course, there's quite a few
hits if you search for invokedynamic. (I guess this was good, but I
don't really remember: https://www.youtube.com/watch?v=qaf8sHjeQ2g)

What I was referring to are polymorphic call sites. Form a quick
glance on the Java API, I guess they could be implemented with
MethodHandles.guardWithTest-s and a MutableCallSite. But, I think we
should look into the Dynalink source code. In this case, starting out
from ChainedCallSite. Here's an illustration of what it does:
https://youtu.be/UIv86fUSORM?t=824

> Regards,
>
> Woonsan
>
>>
>>> -David
>>>
>>>
>>>
>>> ![](https://link.nylas.com/open/5xm8m568zhx9qyloglsg31huz/local-
>>> 178b2039-1688?r=ZGV2QGZyZWVtYXJrZXIuaW5jdWJhdG9yLmFwYWNoZS5vcmc=)
>>>
>>>
>>> On Feb 24 2017, at 9:18 pm, Daniel Dekany <dd...@freemail.hu> wrote:
>>>
>>>> In FM3, I propose removing some legacy complexity:
>>>
>>>>
>>>
>>>> \- Remove BeansWrapper, which is the super class of
>>>   DefaultObjectWrapper, and add its functionality directly to
>>>   DeafultObjectWrapper. That we have this class hierarchy has purely
>>>   historical reasons. (Even if FM2, using pure BeansWrapper is
>>>   deprecated, and causes lot of pain and confusion because it's still
>>>   possible.)
>>>
>>>>
>>>
>>>> \- Remove the following BeansWrapper/DefaultObjectWrapper
>>>   settings, because they just exist in FM2 so that you can chose
>>>   between FM 2.3.0 compatibility and a better functionality:
>>>
>>>>
>>>
>>>>   - BeansWrapper.simpleMapWrapper (DefaultObjectWrapper ignores it)
>>>   - DefaultObjectWrapper.forceLegacyNonListCollections (will be in
>>>     effect false)
>>>   - DefaultObjectWrapper.iterableSupport (will be in effect true)
>>>>
>>>
>>>> PS I know that there's an idea of removing
>>> ObjectWrapper-s/TemplateModel-s altogether, and using a MOP instead,
>>> but that's a fairly brutal change and who knows if it will be
>>> affordable. So while I try not to invest much into
>>> ObjectWrapper-s/TemplateModel-s until we figure that out, I do at
>>> least want to remove stuff that we won't need for sure. And also, baby
>>> steps, easy things first... keep FM3 working all the time.
>>>
>>>>
>>>
>>>> \--
>>> Thanks,
>>>  Daniel Dekany
>>>
>>
>> --
>> Thanks,
>>  Daniel Dekany
>>
>

-- 
Thanks,
 Daniel Dekany


Re: Alternatives to the ObjectWrapper/TemplateModel approach (Was: [FM3] Remove BeansWrapper and some of its settings)

Posted by Woonsan Ko <wo...@apache.org>.
On Sat, Feb 25, 2017 at 4:16 AM, Daniel Dekany <dd...@freemail.hu> wrote:
> Saturday, February 25, 2017, 7:59:55 AM, David E Jones wrote:
>
>> These all sound like good changes, and clarify what is really going on.
>
> (Basically, I'm decreasing code size and complexity before the more
> interesting changes are started.)
>
>> Removing object wrapping IMO is more important than removing the
>> *Template*Model* interfaces.
>
> (The two come hand in hand really. If we had no TemplateModel-s, we
> had no ObjectWrappers either.)
>
>> These interfaces don't have the same runtime and
>> GC overhead as object wrapping and they can be nice for type checking to make
>> sure the operation in the template can actually be done on the object. Still,
>> with those interfaces it would be nice to use more standard ones where they
>> exist (Java collection interfaces for example).
>>
>> On the object wrapping topic there might be some useful things to learn from
>> Groovy, though as FTL doesn't compile to a class not all of the same applies.
>> The biggest performance overhead in Groovy is all the type conversions that it
>> does to be a type optional scripting language. I've done a lot of work on
>> optimizing Groovy code since I made a decision years ago to write a big
>> framework mostly in Groovy.
>>
>>
>>
>> I don't know that this is directly applicable to the discussion, but here is
>> an article I wrote last year on some stuff I learned about Groovy
>> optimization, and it may be that we can avoid some of these issues:
>>
>>
>>
>> https://dzone.com/articles/how-to-make-groovy-as-fast-as-java
>>
>>
>>
>> Even Groovy has a sort of object wrapper, ie its meta class. It's one thing
>> that would be great to disable when you're not using the Groovy features that
>> rely on it... maybe someday I'll even look into this in Groovy itself or open
>> the discussion in that community (for now I'm up to my neck in work :) ).
>
> Luckily, I don't think this kind of performance is priority for a
> template engine like FreeMarker, or at least that it's a high enough
> priority to trump easy extendibility and such. That's because it's not
> a programming language. Its a kind of domain specific language
> basically. For something that generates output, hopefully you don't
> have lines that are executed for millions and millions of times,
> unless you also generate heck of a lot of output, which has to be
> stored or sent, which will then (hopefully...) dominate your
> performance anyway.
>
> Also, for us, a key difficulty is that in general we can't have
> assumptions about the data-model content. It's outside the template. I
> just don't know that in ${user.name}, what `user` will be. Sometimes
> though, the data-model is a bean, so if that's declared inside the
> template, then you have better chances. But... what if User has no
> fullName property, but some User subclass has, and you write
> `${user.fullName!'unknown'}`? Should now I also require the user to do
> an explicit type cast? Anyway, one thing is sure, templates must be
> able to operate in non-static mode. Adding an alternative static mode
> is way out of reach (given the resources we can burn). And without
> that... our performance options are rather limited. Well, we can pull
> some tricks, like with indy, even if you don't know what the type of
> `user` will be, you can during execution learn that it's in practice
> always an User, and then you can link User.getName() as if it was a
> "static" invocation (with a guard condition so if it's not an User
> after all, you can take the slow route).
>
>> A good step in the right direction might be to start with the use of standard
>> Java interfaces. For example when you do a #list it could be required that the
>> object you are iterating over implements either the List or Iterator
>> interfaces (perhaps with optimization to detect RandomAccess lists like
>> ArrayList to avoid creating an Iterator).
>> This doesn't get us all the way down
>> the road, but is a start.
>
> What I consider instead of ObjectWrapper+TemplateModel-s is the
> following. We don't wrap values into anything. Instead we will have an
> interface called MOPImplementation (where MOP stands for Meta Object
> Protocol), which declares methods for each *operations* that FTL is
> interested in, such as `int getSize(env, v)`, `boolean isEmpty(v,
> env)`, `Iterator<Object> getListItemIterator(v, env)`, `Object
> getParent(v, env)` (for XML DOM-s and such), etc. So if you, for
> example, need to #list a value, you get the MOPImplementation instance
> based on the class of the value (it's the class of the "raw" value,
> not a TemplateMode), and then call getListItemIterator on it, which
> either gives you the Iterator or throws an
> TemplateOperationNotSupportedException. A key idea behind this is that
> you do not have a MOPImplementation per value instance. Like if you
> have two List-s, they all will use the same shared MOPImplementation
> instance (something like
> o.a.f.core.mop.impl.ListMOPImplementation.INSTANCE) to access those
> lists. The MOPImplementation isn't bound to a value, it's only bound
> to the class of the value (i.e. you have different MOPImplementation
> instance for List-s and another for arrays, another for DOM node sets,
> etc.). In comparison, with ObjectWrapper-s you have to create at least
> as many TemplateSequenceModel instances as many distinct List
> instances you will touch, because TemplateModel-s are bound to a
> certain value instance. (It's "at least" as many, because if you
> access the same List instance for the second time, you often has
> re-create the TemplateModel, because caching the TemplateModel-s
> doesn't worth it usually. If you assign the list to an FTL variable,
> and then access the variable for multiple times, then no such
> re-wrapping will happen of course, because you store the TemplateModel
> in the variable, not the List directly.)
>
> So, as you see, it's practically as flexible as ObjectWrapper-s. We
> don't hard-wire what's listable, etc., because it all depends on the
> set of MOPInterface classes added to the Configuration. So you can
> still make classes that we have never seen to be listable, or change
> the standard behavior (without changing the source code), etc.
>
> But, I don't think it's a huge win in performance... it's hopefully
> some though:
>
> - You will generate less garbage to be GC-ed for sure, and that's good.
>
> - If you just pass through values the template, like in
>   `obj.m(theValuePassedThrough)`, you don't have to do anything extra
>   with it. (Currently, you have to wrap `theValuePassedThrough`, only
>   to unwrap later... ouch!)
>
> - But... if you assign a value to an FTL variable, it won't keep the result
>   of the "introspection" anymore (because you just store the original
>   object, not a TemplateModel that already knows all about it), so
>   each time you try to do something with it, the MOPImplementation
>   has to be chosen based on the class of the value. There are tricks
>   to mitigate this effect, such as side-storing MOPImplementation next
>   to the variable, but it brings code complexity, and some constant
>   overhead.
>
> - Using indy might becomes feasible, as now what to do only depends on
>   the class of the value, not on the value itself.
>
> But my real agenda with this is to make the code base less daunting
> (because, we need attract contributors, not only users... this is
> marked like that), and to make the API more user friendly.
> TemplateModel-s, if you have them, are all over the place. For
> example, when a user wants to implement a directive in Java, he gets
> TemplateModel-s. The first thing they want to do is, quite invariable
> I pressume, unwrapping them to the classes they know. But because of
> the freedom ObjectWrapper-s and TemplateModel-s have, it's not even
> guaranteed that that's possible. Basically, I don't want FTL to have
> its own type system (as it has with TemplateModel-s). I just want it
> to define a set operations (listing something, getting the size of
> something, etc.) instead. That's much easier to grasp. And if you want
> your Java code to behave like FTL, you can get a MOPImplementation.

+1 on considering MOP as an alternative. Sounds interesting and more
easily understandable and usable to me.
Could you give a reference link to indy?
I'm curious about how it can be used and something specific like how
it handles a dynamic proxy object for instance.

Regards,

Woonsan

>
>> -David
>>
>>
>>
>> ![](https://link.nylas.com/open/5xm8m568zhx9qyloglsg31huz/local-
>> 178b2039-1688?r=ZGV2QGZyZWVtYXJrZXIuaW5jdWJhdG9yLmFwYWNoZS5vcmc=)
>>
>>
>> On Feb 24 2017, at 9:18 pm, Daniel Dekany <dd...@freemail.hu> wrote:
>>
>>> In FM3, I propose removing some legacy complexity:
>>
>>>
>>
>>> \- Remove BeansWrapper, which is the super class of
>>   DefaultObjectWrapper, and add its functionality directly to
>>   DeafultObjectWrapper. That we have this class hierarchy has purely
>>   historical reasons. (Even if FM2, using pure BeansWrapper is
>>   deprecated, and causes lot of pain and confusion because it's still
>>   possible.)
>>
>>>
>>
>>> \- Remove the following BeansWrapper/DefaultObjectWrapper
>>   settings, because they just exist in FM2 so that you can chose
>>   between FM 2.3.0 compatibility and a better functionality:
>>
>>>
>>
>>>   - BeansWrapper.simpleMapWrapper (DefaultObjectWrapper ignores it)
>>   - DefaultObjectWrapper.forceLegacyNonListCollections (will be in
>>     effect false)
>>   - DefaultObjectWrapper.iterableSupport (will be in effect true)
>>>
>>
>>> PS I know that there's an idea of removing
>> ObjectWrapper-s/TemplateModel-s altogether, and using a MOP instead,
>> but that's a fairly brutal change and who knows if it will be
>> affordable. So while I try not to invest much into
>> ObjectWrapper-s/TemplateModel-s until we figure that out, I do at
>> least want to remove stuff that we won't need for sure. And also, baby
>> steps, easy things first... keep FM3 working all the time.
>>
>>>
>>
>>> \--
>> Thanks,
>>  Daniel Dekany
>>
>
> --
> Thanks,
>  Daniel Dekany
>