AvocadoSoftware.com

Software For Hardcore Developers
Welcome to AvocadoSoftware.com Sign in | Join | Help
in Search

Derick Baileys old blog archives - go to derickbailey.com for new contents

Domain Driven Design and the CSLA Business Framework

I've Previously Posted my question of how to merge the Domain Driven Design ("DDD") principles with Rocky Lhotka's CSLA framework. Recently, one of my coworkers asked almost precisely the same question. After a quick discussion with him, I compiled a conversation of sorts, between myself and Jeremy Miller concerning the subject and added my own response to my coworker. After sending out the info to my entire development team and recieving some good questions in response, I feel that the subject has been excersized enough to post. The following is the conversation series concerning DDD and CSLA.

After my original post questions CSLA and DDD, I emailed Jeremy Miller with the following questions:

Jeremy,

My team and I are traveling down the road of Test Driven Development ("TDD") for the first time and we've come to some roadblocks that I'm not sure I udnerstand how to get around.

The issues boil down to domain object models vs. object modal constraints imposed by a framework such as Rocky Lhotka's CSLA. We've been using a modified version of this for a while now (we removed the Data Portal and forced parent-child relationships) with much success in our data-centric applications.

Now we're faced with a new situation - doing TDD in a data-centric application. Do you have any advice, links, book suggestions, etc., that can get us down the right path for being able to create applications that are data-centric? Or better yet - any advice on how to delete 10+ years of data-centric development from my brain so that I can start somewhere fresh and learn the domain model better?

I think my issues are spelled out more directly in my blog post.

Any advice you can give would be a huge plus for me and my team.

Jeremy's response confirmed some of my thoughts and helped me solidify the notion that CSLA does create roadblocks in Unit Testing as well as DDD. It was also reassuring to hear that I'm not the only one asking the questions. I've known that, theoretically, for a while now but having someone else point it out is a good thing.

Derick,

[I wanted to] try to come up with something more profound than "dump CSLA." I read your post, and I'd have to agree with AddCertification vs Certifications.Add.

I don'tremember much from my last look at CSLA.Net, but my recollection is that the CSLA entity classes mash far too much infrastructure stuff into the domain classes for my taste. You really need more loose coupling to write little unit tests efficiently, and you absolutely have to get the data access out of there.

Ayende had something recently about CSLA you could go find.

You might have to punt on writing isolated NUnit tests. If you're really clase to pure data driven apps you might go take a look at FitNesse. I think it's easier to declaratively express set logic checks in FitNesse than it is to write imperative code with NUnit.

You probably already know this, but you're not alone. A lot of people struggle jumping from data centric thinking to object centric or behavioral centric design. All I can say is give the new stuff a chance. I've seen some diehard DataSet and SPROC guys end up being enthusiastic about DDD and TDD later on.

And as a side note, the largest problem that I have with CSLA is the idea that an entity contains it’s own data access code (commonly called the “Active Record” pattern). That in combination with the force parent-child relationships… both of those still bug the crap out of me and I’ll never use a pure version of CSLA because of them. I’m more comfortable having the data access code split out into it’s own class so that I can do dependency injection, and there-by enable TDD in my CSLA based applications.

Fortunately for me and my team, I have known the limitations of the stock CSLA framework for quite some time, and have created a highly modified version of the v2.0 CSLA framework for our use. My changes essentially, have been to remove the forced parent-child relationship and also to completely remove the DataPortal.

I had read a blog post from Rocky a while back, discussing an email about DDD and CSLA that was sent to him, so I pulled up Rocky's blog and found the post to send to my coworkers, to read.

From Rocky’s post:

Whether a developer (mis)uses CSLA .NET to create data-centric objects, or follows my advice and creates responsibility-driven objects is really their choice. But either way, I think good support for the RAD capabilities of the environment is key to attaining high levels of productivity when building interactive applications.

