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 <o...@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_jen...@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 <apa...@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 >>> >>> >> >