felix-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Leangen <o...@leangen.net>
Subject Re: [Converter] DTOs with methods?
Date Tue, 18 Oct 2016 08:49:31 GMT

Hi David B.,

Thanks. I think you’re right, the spec is quite clear.

If I wanted to treat any class like a DTO (ignore the methods and use only the public fields
— just like before the recent changes made to the code base), can you think of any way?

Perhaps having “strict” mode to follow the spec to the letter, and a less strict mode
for people like me?


wdyt?

Cheers,
=David


> On Oct 18, 2016, at 5:45 PM, David Bosschaert <david.bosschaert@gmail.com> wrote:
> 
> Hi all,
> 
> The OSGi spec for DTOs is pretty clear. Section 57.2 of the R6 Core spec
> states:
> 
> "Data Transfer Objects are public classes with no methods, other than the
> compiler supplied default
> constructor"
> 
> Therefore I would be reluctant to use a different definition for the
> Converter.
> 
> OTOH I think that there are a couple of options if you like to have 'DTOs
> with behaviour':
> * you could use JavaBeans. The getters/setters are understood by the the
> converter and will result in similar behaviour, but the beans can have
> other methods too.
> * registry your own converter rules for these classes.
> 
> Cheers,
> 
> David
> 
> On 16 October 2016 at 04:18, David Jencks <david_jencks@yahoo.com.invalid>
> wrote:
> 
>> Hi David L,
>> 
>> I imagine the “extra step” and “redirection” are the need to create both
>> the SomeDTO and the SomeImpl?
>> 
>> Thinking about this a bit more I’m reminded that sometimes I end up
>> thinking that putting that first “this” parameter back into every method
>> that C++ took out might be a good idea :-)
>> 
>> I started down this rabbit hole by thinking, what if we think of DTOs as
>> primitive data types, like int or long, as much as possible.
>> 
>> For your “business method” example, a static method
>> 
>> class SomeHelper {
>>  public static String calculateFooBar(SomeDTO data) {return data.foo +
>> “:” + data.bar;}
>> }
>> 
>> makes perhaps more sense than the SomeImpl I proposed before.  But if you
>> want to do something more complicated, a builder to hold state (outside the
>> DTO, presumably) can make sense:
>> 
>> class SomeBuilder {
>>  String foo;
>>  String bar;
>>  SomeBuilder(SomeDTO data) {foo = data.foo;bar = data.bar;}
>>  public void append(SomeDTO moreData) {
>>    data.foo = data.foo + ”,” + moreData.foo;
>>    data.bar = data.bar + “,” + moreData.bar;
>>  }
>> 
>>  public String calculateFooBar() {return foo + “:” + bar;}
>> }
>> 
>> So I wonder what you end up with if you have
>> -DTOs
>> -a “Helper” class with only static methods taking one or more DTOs
>> -a bunch of “builders” that hold state from one or more DTOs during
>> multi-step calculations.
>> 
>> I suppose there also needs to be some code to call some of these
>> methods/builders, but I think you need that anyway.
>> 
>> thanks
>> david jencks
>> 
>> 
>> 
>> 
>>> On Oct 15, 2016, at 5:28 PM, David Leangen <osgi@leangen.net> wrote:
>>> 
>>> 
>>> Hi David J.,
>>> 
>>> That is an interesting perspective.
>>> 
>>> Also based on the ideas proposed by Peter, and after a bit of
>> experimentation, these are my thoughts:
>>> 
>>> * Java object encapsulation “works", but only if we assume that there is
>>>    no such thing as reflection. Since an object can be introspected, it
>> means
>>>    that there is no “complete” encapsulation, only “weak” encapsulation.
>>> 
>>>     —> True. Important if thinking about security, maybe, but perhaps
>> not
>>>            very convincing to me to change my thinking.
>>> 
>>> * DTOs are not real “Value Objects” because normally a VO should be
>> immutable.
>>>    However, if all we make are copies, and both the producer and
>> consumer understand
>>>    that it is a copy being shipped, then in the end, I cannot see a
>> problem. It will cause me
>>>    to change some habits, but I don’t see a problem.
>>> 
>>> * Java8 and its “functional” flavour have really started to interest me.
>>> 
>>> 
>>> Based mostly on the last two thoughts, I have tried using the pattern I
>> wrote in my earlier post. In essence:
>>> 
>>> * API interface - determines the contract with the rest of the world
>>> * DTO - for transmitting and serializing (essential for a working system)
>>> * Implementation object - usually Value Objects, but sometimes Entities
>>> 
>>> By following most of the DTO rules, which generally means (1) make
>> serialisable data public, (2) provide a no-arg public constructor, and (3)
>> have a tree-like structure that only contains other “DTO-type” objects, the
>> DTO can be combined with the implementation.
>>> 
>>> This completely eliminates an extra step.
>>> 
>>> No longer required:  serialized data —> DTO —> domain object
>>> 
>>> New method: serialized data —> DTO (==domain object)
>>> 
>>> I have even started to make my “simple” DTOs (i.e. pure VOs with little
>> or no behaviour) part of the API instead of the impl.
>>> 
>>> I have been very pleased with the results so far. However, if we don’t
>> provide the possibility to relax the rules on the DTOs a bit, this will no
>> longer be possible. I would be really sad to not be able to use this
>> pattern, unless of course somebody has come up with a better / alternate
>> solution.
>>> 
>>> 
>>> What you propose below seems like it would encapsulate well, but it
>> seems to me that the extra step of redirection would cause duplicate work.
>> No?
>>> 
>>> 
>>> Cheers,
>>> =David
>>> 
>>> 
>>>> On Oct 16, 2016, at 1:10 AM, David Jencks <david_jencks@yahoo.com.INVALID>
>> wrote:
>>>> 
>>>> A while ago Peter said something about DTOs violating data hiding or
>> encapsulation and I decided that if you think of the DTO as a primitive
>> data type they don’t.   Following this line of thinking (which I have not
>> been able to try out in practice, just as thought experiments) you’d have
>>>> 
>>>> public class SomeDTO extends DTO {
>>>> public String foo;
>>>> public String bar;
>>>> }
>>>> 
>>>> public interface SomeInterface {
>>>> SomeDTO data(); //I’m not sure this is needed
>>>> String calculateFooBar();
>>>> }
>>>> 
>>>> public class SomeImpl {
>>>> final SomeDTO data;
>>>> public SomeImpl(SomeDTO data) {this.data = data;}
>>>> public SomeDTO data() {return data;}
>>>> public String calculateFooBar() {return data.foo + “:” + data.bar;}
>>>> }
>>>> 
>>>> I’m curious how this would work out in an actual situation, especially
>> in knowing fi the “data()” accessor is needed.  I’d hope it would only be
>> needed for serialization purposes.
>>>> 
>>>> thanks
>>>> david jencks
>>>> 
>>>>> On Oct 14, 2016, at 9:52 PM, David Leangen <apache@leangen.net>
wrote:
>>>>> 
>>>>> 
>>>>> Hi!
>>>>> 
>>>>> I only noticed now that according to the RFC, DTOs cannot contain
>> methods. I can understand why this is so, and I do not object.
>>>>> 
>>>>> However, I have found a very practical design pattern whereby I use
>> classes that act both as DTOs and domain value objects. In effect, this
>> means that they are DTOs with methods. I am willing to pay the price of
>> having “bloated” DTOs for this convenience.
>>>>> 
>>>>> 
>>>>> Would there be any way to allow configuration to permit this?
>>>>> 
>>>>> If that is out of the question then any suggestions as to what I could
>> do so as to not have to have “duplicate” classes (DTOs and domain VOs)?
>>>>> 
>>>>> 
>>>>> Example:
>>>>> 
>>>>> Domain object API
>>>>> 
>>>>> public interface SomeObject {
>>>>> String foo();
>>>>> String bar();
>>>>> String calculateFoobar();
>>>>> }
>>>>> 
>>>>> Implementation
>>>>> 
>>>>> public class SomeObjectDTO extends DTO implements SomeObject {
>>>>> public String foo;
>>>>> public String bar;
>>>>> 
>>>>> public SomeObjectDTO() {}
>>>>> 
>>>>> public SomeObjectDTO( String aFoo, String aBar ) {
>>>>>     foo = aFoo; bar = aBar;
>>>>> }
>>>>> 
>>>>> @Override public String foo() { return foo; }
>>>>> @Override public String bar() { return bar; }
>>>>> @Override public String calculateFoobar() { return foo + “:” + bar;
}
>>>>> }
>>>>> 
>>>>> 
>>>>> I like the above because:
>>>>> * No duplication
>>>>> * As a DTO, can be sent over the wire and serialised
>>>>> * Implements the domain API
>>>>> 
>>>>> 
>>>>> Cheers,
>>>>> =David
>>>>> 
>>>>> 
>>>> 
>>> 
>> 
>> 


Mime
View raw message