This is, essentially, the working conclusion that I came to when I hit that roadblock of TDD and DDD vs. CSLA. I basically made the conscious statement that I can find an acceptable balance by applying both TDD and DDD with the constraints of using CSLA as the base entity framework.

You have seen that I bring up the question of “Personnel.AddCertification” vs. “Personnel.Certifications.Add” and have seen Jeremy Miller responds that Personnel.AddCertification is the “correct” way to approach the situation from a DDD perspective. Given the constraints of mixing DDD and CSLA, I am, for the time-being, comfortable saying “Personnel.Certifications.Add” and still calling this DDD. This isn’t pure DDD, but I think it does fit within the spirit of DDD. It at least provides one perspective, though some won’t agree with it.

Having sent this chain of conversation to my development team, I recieved the following questions in response.

  1. Jeremy Miller responds that Personnel.AddCertification is the “correct” way” – Do you agree with Jeremy? If not, why?
  2. I am, for the time-being, comfortable saying “Personnel.Certifications.Add” and still calling this DDD” – Why are you “comfortable” saying this?
  3. the largest problem that I have with CSLA is the idea that an entity contains it’s own data access code (commonly called the “Active Record” pattern)” – Does CSLA force the “Active Record” pattern? What’s wrong with an entity having its own data access code? If a class has its own data access code, must it be implemented as an “Active Record”?
  4. I’m more comfortable having the data access code split out into it’s own class so that I can do dependency injection, and there-by enable TDD in my CSLA based applications” – A class having it’s own data access code prevents TDD?

