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 <[email protected]> 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 <[email protected]>
>> 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 <[email protected]> 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
>>>
>>>
>>
>