james-mime4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ioan Eugen Stan <stan.ieu...@gmail.com>
Subject Re: [DISCUSSION] make most of mime4j immutable
Date Thu, 16 May 2013 07:40:56 GMT
On Wed, May 15, 2013 at 8:59 PM, Oleg Kalnichevski <olegk@apache.org> wrote:
> On Wed, 2013-05-15 at 18:24 +0200, Stefano Bagnara wrote:
>> 2013/5/15 Oleg Kalnichevski <olegk@apache.org>:
>> > (1) Do nothing. While the present DOM API is not fancy and fluid and all
>> > it works.
>> > (2) Make DOM elements (almost) immutable but keep the existing
>> > Disposable model at the expense of having a few fringe cases when the
>> > same body part instance can end up referenced by multiple Message
>> > objects. Disposal of one message will inadvertently render other
>> > instances' state invalid.
>>
>> In order to better judge the best option I would have to understand
>> what immutability bring us.
>> I don't care at all that a single element could be shared between
>> messages or that a single message (or part of it) could be manipulated
>> concurrently by multiple threads.
>> On the other side I care of clean/simple API.
>>
>
> There is more to immutability than just thread safety. Immutable objects
> are always guaranteed to be in a consistent state. Always. This is
> actually quite nice once you come to depend on it.

Yes, this pays off mostly with concurrency, but it also impacts the API design.
Having immutable state makes me more relaxed because I have to worry
less about concurrency issues.

> This is currently a trend and trends may pass but there is a common
> belief that builder fluent pattern suits well for initialization of
> complex objects with many various dependencies. JAX-RS API could be a
> good example of that.

Yes, trends may pass but immutability and functional design with no
shared state are better suited for concurrent and multi
processor/cores programming. Nobody can change the object so you are
free to share it across all cores/threads => no need to synchronize.

>> Can you provide a snippet of code for the current API that you don't
>> like and how you expect it to be after an immutable/almostimmutable
>> refactoring?
>>
>
> It is not the best example but something that actually works already
>
> before refactoring
> https://svn.apache.org/repos/asf/james/mime4j/tags/apache-mime4j-project-0.7/dom/src/main/java/org/apache/james/mime4j/message/BasicBodyFactory.java
>
> after refactoring
> https://svn.apache.org/repos/asf/james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/BasicBodyFactory.java
>
>
>> > (3) Reconsider resource management concept. One possibility would be to
>> > move responsibility for resource disposal from DOM elements to Storage
>> > manager.
>>
>> If I understand it, this would always expose the Storage manager to
>> the DOM user.
>>
>> I find this is a frequent DOM use case:
>>
>> try {
>>   message = messageBuilder.parseMessage(new EOLConvertingInputStream(is));
>> } catch (...) {
>>   ...
>> } finally {
>>   message.dispose();
>> }
>>
>
> Absolutely not. On the contrary those users who do not need special
> storage would no longer have to dispose of Message objects.
>
>
>> This code currently uses the dom package and doesn't even know a
>> storage package exists.
>
> That's the whole point. We have a situation when a requirement relevant
> for a fraction of user population imposes design decisions that impact
> ALL users.

I agree with you reasoning here. Messages should not dispose
themselves and we should do well to keep them free of resources that
need to be properly disposed (InputStreams and such).

>> You could pass a different messageBuilder (using an advanced storage
>> technique) to this code and it should works the same way... are you
>> suggesting that every dom users should be forced to deal with a
>> storage manager to tell when it's done working with a message? Can you
>> make an example?
>>
>
> That's how it could look (warning: it is pseudo-code)

I like the way it builds up. Nice.

> ---
> StorageManager sm = new SomeStorageManager();
> try {
>   Message m1 = new MessageBuilder()
>    .setStorageManager(sm)
>    .parse(stream)
>    .build();
>
>   Message m2 = new MessageBuilder()
>    .setStorageManager(sm)
>    .parse(stream)
>    .addThis()
>    .changeThat().
>    .build();
>
> Message m3 = new MessageBuilder()
>   .setStorageManager(sm)
>   .copy(m2)
>   .addMore()
>   .build();
>
>   // force disposal of a message, if required
>   sm.dispose(m2);
>   // Message m3 should still remain in a consistent state
>
> } finally {
>   // Disposes of resources held by Message m1 and m3
>   sm.close();
> }
> ---
>
> Oleg
>



--
Ioan Eugen Stan
0720 898 747

Mime
View raw message