Should a Trim method generally in the Data Access Layer or with in the Domain Layer?
I'm dealing with a database that contains data with inconsistencies such as white leading and trailing white space.
In general I see a lot of developers practice defensive coding by trimming almost all strings that come from the database that may have been entered by a user at some point. In my oppinoin it is better to do such formating before data is persisted so that it is done only once and then the data can be in a consistent and reliable state. Unfo开发者_如何学编程rtunatley this is not the case however which leads me to the next best solution, using a Trim method.
If I trim all data as part of my data access layer then I don't have to concern myself with defensive trimming within the business objects of my domain layer. If I instead put the trimming responsibility in my business objects, such as with set accessors of my C# properties, I should get the same net results however the trim will be operating on all values assigned to my business objects properties not just the ones that come from the inconsistent database.
I guess as a somewhat philisophical question that may determine the answer I could ask "Should the domain layer be responsible for defensive/coercive formatting of data?" Would it make sense to have a set accessor for a PhoneNumber property on a business object accept a unformatted or formatted string and then attempt to format it as required or should this responsibility be pushed to the presentation and data access layers leaving the domain layer more strict in the type of data that it will accept? I think this may be the more fundamental question.
Update: Below are a few links that I thought I should share about the topic.
Information service patterns, Part 3: Data cleansing pattern
LINQ to SQL - Format a string before saving?
How to trim values using Linq to Sql?
I'd suggest "cleaning" the data in the Application layer. The reason you want to do it here (yes, higher in the stack like Dev Art suggested) is because your Domain Model should 'model' the domain as close as possible. What if at some point in time all the data is 'clean'? Well, then you might want to remove the helper method that does the 'cleaning'. Easier to remove it from a place higher in the application stack.
Use a classy extension method that uses reflection (don't start with telling me reflection is slow until you know how it works) or something to dig into all 'string' properties (for example) of your domain object graph. Here is an example that uses this technique to adjust DateTime
values to a fixed offset - note how it will "offset" all DateTime
values even deep in collections or other custom types. In your case, the offsetting wlil be your trimming. This is certainly easier than adding .Trim()
s all over the show and can be decoupled fairly easily.
Remember, the bad data is a cross-cutting concern to your Domain and so should not tie directly to it (think AOP).
The data must be cleaned prior to being persisted. Now that it is persisted you have unclean data, that likely needs to be cleaned in the database. Consider looking for customer by name. Can I find "John", "Doe" if what I stored was " John ", " Doe ".
Cleaning the data as close to the UI allows you have much simpler code. The defensive code can change from cleanup code to assertions. (i.e. assert string = trimmed(string)). To get to this point you will need to cleanup the database as well as the UI code.
it is better to do such formatting before data is persisted
Absolutely.
Should the domain later be responsible for defensive/coercive formatting of data?
With the currently stored data you won't find a right place to introduce the trim. it's because the consistency of your storage is broken.
You could try the self-healing approach. Read the data and trim it somewhere before displaying in a dialogue. As soon as the user saves this dialogue, the data in the database gets "fixed".
As for the new input, I'm leaning toward opinion that trimming data is some cleaning operation that belongs neither to the domain layer nor to the data layer. The user input should get "cleaned" somewhere close to the UI layer before you actually start working with that data.
精彩评论