views:

451

answers:

5

Okay, so we have a utility here in-house that generates business-model classes from our database tables and views, similar to (but not quite exactly like) an ORM. In maintaining it, it occurred to me that the data in the schemas isn't likely going to change a whole lot. The functionality, however, might. We may want to add additional functionality down the road. We may want to generate some of that functionality, and we may want to extend it.

The classes we're building will reside in a class library for consumption by other libraries and applications. No big surprise there. But the stumper here is how to design generated classes in such a way that we disrupt as little code as possible when we regenerate a class. If, for example, code has been added to a property (which represents a column in a database table), we don't want to lose that.

So, there are two approaches that leap to mind:

Classic inheritance, where the entire thing is done in a single, "monolithic" class and consumers are free to override the base implementation. This gets kind of tricky from time to time, though, and frequently introduces casting headaches. Further, if the derived class isn't careful and forgets to invoke base class functionality, things can quickly go awry.

Partial classes. In this scheme, we separate the business object into distinct parts: the properties (which map to columns), and the behaviors. Behaviors could even be broken down further into generated behaviors and custom behaviors. The problem with this approach, as you can see, is its inherent complexity. Further, there's the naming problem.

Here's my question for you folks: When you're dealing with a scenario like this (if you ever have), or if you were presented with a scenario like this, what solutions would you consider, and why?

+2  A: 

I would go partial classes path. Just because it fits more natural for dividing 1 object in many parts. Even Linq2Sql uses partials. Fight with complexity with patterns and proper conventions. And it's easier to perform 'partial update' (if generated code is well structured) on partial classes.

If you aren't doing any code generating - go class inheritance way (actually, you would be forced to, cause partials won't work across different assemblies).

Arnis L.
"Mr. Downvoter", be so kind and leave a reason. I would be glad to learn something new...
Arnis L.
Please see other answer for comments.
eschneider
Thanks for pointing out.
Arnis L.
+2  A: 

This is exactly the problem that partial classes exist to resolve. I think you may be breaking them down a little too far for practical purposes though. My gut reaction without knowing the finer details of your application would be to use a partial class file for all the generated code of a class, and a second file for all the code created by hand. Come up with a naming convention for generated partial classes and stick with it.

Matthew Vines
I would never do this. When you recreate all the partial class for all the DB changes, your entire code base could or probably will be broken. Partials was added mostly for the designers, and are a hack for a bad design IMO.
eschneider
I disagree entirely. I personally am not a big fan of code generation, but partial classes are the only way to go about it. You MUST have a mechanism of regenerating the code you want auto generated without touching the rest of your classes code. Partial classes are by far the best solution to that problem.
Matthew Vines
Also if done correctly, no regeneration of a partial class should break your codebase. Due to the magic of encapsulation. You can and should have your auto generated code conform to an interface that your classes implement. The most likely changes (adding a field, changing a data type, etc.) Will not break your class's contract.
Matthew Vines
Agree with Matthew. Partials serve an extremely useful purpose, and IMO are more likely than not to be representative of a really good design.
womp
For the short term, initial development I would agree more (but then you have several files which can be a maintenance hazard also). But long term (maintenance) this should be done manually. If I recreated say 500 partial classes, that could have a huge impact on the code.
eschneider
I think you're overstating the impacts. The whole point of partials is that you *don't* impact your codebase when you regenerate classes. We have a build process that regenerates a set of classes from an XML schema on every single build. The schema changes with every feature addition. We have not had to touch the partial classes in two years.
womp
+7  A: 

The whole reason Partial Classes are included in .Net is to make it easier to utilize code generation tools.

If you are generating code, use partial classes. It's really that simple. Why would you take the risk that the code might have to be re-generated down the road and you'd have to do a ton of work to re-update it with customizations?

I don't find there is much complexity to partials either - it's simply one class split over multiple files. Generated code in one file, custom code in the other.

womp
A: 

I would not expect to recreate the objects every time the DB changes. Get the DB schema as close as possible the create the objects. I would handle future changes to the DB manually as needed.

You want them evolve separately. Other wise just used DataSets and be completely bound to the DB schema.

eschneider
Question was about choosing between partials and inheritance, wasn't it?
Arnis L.
Yes, My answer is he is approaching the problem wrong. I feel code generation should be used as a one-time process to do a lot of grunt work. In the long term I would make changes manually as needed to reflect changes in the DB. This is typically how it's done.
eschneider
This is not a good solution. If you're designing a large project from scratch using an ORM tool, the schema will be changing daily, in big ways. In order to keep your entity classes up to date, you would spend all day making manual changes. A simple right-click, "update from database" in any ORM tool takes care of that all for you - but would wipe out any customizations you've done to your entities.
womp
womp's description of the problem is exactly the situation we're facing. (Well, not exactly, but pretty close.) We have a large database, and we're trying to write a lot of new code in .NET that models that database, while strapping new code onto it. So we need to generate a lot of classes really quickly, while new views are being created. We don't want to lose any work while it changes, but may need to regenerate fairly frequently. The code we generate is fairly specific to our internal framework.
Mike Hofer
@eschneider btw, i didn't downvote you ^^
Arnis L.
Yes, agree with you guys to some extent (but this is more of a short term thing). Have you considered dumb data objects, and having separate business object use/decorate them?
eschneider
A: 

If you have a type that is to be serialized (to xml) and want to add some functionality, you have to use partial class and not inheritance. Thanks ///M

Mats