Friday, May 12, 2017, 10:49:33 PM, Daniel Dekany wrote:

> Thursday, May 11, 2017, 6:49:09 AM, Woonsan Ko wrote:
>
>> Hi Daniel,
>>
>> On Fri, May 5, 2017 at 3:18 PM, Daniel Dekany <ddek...@apache.org> wrote:
>>> This is now partially implemented (I have just committed it). There
>>> are many rough edges yet, but Configuration is now immutable, and it
>>> basically works. See:
>>>
>>>   
>>> https://github.com/apache/incubator-freemarker/blob/3/src/test/java/org/apache/freemarker/manualtest/GettingStartedExample.java
>>>
>>> Would be good if more people looks at this thing. As you will see if
>>> you do, there's a hierarchy of configuration related interfaces, which
>>> are implemented by both XxxConfiguration and XxxConfiguration.Builder.
>>> And so on... please find mistakes in this stuff, especially
>>> architectural ones.
>>
>> It looks really good! Great work!
>> I think a builder instance may return the same instance. I've read
>> about the builder pattern again:
>> https://en.wikipedia.org/wiki/Builder_pattern. There's no rule or
>> reason to have to return a new instance on every #build() call. Even
>> the Java example, CarBuilderImpl, in the page returns the same
>> instance, too. It seems a lot safer to do in our context as well. So,
>> I would return the same instance from the same builder on #build()
>> calls.
>
> But that's impossible if the builder creates immutable objects (which
> is the main reason of using builders in many Java frameworks,
> including FM3):
>
>  Object obj1 = builder.build();
>  b1.setFoo(123);
>  Object obj2 = builder.build();
>  assertSame(obj1, obj2)  // Impossible, as we create immutable objects

Any reaction to this? Right now I have no better idea than disallowing
calling build() for more than once (by throwing IllegalStateException).

>> Kind regards,
>>
>> Woonsan
>>
>>>
>>>
>>> Sunday, February 19, 2017, 7:41:54 PM, Woonsan Ko wrote:
>>>
>>>> On Sun, Feb 19, 2017 at 10:04 AM, Daniel Dekany <ddek...@freemail.hu> 
>>>> wrote:
>>>>> Sunday, February 19, 2017, 11:35:44 AM, Denis Bredelet wrote:
>>>>>
>>>>>> My message was not clear, I mean builders are not required for
>>>>>> standard configuration settings if they are simple types.
>>>>>
>>>>> Of course not. We are only talking about setting values like
>>>>> ObjectWrapper, TemplateLoader, TemplateResolver (when it's added),
>>>>> etc. For them, I think we will have just bite the bullet and add both
>>>>> `void setFoo(Foo)`, and `void setFooBuilder(Builder<Foo>)` (and their
>>>>> fluent API equivalent), and `Builder<Foo> getFooBuilder()`, but no Foo
>>>>> getFoo().
>>>>
>>>> +1
>>>>
>>>>> And if you call setFoo(myFoo), then getFooBuilder() will
>>>>> return something like a `new o.a.f.core.ResultWrapperBuilder(myFoo)`,
>>>>> where ResultWrapperBuilder is just a wrapper myFoo, so that it
>>>>> satisfies the Builder<Foo> interface.
>>>>
>>>> +1
>>>>
>>>>> I think I will also ban using
>>>>> setFoo(Foo) if Foo is known to have a Builder, just to enforce the
>>>>> intended usage pattern.
>>>>
>>>> +1
>>>>
>>>>> Unless somebody comes up with a better idea, I
>>>>> will try this approach when I get there, and we will see how it works
>>>>> out in reality.
>>>>
>>>> +1
>>>>
>>>> Woonsan
>>>>
>>>>>
>>>>>>> Le 19 févr. 2017 à 10:24, Denis Bredelet <brede...@mac.com> a écrit :
>>>>>>>
>>>>>>> Hi Daniel,
>>>>>>>
>>>>>>>>>> But then we lose the immutability of the built object, which was the
>>>>>>>>>> point of using builders on the first place.
>>>>>>>>>
>>>>>>>>> Ah, you're totally right! If builder is able to update an immutable
>>>>>>>>> object, then the object turns out to be mutable indirectly through the
>>>>>>>>> builder. I missed that part. :-)
>>>>>>>>> Hmm.. it seems difficult to make it immutable considering those
>>>>>>>>> expensive nested objects.
>>>>>>>>> Would it be possible to introduce lifecycle methods such as
>>>>>>>>> #initialize() in Configuration to prohibit (IllegalStateException)
>>>>>>>>> using it and its nested objects until initialized?
>>>>>>>>
>>>>>>>> Sure, but that was plan B in case we don't go for builders at all (see
>>>>>>>> in the thread starter mail). I mean, if we have that, what's the
>>>>>>>> benefit of the builder classes? When I go for builders, I would hope
>>>>>>>> fore real final fields in the built objects, and that also means that
>>>>>>>> I don't have to worry about the ordering of the field assignments,
>>>>>>>> because I got all everything at once, so I can sort the assignments.
>>>>>>>
>>>>>>> Final fields for built objects is not a requirement if all the standard 
>>>>>>> configuration settings are simple, e.g. String or Integer etc.
>>>>>>>
>>>>>>> Then possible mutations do not affect the standard configuration when 
>>>>>>> using a builder.
>>>>>>>
>>>>>>> — Denis.
>>>>>>>
>>>>>>>>> If so, perhaps we can wait for everything configured in each stage
>>>>>>>>> and finally initialize those expensive objects only once by the
>>>>>>>>> core. Also, would it be possible to wait until the final
>>>>>>>>> initialization phase, only capturing settings, without having to
>>>>>>>>> create a nested object such as ObjecrWrapper in earlier stage?
>>>>>>>>
>>>>>>>> Where do I capture the settings of the ObjectWrapper (the nested
>>>>>>>> settings)? Anyway, that's why I thought that perhaps, if we have
>>>>>>>> cfg.setFoo(T) where Foo is not just some primitive or such, then we
>>>>>>>> also allow cfg.setFooBuilder(Builder<? extends T>)... and then, you
>>>>>>>> can, using your words, capture the nested settings too.
>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>> --
>>>>> Thanks,
>>>>>  Daniel Dekany
>>>>>
>>>>
>>>
>>> --
>>> Thanks,
>>>  Daniel Dekany
>>>
>>
>

-- 
Thanks,
 Daniel Dekany

Reply via email to