In my domain each Domain Entity may have many Value Objects. I have created value objects to represent money, weight, count, length, volume, percentage, etc.
Each of these value objects contains both a numeric value and a unit of measure. E.g. money contains the monetary value and the currency ($, euro,...) , weight contains the numeric value and the unit of weight (kilo, pound, ...)
In the user interface these are displayed side-by-side as well: field name, its value followed by its accompanying unit, typically in a properties panel. The domain entities have equivalent DTOs that are exposed to the UI.
I have been searching for the best way to transfer the value objects inside the DTOs to the UI.
Do I simply expose the specific value object as a part of the DTO?
Do I expose a generic "value object"-equivalent that provides name/value/unit in a DTO?
Do I split it into separate name/value/unit members inside the DTO, just to reassemble them in the UI?
Do I transfer them as a KeyValuePair or Tuple inside the DTO?
Something else?
I have searched intensively but no other question seems to quite address this issue. Greatly appreciate any suggestions!
EDIT:
In the UI both values and units could get changed and sent back to the domain to update.
I would be inclined to agree with debuggr's comment above if these are one-way transfers; Value Objects aren't really Domain objects - they have no behaviour that can change their state and therefore in many ways they are only specialised "bit-buckets" in that you can serialise them without losing context.
However; if you have followed DDD practices (or if your back-end is using multi-threading, etc) then your Value Objects are immutable i.e they perhaps look something like this:
public class Money
{
readonly decimal _amount;
readonly string _currency;
public decimal Amount {get{return _amount;}}
public decimal Currency {get{return _currency;}}
public Money(decimal amount, string currency)
{
//validity checks here and then
_amount=amount;
_currency=currency;
}
}
Now if you need to send these back from the client, you can't easily re-use them directly in DTO objects unless whatever DTO mapping system you have (custom WebAPI Model binder, Automapper, etc) can easily let you bind the DTO to a Value Object using constructors...which may or may not be a problem for you, it could get messy :)
I would tend to stay away from "generic" DTO objects for things like this though, bear in mind that on the UI you still want some semblance of the "Domain" for the client-side code to work with (regardless of if that's Javascript on a Web Page or C# on a Form/Console, or whatever). Plus, it tends to be only a matter of time before you find an exceptional Value Object that has Name/Value/Unit/Plus One Weird Property specific to that Value concept
The only "fool-proof"*** way of handling this is one DTO per Value Object; although this is extra work you can't really go wrong - if you have lots and lots of these Value Objects, you can always write a simple DTO generation tool or use a T4 template to generate them for you, based on the public properties of your Value Objects.
***not a guarantee
DDD is all about behavior and explicitly expressing intent, next to clearly identifying the bounded contexts (transactional and organizational boundaries) for the problem you are trying to solve. This is far more important than the type of "structural" questions for which you are requesting answers.
I.e. starting from the "Domain Entities" that may have "Value Objects", where "Domain Entities" are mapped as a "DTO" to show/be edited in a UI is a statement about how you have structured things, that says nothing about what a user is trying to achieve in this UI, nor what the organization is required to do in response to this (i.e. the real business rules, such as awarding discounts, changing a shipping address, recommending other products a user might be interested in, changing a billing currency, etc).
It appears from your description, that you have a domain model that is mirroring what needs to be viewed/edited on a UI. That is kinda "putting the horse behind the carriage". Now you have a lot of "tiers" that provide no added value, and add a lot of complexity.
Let me try to explain what I mean, using the (simplified) example that was mentioned on having an "Order" with "Money". Using the approach that was mentioned, trying to show this on screen would likely involve the following steps:
Read the "Order Entity" for a given OrderId and its related "Money" values (likely in Order Lines for specific Product Types with a given Quantity and Unit Price). This would require a SQL statement with several joins (if using a SQL DB).
Map each of these somehow to a mirroring "domain objects" structure.
Map these again to mirroring a "DTO" object hierarchy.
Map these "DTO" objects to "View" or "ViewModel" objects in the UI.
That is a lot of work that in this example has not yielded any benefit of having a model which is supposed to capture and execute business logic.
Now as the next step, the user is editing fields in a UI. And you somehow have to marshal this back to your domain entity using the reverse route and try to infer the user's intent from the fields that were changed and subsequently apply business rules to that.
So say for instance that the user changes the currency on the "MoneyDTO" of a line item. What could be the user's intent? Make this the new Billing Currency and change it for all other line items as well? And how does this relate to the business rules? Do you need to look up the exchange rate and change the "Moneys" for all line items? Is there different business logic for more volatile currencies? Do you need to switch to new rules regarding VAT?
Those are the types of questions that seem to be more relevant for your domain, and would likely lead to a structure of domain entities and services that is different from the model which is viewed/modified on a UI.
Why not simply store the viewmodel in your database (e.g. as Json so it can be retrieved with a single query and rendered directly), so that you do not need additional translation layers to show it to a user. Also, why not structure your UI to reveal intent, and map this to commands to be sent to your domain service. E.g. a "change shipping address" command is likely relevant in the "shipping" bounded context of your organisation, "change billing currency" is relevant in the "billing" bounded context.
Also, if you complement this with domain events that are generated from your domain, denoting something that "has happened" you get additional benefits. For example the "order line added" event could be picked up by the "Additional Products A User Might Be Interested In" service, that in response updates the "Suggested Products" viewmodel in the UI for the user.
I would recommend you to have a look at concepts from CQRS as one possible means for dealing with these types of problems. As a very basic introduction with some more detailed references you could check out Martin Fowler's take on this: http://martinfowler.com/bliki/CQRS.html
Related
I have a question about keeping track of objects in different layers of a software application. In my application, I have objects in the domain layer (e.g. LineShape) that are used to represent business entities, and I have corresponding objects in the presentation layer (e.g. System.Windows.Shapes.Line) that are used to display these entities on the screen.
My question is, how do I keep the correspondence between the domain objects and the presentation objects, so that I can identify which domain object is represented by a given presentation object?
For example, if the user clicks on a System.Windows.Shapes.Line in the user interface, how can I determine which LineShape in the domain layer this object represents?
I have thought of a few potential solutions, but none of them seem ideal, especially for larger and more complex object models.
One solution is to use a dictionary that maps presentation objects to domain objects. In this case, when the user clicks on a System.Windows.Shapes.Line, I could look up the corresponding LineShape in the dictionary.
Another solution is to use an ID for both the presentation and domain objects. This approach has the advantage of being simple, but it seems strange to me to use IDs for every object in a domain-driven design, as IDs are typically used only for entities.
Are there any best practices or established patterns for solving this problem?
Use an Id for objects both in Presentations and Domain. This sounds a
bit strange to me, because as far as I am aware, we are not supposed
to use Id for every object in DDD, just for entities.
Perhaps you would be looking at an address rather than an ID. Even values must somehow be addressed so they can be replaced. Such an address may be a class property's name, an array's index, etc.
If you see the whole drawing as a collection of shape values then you could always use the shape's index as the address allowing to replace that specific shape value in the collection.
However, note that the address is only valid as long as you are working against the expected drawing's version.
Furthermore, you could also use the combination of all shape's properties to identify a given shape to modify. If you have two identical shapes (same shape, position, layer, etc.), does it matter which one you re-shape? The final drawing would look exactly the same.
In the end if it makes your life easier to model shapes as entities and given them an ID then perhaps that's the right model too even though you may not care about the specific shape's entire lifecycle.
Finally, note that if shapes are values then you can't possibly keep a reference to them in view models since values are immutable. Also, if shapes are entities, but the drawing is the Aggregate Root then shape entities shouldn't be accessible outside the root. Therefore it most likely only makes sense to reference a domain's Shape in the view model if it's an AR (unless you violate the visibility rule, but still enforce invariants through root-handled events). Also note that address/ID references may be the only option if your domain model lives on another tier.
You've asked a somewhat broad question, so I will give what I think is a correct but general answer.
In WPF, one way or another, the on-screen controls will have a DataContext. The DataContext generally speaking should be the object you want to get a hold of.
This should be the case more or less regardless of what method you use to populate all the screen controls.
It may suit your program to create special viewmodel classes which bridge between your "native" data objects, in which case those viewmodel classes will be set as the DataContext objects. If you don't need the viewmodel then the native data objects will play that role.
If you are using events, then in the code-behind for the event you can directly access the DataContext property, cast it to the expected type, and off you go.
If you are using commands then generally they are part of the viewmodel object in the first place, so they can just act directly on the object which owns them.
Background
We've been migrating a large amount of legacy code & systems to ASP.NET MVC forms. I've already coded up a number of CRUD type interfaces with MVC 4, using model binding, validation, attributes etc., so I'm fairly familiar with that whole paradigm. So far, all of these forms have been on our backend administration & management applications, where it pays to have very strict input validation. We are launching our first consumer facing application in MVC and are faced with a different type of problem.
The Problem
Our legacy forms in this area are the main revenue engine for our company. Usability of the consumer experience is the rule of the day. To that end, we want our forms to be as lenient as possible - the legacy system did a number of things to automatically correct user input (in entirely custom, non standard ways each time, of course). To that end, we don't so much want input validation as we want sanitation.
Examples
We ask the user for numerical inputs which have a unit of measure implied. Common ones are currency amounts or square footage. The input label is clear that they don't need to provide these formats:
What is the approximate square footage? (example: 2000)
What is your budget? (example: 150)
People being people, not everyone follows the directions, and we frequently get answers like:
approx 2100
1500 sq. ft.
$47.50, give or take
(Okay, I exaggerate on the last one.) The model that we are ultimately storing into our business logic accepts numeric input type for these fields (e.g. int & float). We can of course use datatype validator attributes (example [DataType(DataType.Currency)] for the budget input, or just having the field type be an integer for the square footage) to clearly indicate to the user they are doing it wrong, providing helpful error messages such as:
The square footage must be numbers only.
A better user experience, however, would be to attempt to interpret their response as leniently as possible, so they may complete the form with as little interruption as possible. (Note we have an extensive customer service side who can sort out mistakes on our system afterwards, but we have to get the user to complete the form before we can make contact.) For the square footage examples above, that would just mean stripping out non-digit characters. For the budget, it would mean stripping out everything that's not a digit or a decimal point. Only then would we apply the rest of the validation (is a number, greater than 0, less than 50000 etc.)
We're stuck on the best approach to take to accomplish this.
Potential Solutions
We've considered custom attributes, custom model bindings, and a separate scrubber service class that would live between the model and the database. Here are some of the considerations we've taken into account trying to decide upon the approach.
Custom Validation Attributes
I've read a number of helpful resources on this. (They have varying degrees of relevancy and recency. A lot of stuff I found searching for this was written for MVC2 or MVC3 and is available with standard attributes in MVC4.)
Extending ASP.NET MVC’s Validation
Custom Validation Attribute in ASP.NET MVC3
A lot of questions & topics on input sanitization which were focused on Cross-site scripting attacks or database injection.
What I haven't found is anyone doing what I want to do, which would be changing the model value itself. I could obviously create a local copy of the value, sanitize it and provide a pass/fail, but this would result in a lot of duplicate code. I would still have to sanitize any input values again before saving to the database.
Changing the model value itself has 3 benefits:
It affects subsequent validation rules, which would improve their acceptance rate.
The value is closer to what will be put into the database, reducing the additional prep & mapping overhead needed before storage.
In the event of the form being rejected for another reason, it gently suggests to the user "You're trying to hard on these fields."
Is this a valid approach? Is there someone out there who has used validation attributes in this way that I just missed?
Custom Model Binding
I read Splitting DateTime - Unit Testing ASP.NET MVC Custom Model Binders which focuses on custom date time input fields with custom validation & parsing done at the model binding layer. This lives a lot closer to the model itself, so it seems like a more appropriate place to be modifying the model values. In fact, the example class DateAndTimeModelBinder : IModelBinder does exactly that in a few places.
However, the controller action signature provided for this example does not make use of an overall model class. It looks like this
public ActionResult Edit(int id,
[DateAndTime("year", "mo", "day", "hh","mm","secondsorhwatever")]
DateTime foo) {
Rather than this
public ActionResult Edit(
MyModelWithADateTimeProperty model) {
Shortly before that, the article does say
First, usage. You can either put this Custom Model Binder in charge of all your DateTimes by registering it in the Global.asax:
ModelBinders.Binders[typeof(DateTime)] =
new DateAndTimeModelBinder() { Date = "Date", Time = "Time" };
Would that be sufficient to invoke the model binding for the date time field on the single-parameter model example MyModelWithADateTimeProperty?
The other potential draw back that I see here is that the model binder operates on a type, rather than an attribute you can apply to the standard data types. So for example, each set of validation rules I wanted to apply would necessitate a new, custom type. This isn't necessarily bad, but it could get messy and cause a lot of repeated code. Imagine:
public class MyDataModel {
[Required]
public CurrencyType BudgetRange { get; set; }
public PositiveOnlyCurrencyType PaymentAmount { get; set; }
[Required]
public StripNonDigitsIntegerType SquareFootage { get; set; }
Not the ugliest model code I've ever seen, but not the prettiest either.
Custom, External scrubber class
This has the fewest questions for me, but it has the most drawbacks as well. I've done a few things like this before, only to really regret it for one of the following reasons:
Being separate from the controller and model, it is nigh impossible to elegantly extend its validation rules to the client side.
It thoroughly obfuscates what is and what isn't an acceptable input for the different model fields.
It creates some very cumbersome hoops for displaying errors back to the user. You have to pass in your model state to the scrubber service, which makes your scrubber service uniquely tied to the MVC framework. OR you have to make your scrubber service capable of returning errors in a format that the controller can digest, which is rather more logic than is usually recommended for a controller.
The Question
Which approach would you take (or, have you taken) to accomplish this type of sanitization? What problems did it solve for you? What problems did you run into?
I would take ModelBinder approach.
When form data comes in - it goes to model binders infrastructure. There you can override decimal model binder to refine input. After that you can send it to validation routines without neeed to write specific validation attributes or something like that.
Also you can use one intelligent model binder that will do type switch internaly or override ModelBinderProvider, so your code wont be bloated with ModelBinderAttribute. Here is Jimmy Bogart article about this. Also you will get some flexibility, because you can use attributes to declare if model uses strict or adaptive binding.
In overall, IMHO, validation attributes are not suposed to alter input. They should validate it. Model binders are in fact responsible for converting all weird stuff that comes in into something usable in your system and your third approach duplicates Model binder functionality)
Hope this helps and sorry for my english)
I'm looking for a good way to add arbitrary properties to the objects in a strongly typed list, based on the principle that I shouldn't pass a DataTable from my business layer to my presentation layer.
For example, I might have a Category class with the properties CategoryId and Title. On one page I would like to fetch a list of all categories (ie. List<Category>) together with the most expensive product in each category.
A while ago, I would have just returned a DataTable with some additional columns in it with the product data in, but I'm trying not to do that -- it would be trivial to set up it's not good practice.
One option is to add a MostExpensiveProduct property to my Category class, but I might want to display the most recently added product in another case, or the cheapest product, so I'd end up adding a lot of properties to cover all the options. This just doesn't feel right to me.
Am I missing a trick here? What is the best way of doing this? Or should I just be returning a DataTable to which I can add as many columns as I need and not worry about it?
The issue seems to be you have a lot of different views you'd like to offer the user. The options I see are:
You could construct separate classes for each view that inherit from the Category class. Code gen would be a good solution here.
You could store an Attributes property, which has an IDictionary interface, and refer to items by key. I'm becoming a fan of this approach.
You could generate a data table only for binding purposes, for these views... or develop a data table like component where you can refer to fields by Key...
For fields that you compute (say you store sales tax and net price, and compute gross cost), you could store as a method of the Category object, or as an extension method.
I'm sure there are other options that I haven't thought about...
HTH.
You should create a specialized class (a view model) for each view you have containing only the properties you are interested in using in the view. This may seem like unnecessary duplication for the simplest cases, but pays off in terms of consistency and separation of layers. You can construct the view models manually, or if that gets tedious, use an object-object mapping framework like AutoMapper.
There are several things to consider here IMHO. First, it seems that the only reference from Category to Product should be Category.Products, meaning you should never have something like Category.MostExpensiveProdcut etc. As far as your business layer, I would do something like this:
From your code behind in the presentation layer:
call CategoryManager.GetCategories();
call List<Product>ProductManager.GetMostExpensiveProducts(List<Category>);
Now that you have a list of Categories, and a list of Products (assuming your Product has a reference back to its Category) you have all the necessary information to work with. Using this setup your entities (Category, Product) are not polluted.
Another thing to consider is introducing a services layer. If you find that you don't want (for whatever reason) to make two calls to the business managers, rather you want to make a single call and get all your information in one shot I would consider introducing a services layer sometimes aka "application facade". This facade would be responsible for making the individual calls to the business managers and combining results into one response before shipping it back to the UI layer. Someone mentioned that that custom object would be a "ViewModel", which is correct but often used in reference to MVC. Another name for it would be a DTO (Data Transfer Object), which designed for use with service layers/application facade.
What advice/suggestions/guidance would you provide for designing a class that has upwards of 100 properties?
Background
The class describes an invoice. An invoice can have upwards of 100 attributes describing it, i.e. date, amount, code, etc...
The system we are submitting the invoice to uses each of the 100 attributes and is submitted as a single entity (as opposed to various parts being submitted at different times).
The attributes describing the invoice are required as part of the business process. The business process can not be changed.
Suggestions?
What have others done when faced with designing a class that has 100 attributes? i.e., create the class with each of the 100 properties?
Somehow break it up (if so, how)?
Or is this a fairly normal occurrence in your experience?
EDIT
After reading through some great responses and thinking about this further, I don't think there really is any single answer for this question. However, since we ended up modeling our design along the lines of LBrushkin's Answer I have given him credit. Albeit not the most popular answer, LBrushkin's answer helped push us into defining several interfaces which we aggregate and reuse throughout the application as well as a nudged us into investigating some patterns that may be helpful down the road.
You could try to 'normalize' it like you would a database table. Maybe put all the address related properties in an Address class for example - then have a BillingAddress and MailingAddress property of type Address in your Invoice class. These classes could be reused later on also.
The bad design is obviously in the system you are submitting to - no invoice has 100+ properties that cannot be grouped into a substructure. For example an invoice will have a customer and a customer will have an id and an address. The address in turn will have a street, a postal code, and what else. But all this properties should not belong directly to the invoice - an invoice has no customer id or postal code.
If you have to build an invoice class with all these properties directly attached to the invoice, I suggest to make a clean design with multiple classes for a customer, an address, and all the other required stuff and then just wrap this well designed object graph with a fat invoice class having no storage and logic itself just passing all operations to the object graph behind.
I would imagine that some of these properties are probably related to each other. I would imagine that there are probably groups of properties that define independent facets of an Invoice that make sense as a group.
You may want to consider creating individual interfaces that model the different facets of an invoice. This may help define the methods and properties that operate on these facets in a more coherent, and easy to understand manner.
You can also choose to combine properties that having a particular meaning (addresses, locations, ranges, etc) into objects that you aggregate, rather than as individual properties of a single large class.
Keep in mind, that the abstraction you choose to model a problem and the abstraction you need in order to communicate with some other system (or business process) don't have to be the same. In fact, it's often productive to apply the bridge pattern to allow the separate abstractions to evolve independently.
Hmmm... Are all of those really relevant specifically, and only to the invoice? Typically what I've seen is something like:
class Customer:
.ID
.Name
class Address
.ID
.Street1
.Street2
.City
.State
.Zip
class CustomerAddress
.CustomerID
.AddressID
.AddressDescription ("ship","bill",etc)
class Order
.ID
.CustomerID
.DatePlaced
.DateShipped
.SubTotal
class OrderDetails
.OrderID
.ItemID
.ItemName
.ItemDescription
.Quantity
.UnitPrice
And tying it all together:
class Invoice
.OrderID
.CustomerID
.DateInvoiced
When printing the invoice, join all of these records together.
If you really must have a single class with 100+ properties, it may be better to use a dictionary
Dictionary<string,object> d = new Dictionary<string,object>();
d.Add("CustomerName","Bob");
d.Add("ShipAddress","1600 Pennsylvania Ave, Suite 0, Washington, DC 00001");
d.Add("ShipDate",DateTime.Now);
....
The idea here is to divide your into logical units. In the above example, each class corresponds to a table in a database. You could load each of these into a dedicated class in your data access layer, or select with a join from the tables where they are stored when generating your report (invoice).
Unless your code actually uses many of the attributes at many places, I'd go for a dictionary instead.
Having real properties has its advantages(type-safety, discoverability/intellisense, refactorability) but these don't matter if all the code does is gets these from elsewhere, displays on UI, sends in a web-service, saves to a file etc.
It would be too many columns when your class / table that you store it in starts to violate the rules of normalization.
In my experience, it has been very hard to get that many columns when you are normalizing properly. Apply the rules of normalization to the wide table / class and I think you will end up with fewer columns per entity.
It's considered bad O-O style, but if all you're doing is populating an object with properties to pass them onward for processing, and the processing only reads the properties (presumably to create some other object or database updates), them perhaps a simple POD object is what you need, having all public members, a default constructor, and no other member methods. You can thus treat is as a container of properties instead of a full-blown object.
I used a Dictionary < string,string > for something like this.
it comes with a whole bunch of functions that can process it, it's easy to convert strings to other structures, easy to store, etc.
You should not be motivated purely by aesthetic considerations.
Per your comments, the object is basically a data transfer object consumed by a legacy system that expects the presence of all the fields.
Unless there is real value in composing this object from parts, what precisely is gained by obscuring its function and purpose?
These would be valid reasons:
1 - You are gathering the information for this object from various systems and the parts are relatively independent. It would make sense to compose the final object in that case based on process considerations.
2 - You have other systems that can consume various sub-sets of the fields of this object. Here reuse is the motivating factor.
3 - There is a very real possibility of a next generation invoicing system based on a more rational design. Here extensibility and evolution of the system are the motivating factor.
If none of these considerations are applicable in your case, then what's the point?
It sounds like for the end result you need to produce an invoice object with around 100 properties. Do you have 100 such properties in every case? Maybe you would want a factory, a class that would produce an invoice given a smaller set of parameters. A different factory method could be added for each scenario where the relevant fields of the invoice are relevant.
If what you're trying to create is a table gateway for pre-existing 100-column table to this other service, a list or dictionary might be pretty quick way to get started. However if you're taking input from a large form or UI wizard, you're probably going to have to validate the contents before submission to your remote service.
A simple DTO might look like this:
class Form
{
public $stuff = array();
function add( $key, $value ) {}
}
A table gateway might be more like:
class Form
{
function findBySubmitId( $id ) {} // look up my form
function saveRecord() {} // save it for my session
function toBillingInvoice() {} // export it when done
}
And you could extend that pretty easily depending on if you have variations of the invoice. (Adding a validate() method for each subclass might be appropriate.)
class TPSReport extends Form {
function validate() {}
}
If you want to separate your DTO from the delivery mechanism, because the delivery mechanism is generic to all your invoices, that could be easy. However you might be in a situation where there is business logic around the success or failure of the invoice. And this is where I'm prolly going off into the weeds. But it's where and OO model can be useful...I'll wage a penny that there will be different invoices and different procedures for different invoices, and if invoice submission barfs, you'll need extra routines :-)
class Form {
function submitToBilling() {}
function reportFailedSubmit() {}
function reportSuccessfulSubmit() {}
}
class TPSReport extends Form {
function validate() {}
function reportFailedSubmit() { /* oh this goes to AR */ }
}
Note David Livelys answer: it is a good insight. Often, fields on a form are each their own data structures and have their own validation rules. So you can model composite objects pretty quickly. This would associate each field type with its own validation rules and enforce stricter typing.
If you do have to get further into validation, often business rules are a whole different modelling from the forms or the DTOs that supply them. You could also be faced with logic that is oriented by department and has little to do with the form. Important to keep that out of the validation of the form itself and model submission process(es) separately.
If you are organizing a schema behind these forms, instead of a table with 100 columns, you would probably break down the entries by field identifiers and values, into just a few columns.
table FormSubmissions (
id int
formVer int -- fk of FormVersions
formNum int -- group by form submission
fieldName int -- fk of FormFields
fieldValue text
)
table FormFields (
id int
fieldName char
)
table FormVersions (
id
name
)
select s.* f.fieldName from FormSubmissions s
left join FormFields f on s.fieldName = f.id
where formNum = 12345 ;
I would say this is definitely a case where you're going to want to re-factor your way around until you find something comfortable. Hopefully you have some control over things like schema and your object model. (BTW...is that table known a 'normalized'? I've seen variations on that schema, typically organized by data type...good?)
Do you always need all the properties that are returned? Can you use projection with whatever class is consuming the data and only generate the properties you need at the time.
You could try LINQ, it will auto-gen properties for you. If all the fields are spread across multiple tables and you could build a view and drag the view over to your designer.
Dictionary ? why not, but not necessarily. I see a C# tag, your language has reflection, good for you. I had a few too large classes like this in my Python code, and reflection helps a lot :
for attName in 'attr1', 'attr2', ..... (10 other attributes):
setattr( self, attName, process_attribute( getattr( self, attName ))
When you want to convert 10 string members from some encoding to UNICODE, some other string members shouldn't be touched, you want to apply some numerical processing to other members... convert types... a for loop beats copy-pasting lots of code anytime for cleanliness.
If an entity has a hundred unique attributes than a single class with a hundred properties is the correct thing to do.
It may be possible to split things like addresses into a sub class, but this is because an address is really an entity in itself and easily recognised as such.
A textbook (i.e. oversimplified not usable in the real world) invoice would look like:-
class invoice:
int id;
address shipto_address;
address billing_address;
order_date date;
ship_date date;
.
.
.
line_item invoice_line[999];
class line_item;
int item_no.
int product_id;
amt unit_price;
int qty;
amt item_cost;
.
.
.
So I am surpised you dont have at least an array of line_items in there.
Get used to it! In the business world an entity can easily have hundreds and sometimes thousands of unique attributes.
if all else fails, at least split the class to several partial classes to have better readability. it'll also make it easier for the team to work in parallel on different part of this class.
good luck :)
I've got some entities which have decimal properties on them. These entities' properties are displayed in multiple places throughout my UI.
Currently I'm finding myself doing:
litWeight.Text = person.Weight.ToString("0.00");
all over the place.
Now I know for a fact that in several instances, and am suspicious of many others that the client is likely to want the values to 3d.p. in the future.
Is there some pattern I can employ to handle the formatting of this Weight property (and other properties; not just decimals, perhaps dates etc.) so that I can have this formatting in a single place?
I know could use a formatstring in the webconfig, or write some extension methods in the UI but these don't seem very elegant solutions.
It would be nice to have some formatting objects which are tied to my entities, so its inherently obvious which formatter to use.
Thanks,
Andrew
The simplest solution would be to make a utility class with static methods that appropriately format different types of values and call them. For example:
litWeight.Text = Utility.FormatWeight(person.Weight);
Can you not add a method to the entities for formatting themeslves? Then each object can delegate to a 'strategy' object to do the actual formatting.
A reason for this is both to be able to change the decimal places etc, but also to allow things like internationalisation - decimal formatting is locale-dependent; some countries use decimal commas instead of points, or group digits in sets other than threes etc.
EDIT: The comment was this puts presentation code in the domain layer. True, so apply the standard fix for all design problems; add one more layer of indirection :)
You may not want to have the full MVC, but the concept of View and Model still seem appropriate. Perhaps, for each entity, define a View class, so PersonView which keeps a reference to a Person object and has properties called format_weight etc for each property of Person that is of interest? It should still use a Strategy pattern for the actual formatting.
So your example would be
PersonView pv = new PersonView(person)
litWeight.Text = pv.format_weight();
(please excuse syntactical errors, I don't speak C#)
If you want, you could make PersonView drop in replacement for Person, either by reimplementing the methods/properties and delgating to the referenced Person, or by inheriting from Person when making PersonView?
You could create a very basic user control - deriving from label or similar - that is responsible purely for displaying a weight string so you then have:
weightValue.DisplayValue(person.Weight);
and the setter formats the decimal as required. If this is used whenever you display a weight then you only have to alter the user control to change all displays of weight.
A basic version could be:
public void DisplayValue(decimal weight)
{
this.Text = weight.ToString("0.00");
}