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 10:27:52 GMT

Hi David B.,

Thanks for this suggestion. That would indeed work nicely. As you say, it requires an extra
class, but at least there is very little duplication, at least converting TO something.

Converting TO:

>  Map m = converter.convert(myDtoWithMethods).as(PlainDTO.class).to(Map.class)

When converting FROM something, would this work?

myDtoWithMethods = converter.convert(map).as(PlainDTO.class).to(DtoWithMethods.class)

If so, then I think this would work just fine!


Cheers,
=David


> On Oct 18, 2016, at 6:13 PM, David Bosschaert <david.bosschaert@gmail.com> wrote:
> 
> Hi David L,
> 
> Recently I added the 'as()' method to the converter, which is really meant
> to disambiguate source objects. Let's say you have an object that is both a
> JavaBean as well as implementing an interface. The Converter spec will
> specify some 'priority' rules for this, but they may not always be what you
> want. The as() method can be used to treat the source object in a
> particular way.
> 
> For example, let's say your MyClass extends MyBean implements Intf1
> Let's say you want to force the converter to look at an instance of MyClass
> as Intf1.
> 
> You could then do
>  converter.convert(myobj).as(Intf1.class).to(Map.class)
> 
> Would it help to use this for the DTO+methods as well?
> You might have:
> 
> Class PlainDto {
>  public String foo;
> }
> 
> Class DtoWithMethods extends PlainDto {
>  public int someMethod() {}
> }
> 
> And then maybe use these via:
>  converter.convert(myDtoWithMethods).as(PlainDTO.class).to(Map.class)
> ?
> 
> It would require a separate class that follows the pure DTO rules...
> 
> Cheers,
> 
> David
> 
> 
> On 18 October 2016 at 09:49, David Leangen <osgi@leangen.net> wrote:
> 
>> 
>> 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