Make the user explicit!
I have already come across domains where the user culture is a first-class citizen in the domain, but in such situations I model the correct value object (in your example, I would use the Position class class that implements IEquatable<Position> ) and a User who can express such values.
Following your example, something like:
public sealed class VATIN : IEquatable<VATIN> { // implementation here... } public sealed class Position : IEquatable<Position> { // implementation here... } public sealed class Person { // a few constructors here... // a Person identifier from the domain expert, since it an entity public VATIN Identifier { get { // implementation here } } // some more properties if you need them... public Position CurrentPosition { get { // implementation here } } // some commands public void PromoteTo(Position newPosition) { // implementation here } } public sealed class User { // <summary>Express the position provided according to the culture of the user.</summary> // <param name="position">Position to express.</param> // <exception cref="ArgumentNullException"><paramref name="position"/> is null.</exception> // <exception cref="UnknownPositionException"><paramref name="position"/> is unknown.</exception> public string Express(Position position) { // implementation here } // <summary>Returns the <see cref="Position"/> expressed from the user.</summary> // <param name="positionName">Name of the position in the culture of the user.</param> // <exception cref="ArgumentNullException"><paramref name="positionName"/> is null or empty.</exception> // <exception cref="UnknownPositionNameException"><paramref name="positionName"/> is unknown.</exception> public Position ParsePosition(string positionName) { // implementation here } }
And don't forget about the documentation and the correctly designed exceptions !
Attention
There are at least two huge design smells in the sample model:
- public setter (Position property)
- a System.String with a business value
A public setter means that your object provides its own state to customers regardless of its own invariants, or that such a property has no commercial value for the object and, therefore, should not be part of the object at all. Indeed, mutable objects always need separate commands (which can change state) and queries (which cannot) .
A System.String with business semantics always smells like a domain concept that is left implicit, usually a value object with equality actions (which implements IEquatable, I mean).
Keep in mind that the reusable model is pretty hard to get, as it requires more than two domain experts and extensive ddd modeling experience. The worst “domain model” I have encountered in my career was developed by a senior programmer with huge OOP skills, but had no previous modeling experience: it was a combination of GoF templates and data structures, in the hope that they would be really flexible be useless. After 200 thousand Euros spent on this, we had to throw it away and restart it from scratch.
Maybe you just need a good data model directly mapped to a set of simple data structures in C #: you will never have any ROI from an upfront investment in a domain model unless you really need it!