I am working on a large project which, in part, is to replace an existing server stack. With a large, very normalized database, it was clear that we would need to construct many composite objects. An example of one of my queries is such: My composite object definition:
[DataContract]
public class CompositeEvent
{
Guid eventIdentity;
string accountIdentity;
string eventMessage;
DateTime eventLoggedOn;
string methodName;
string programName;
string userIdentity;
List<CompositeException> exceptions = new List<CompositeException>( );
List<CompositeParameter> methodParameters = new List<CompositeParameter>( );
List<CompositeParameter> databaseParameters = new List<CompositeParameter>( );
[DataMember]
public Guid EventIdentity
{
get { return eventIdentity; }
set { eventIdentity = value; }
}
[DataMember]
public string AccountIdentity
{
get { return accountIdentity; }
set { accountIdentity = value; }
}
[DataMember]
public string EventMessage
{
get { return eventMessage; }
set { eventMessage = value; }
}
[DataMember]
public DateTime EventLoggedOn
{
get { return eventLoggedOn; }
set { eventLoggedOn = value; }
}
[DataMember]
public string MethodName
{
get { return methodName; }
set { methodName = value; }
}
[DataMember]
public string ProgramName
{
get { return programName; }
set { programName = value; }
}
[DataMember]
public string UserIdentity
{
get { return userIdentity; }
set { userIdentity = value; }
}
public string QualifiedCreator
{
get
{
if ( String.IsNullOrEmpty( programName ) && String.IsNullOrEmpty( methodName ) )
return string.Empty;
return string.Format( "{0}:{1}", String.IsNullOrEmpty( ProgramName ) ? "{undefined}" : ProgramName, String.IsNullOrEmpty( MethodName ) ? "{undefined}" : MethodName );
}
}
[DataMember]
public int EventTypeIdentity { get; set; }
[DataMember]
public string EventTypeName { get; set; }
[DataMember]
public List<CompositeException> Exceptions
{
get { return exceptions; }
set { exceptions = value; }
}
[DataMember]
public List<CompositeParameter> MethodParameters
{
get { return methodParameters; }
set { methodParameters = value; }
}
[DataMember]
public List<CompositeParameter> DatabaseParameters
{
get { return databaseParameters; }
set { databaseParameters = value; }
}
}
And my database query in my service :
using ( Framework.Data.FrameworkDataEntities context = new Data.FrameworkDataEntities( ) )
{
var list = from item in context.EventLogs
join typeName in context.EventLogTypes on item.EventTypeId equals typeName.Id
orderby item.EventLoggedOn, item.EventLogType
select new CompositeEvent
{
AccountIdentity = item.AccountIdentity,
EventIdentity = item.Id,
EventLoggedOn = item.EventLoggedOn,
EventMessage = item.EventMessage,
EventTypeIdentity = item.EventTypeId,
EventTypeName = typeName.EventTypeName,
MethodName = item.MethodName,
ProgramName = item.ProgramName,
UserIdentity = item.UserIdentity
};
return new List<CompositeEvent>( list );
}
Now it is clear from the definition of my composite object that it only contains data, no business rules, and no other persistence or exposure of business structure, data structure, or anything else.
Yet my team mate states that this can only exist in the domain model and I MUST spend cycles moving my data from this well-defined object to a DTO. Not only that but a) all DTO's must have DTO in their name and b) they must only exist for the purpose of being moved across the network. So when our client code is developed it must a) create properties of each object property and b) move from the DTO to the view model properties.
I feel that this is taking DTO to the extreme. That based on the definition of the composite objects that these ARE data transfer objects. Also I see absolutely no issue with storing this object in the client and doing bindings directly to this object in the client. Since all I'm doing is taking every property defined in the composite object and copying them into the DTO it seems to be a massive waste of time and cycles to create an object only to copy it to another object then copy it once again to internal properties of the client.
I'm interested in other opinions on this. I feel that I'm not violating any of the OOP rules such as Separation of Concerns or Single Responsibility Principle ... at least as long as you don't become extremely anal about these. Opinions????