My responses are as follows... please note that these are my opinions based on my current experience in development and knowledge gained from various resources including blog posts, books, online articles, discussions with other developers, etc.

  1. When dealing with true domain driven design, yes I agree with that statement.
  2. It’s basically a learning process for me, taking one step at a time. I’ve been development data-centric apps for over 10 years, now. As much as I would love to just jump off the deep end of DDD, I’m not comfortable doing that. According to the documents that I’ve read about DDD, we should be making statements like “Personnel.AddCertification”. However, with our current implementation of CSLA, this becomes difficult because CSLA dictates much of how we build our object models (even in the customized version that we use on our team). I don’t completely understand how to integrate a DDD object model into a UI based application. I’m not sure if there are DDD frameworks that provide all the databinding, etc., that we need or how to approach that situation. As a result of my lingering questions, I can’t completely dive into DDD and get rid of CSLA yet. So the reason I am “comfortable” saying “Personnel.Certifications.Add”, is because I understand my own limitations as a developer but also my desire to move forward with DDD where I can. The result is that I am trying to find a middle ground between the two and I will have to make certain sacrifices a long the way. Saying “Personnel.Certifications.Add” is a concession to the CSLA framework so that I can still use it’s databinding features.
  3. The standard CSLA implementation does enforce the Active Record pattern - by definition, an entity having it’s own data access code directly embedded into the object is the Active Record pattern. As for what’s “wrong” with it, that’s all a matter of perspective. From my experience and understanding of systems that span a single WinForm all the way out to distributed client/server apps that span 120+ clients with multiple servers, having the data access code embedded into an entity is a huge problem because it forces you to build your applications within those constraints. What happens if I am building an enterprise level application with CSLA and one of the requirements is client/server setup? At a very basic level, CSLA supports this through the “Data Portal” that is built in. However, this data portal has serious limitations as well. You are still coding all of your objects to contain the data access code, which means that the objects you are remoting from the server to the client are significantly heavier than an object that was pure data or data+business logic. The data port limits client/server development to data access – you can’t split your client server into an n-tier physical architecture where ServerA runs data access, ServerB runs business process, and the clients connect directly to ServerB and never know about ServerA. There’s also the issue of multiple data sources – what happens if my client needs to be written for occasional connectivity and do all the needed data access via a local XML database or via the true data server when possible? If I have my data access code stuffed directly into my objects, I can’t run in this scenario because I am limited to only the true data source. By splitting out the data access into it’s own class and providing dependency injection for the data access layer, I can use system logic to check my connection to the server and if it’s not available I will inject the XML data access layer into the process so that my data is stored on the local system. … I’ve seen this happen more than once, where the DAL becomes a severe obstruction to the application working as needed, and ugly hacks are put in place to work around the issue. Code simple, code small, code for flexibility because change will happen.
  4. Yes. Unit Testing is designed to test the smallest possible unit of code, to ensure that each small unit works appropriately, so that when the small units are chained together to create a larger unit, it can be known with significant confidence that the larger unit will function appropriately. A single unit test should work within a single domain – whether it’s the business logic, entity and data validation rules, or data access. The moment you introduce the data access layer as part of the entity itself, you have moved past a Unit test and are now talking about an Integration test. A unit test should be able to test the business logic required to say that an object is able to be saved (for example, examining the “IsSavable” property on the object) and make a call to a mock data access layer that will simulate a save occurring. This ensures that the business logic is working without actually worrying about the true data access code – just mock up the data access code so it looks like the object is getting saved. A unit test should also be a quick indication of how well a piece of code is working. If a single unit test takes 3 seconds because of network connectivity, etc. no big deal. When you have 30, 40, 120 unit tests that each take 3 seconds to run… very big deal. No one wants to sit there and twiddle their thumbs for 4 minutes while their unit tests are running, just so they can verify that one small function executed propertly.

    Take the example of a labor entry application. Let’s say I want to unit test the business process of an employee entering labor performed for a work order and I want to approach the code from the strict CSLA design and have all of the data access inside of the objects. The first problem is that my unit test can’t instantiate any of the objects I need. I have to call the DataPortal to do it for me. That’s strike one against CSLA – I don’t want to test whether or not the data portal works - I just want to create an object. Now move on to unit test code to input some hours for a work order and I need to call the method that checks all of the appropriate business logic to ensure that a valid work area, labor type, etc., has been input. In our CSLA implementation, I would have to make a call back to the data store to verify that the work done is valid. Strike two – making a data access call to validate data. Once again, this is testing the data portal, and now it’s also testing the data access code. Additionally – to actually verify that all of the data selected is valid, I am required to have a significant amount of data set up in my database; plus the actual database, the network connectivity, configuration utilities with a .Config file properly configured (and by the way, no .config file exists when running a unit test). That’s strike 3, 4, 5, and 6 against CSLA for unit testing. By trying to test the simple process of a user adding hours to a task, and only wanting a simple check to make sure all the appropriate data was input, I have been forced to fully integrate a significant amount of code that lives entirely outside of the unit test’s domain. This is no longer a unit test – this is an integration test, requiring many moving parts and a lot of setup data in the database to be in place.

    Now with that being said – I believe we should be doing integration tests, as well, just not at the unit test level. We need to additional research on projects such as FitNesse and others that do the Integration level testing, to ensure that all of the moving parts do work together. We can even fudge NUnit to do our integration testing, but that is a subject entirely separate from unit testing.  

As you can see, I don’t have all the answers - I do have a good direction, a lot of experience to back up my current thoughts, and an understanding that this is a process of discovery and learning, not a statement of truth or fact. I'm still searching for the right direction to move our development frameworks. I'm leaning towards a DDD model with other agile practices, but I haven't quite made all the connections yet.

One of the project managers responded, quoting what I think sums up the entire conversation as well as TDD/DDD...

"Code simple, code small, code for flexibility because change will happen." If through experience we learn nothing else ...

Published Monday, February 19, 2007 6:38 AM by dredge
Filed Under: , , , ,
New Comments to this post are disabled

This Blog

Post Calendar

<February 2007>
SuMoTuWeThFrSa
28293031123
45678910
11121314151617
18192021222324
25262728123
45678910

Advertisement

News

this is my old blog archives - go to http://derickbailey.com for updates

Syndication

Advertisement

Powered by Community Server, by Telligent Systems