Jon Kruger -
  • About Me
  • Blog
  • Values
  • Presentations
About Me
Blog
Values
Presentations
  • About Me
  • Blog
  • Values
  • Presentations
Jon Kruger
Architecture

Defending my project architecture

Today in a meeting we had a big debate about project architecture, anemic domain models, SOA, and other kinds of good stuff. Seeing that I was in the minority arguing against lots of really smart people I should answer the call and defend my ideas. :)

The question that started the discussion was, “Does SOA lead to the anemic domain model anti-pattern?” This issue has been debated in the altdotnet forums recently.

First, a little about the architecture of my project. We are writing a Windows Forms app that talks to a middle-tier using WCF and then saves to a SQL Server database. Our layers go something like this:

User Interface (controllers, views)
Service Agent (helps controllers talk to web services)
—- service boundary —-
WCF services
Business Logic
Data Access (LINQ to SQL)
————————–
SQL Server

LINQ to SQL generates all of our entity objects and these entity objects are used on both sides to the wire. Our web services are not exposed to the public and our Winforms client is the only app consuming them.

Here are the issues that people have with this:

Sharing the entity objects on both sides of the wire violates SOA tenets because it introduces tight coupling between server and client.

Sharing the entity objects on both sides does violate SOA tenets. But in our case, what we’re doing is not SOA! Wikipedia defines SOA as:

Service-Oriented Architecture (SOA) is a software architecture where functionality is grouped around business processes and packaged as interoperable services. SOA also describes IT infrastructure which allows different applications to exchange data with one another as they participate in business processes.

Notice the part about applications exchanging data with one another. We are not exposing our web services to anyone other than our client. We have total control of both sides of the wire. Just because I’m using web services in my app does not mean that we have a service oriented architecture! So why should I create different entity objects for each side of the wire along with DTOs and translation classes? What benefit does that give me?

Sure, sometimes you add properties to entity objects just to help you display something in a grid. And sometimes you have properties on an entity that you will never need on the client side. And theoretically there is a situation where you may want your entity object on the client to be structured differently than they are on the server for some reason. But are any of these good reasons to create new layers and create more code that I have to maintain?

I’ve worked on projects that have had separate entities for the client and server (with DTOs and translation in between). This was quite painful. Every time I had to add a new entity object with corresponding services and UI screens, I had to add 13 files to the project. 13 files!! This was before I even wrote any unit tests. I spent more time writing plumbing than anything else.

One day when I was working said project I picked up what looked like an easy bug. I had to add 2 fields to a database table and then add them to a screen. No fancy logic, no validation. It took me 20 minutes! All I was doing as was adding two properties to a screen! These types of things should be easy.

On my current project, things go much faster. I can drag my database tables onto the LINQ to SQL designer and immediately I have my entity objects created and I can load and save them to the database. I can immediately go and start writing code that has business value. I have to create 4 fewer classes for each entity now (no client entity, no DTOs, no translation code). I’m not hand-writing my entities and mapping files because these are generated for me. Sure, they’re not true POCO entities (although you can do this with LINQ to SQL if you don’t want to use the generated code), but I don’t think that it’s worth throwing away the generated code just so that I can write my own POCO entities (read: plumbing).

There are some cases where we still need DTOs to load and save data in complex situations, but we don’t spend the time doing it until we need to.

Like I said before, all of my web services are only consumed by our client. If another application or someone outside of my team wanted to consume my services, I would create a new service and use DTOs and translation so that I don’t tightly couple my domain model with outside consumers. Now I’m doing true SOA! But I don’t spend the time doing all of the extra work until I need to do it.

Because LINQ to SQL generates our entity objects and we use these throughout the app, we don’t have a rich domain model and our entity objects map one-to-one with database tables.

Sure, I admit that having entity objects map one-to-one with database tables isn’t always “ideal”, and LINQ to SQL doesn’t handle many-to-many relationships that well. But honestly, it’s not that bad. This doesn’t always sit well with the Domain Driven Design crowd, who say that you should start by creating your business objects and that the primary focus should be on the domain and domain logic. Certainly these are good concepts, and I’m not saying that DDD is a bad idea at all. If we were using NHibernate instead of LINQ to SQL we could make our business objects more like business objects and less like database tables.

My point is this — there are situations where Domain Driven Design is good (complex domain designs). But keep in mind that the goal is to deliver a working piece of software (that is testable and maintainable and all that). No one will care that your business layer is super-elegant if you don’t get done on time. In that case, my “good enough” business layer trumps the more elegant business layer that took longer to develop (in fact, I’d guess that with DDD you would still have the majority of your business objects map one-to-one with database tables anyway). Remember, the architecture is not the deliverable.

The business objects do not have any behavior in them, all of that is in the business logic layer (the anemic domain model anti-pattern), and this is not good object-oriented design.

Yes, the fact that my business objects don’t have the logic in them is an example of the anemic domain model pattern. You got me on this one. But really, how bad is this? Sure, you don’t know to look for GetOrdersForCustomer() in the CustomerLogic class or the OrderLogic class. But what’s the worst that can happen? Someone writes the code to fetch this stuff twice?

While I would love to have the business logic encapsulated in my business objects, I also don’t want to send all of the validation rules and server logic over to the client, and I don’t want to switch to DTOs and client entities just to resolve this problem. So I’ll live with the anemic domain model for now. Honestly, most of the complaints I’ve heard is that it’s annoying to have the logic in separate classes, but I haven’t heard anyone say that it flat out doesn’t work.

In summary…

Remember, what is our goal — to deliver a piece of software on time, that meets the business needs, and is maintainable. On my current project, we delivered on time (our first release was done a month ahead of time), we were able to spend more time writing code that meets a business need (vs. writing plumbing), and our code is quite maintainable in my opinion (18 different developers have worked on it, and we just wrote our 3000th unit test today). Obviously, I cannot take most of the credit for this because the people writing the code are the main reason for the success. But I like to think that the architecture that we’re using helped us do it.

Discuss!

July 22, 2008by Jon Kruger
Architecture

In my former life, I got to write code

I used to write about LINQ and writing code and other developer stuff. That was back when I got to write code for a living.

My role on my current project started out as a lead developer role but has since morphed into non-coding architect/project manager. I have to admit that I got a little sad when I took my name off of the feature wall because I had worked on one feature in the last 3 months. But that’s life in the consulting world, and even though I’m not writing as much code as I used to, I’m still having fun and I’m still learning a lot.

We just went live with our first release last week and it was a really big deal at the client site. It was a big deal for me too since this is the first time I have been in charge of a project. Having a solid development team has made the whole process pretty painless, but I feel like what has made me successful personally are things that I’ve learned over time on previous projects.

Maintaining realistic expectations is crucial

Probably the worst thing that I can do is not be realistic. We have to give the business a realistic expectation of what we can get done and in how much time we will get it done. I have to be realistic with how much stuff I tell myself that I can get done myself and how much I need to delegate to others. The project sponsors need to be realistic with the rest of the business and not promise them something that is not realistic (this is done really well at the client that I’m at right now). I have to be realistic about how I balance work stuff and non-work stuff. In other words, don’t lie to others and don’t lie to yourself.

Estimating features is crucial

One of the most important things that I (and the rest of the development team) have to do is estimate how long features will take to complete. If we are unable to come up with accurate estimates, we’ll end up behind on our schedule, we’ll start to cheat on good development practices like unit testing, and the project will probably end up over budget. I’ve seen it happen many times.

The longer I’m in this business, the better I’m getting at estimating features. When I first started as a developer, I underestimated everything because I never considered all of the factors. On each project, I feel like I add a little more to my estimates. Hopefully this doesn’t mean that I’m becoming a slower developer!

Actually, what it means is that I’m learning everything that goes into completing a feature. When I first started estimating, I would just estimate the time it would take to complete the first pass at the feature. I never included the time that it will take to manually test the feature, write unit tests, fix the average number of bugs for that type of feature, design the feature with other developers, and even chase down requirements. All of those things affect how long it will take me to complete a feature.

People skills are crucial

You here this all the time, but it’s true. The reason I’m not writing code is that I spend a good portion of my day talking to people. On a normal day I might be chasing down requirements, making sure that the app is running OK in production, planning for future releases, working with the infrastructure team to make sure they can meet our needs, answering QA questions, helping out the training staff, helping other developers, discussing other projects, and sitting in numerous meetings. This is why I’m still having a lot of fun even though I don’t get to write code. I really enjoy working with people, and it’s even more fun when the people you are working with are doing a good job.

Part of my job is taking business requirements and translating them into technical requirements. The hardest part of doing this is that everyone speaks a different language. Every business has it’s own lingo, and every industry has it’s own lingo. Project managers, BAs, QA people, architects, developers, and DBAs each have their own lingo. So not only do I have to ask the right questions, I have to know how to interpret what someone else is saying and translate it into terms that someone else in another role can understand. I feel like I’m getting better at this, but it’s not easy.

Keeping everyone on the same page is of the utmost importance. Everything might be fine with our application, but if we broke someone else’s application in the process, we didn’t really succeed. So it’s my job to make sure that I know about everything and everyone involved in the process and then make sure that they feel and know that they are a part of the process.

That’s why I think it’s important to make people feel like they know me and feel like they are a part of my team. Otherwise, they won’t be as willing to work with us because they’ll probably feel like I’m being a burden to them. I would rather have them feel like they’re helping out a friend.

People skills apply to anything collaborative in life. It doesn’t matter if you’re a developer, an architect, a project manager, a football player, a student, a doctor, or a spouse. So don’t think that you can ignore this skill, because sooner or later you’re going to end up needing it.

April 22, 2008by Jon Kruger
Architecture

Frameworks and layers

I’ve recently started on a new project where we are rewriting a legacy app basically from scratch. This means that the first coding task is to set up all of the architecture, frameworks, and layers that we will use for the rest of the project.

I think that this is the most crucial time in the life of the project. The work that is done now will affect many things, including:

  • How long it will take to develop the rest of the application
  • How long it will take for other developers to understand the architecture (learning curve) so that they can be productive
  • How easy it will be to add new features and make changes several years later (after many of the original developers are no longer on the project)
  • Whether or not the project ultimately succeeds

Those are some important issues! So we better get it right!

Many of the problems I have seen have come from having too many unnecessary layers to deal with in the project. Let’s look at some common rationalizations for layers and tiers in project architecture.

“By separating the business entities and logic from the database code, we can insulate the business code so that it can work with any database.”

I would hope that almost every application does this one. I was on a project that used NHibernate and we were able to rip out Oracle and replace it with SQL Server in a day or so. This separation is fairly easy to implement, especially if you use an O/R mapper. It also lets you write unit tests against the business layer so that you can make sure that database changes don’t break your application.

“We’ll have a separate UI layer and business layer and keep the validation code out of the UI.”

This is good on many fronts — you are able to write a new UI and use the existing business layer (e.g. put a web front end on top of a business layer that was used in a Winforms app, or maybe you’re really brave and you move from Winforms to WPF!). Also, in most cases you will need certain pieces of validation and logic code that can’t just live in one screen on the UI, and putting validation logic in the UI makes it impossible to unit test.

“Let’s write our data layer so that we could plug in any database with any schema so that it will work without our business layer knowing that anything changed.”

I really have to question this one. Let’s say that there is a possibility that we could have another database schema that we might have to plug in. But let’s think about this some more.

  • Honestly, what are the chances that this will ever happen? If we’re going to invest a significant amount of time in order to have this flexibility, we better be pretty sure that we’re going to have to plug in another database someday.
  • Even if we did someday have to plug in a different database schema, would we even be able to get it working? Can you really switch to a drastically different database schema and have the app be fast enough? What if the new database has different constraints and foreign keys?
  • Would it be easier to write some kind of integration that would bring the data from the new database into our database? No one likes to write integration code, but it gets the job done and it won’t affect the performance of the application.
  • Having a bulkier architecture to deal with will affect how fast you can develop pretty much any feature that you want to add to the application. Also, when a new developer joins your team, it will affect how fast they can get up to speed (and they might be bitter at you for making their life more painful).

We need to always remember why we are writing code in the first place — to provide business value. Sure, writing applications can be fun, but they’re not paying us just to have fun!

Frameworks and layers are meant to serve us… if you feel like you’re a slave to your framework, maybe you need to rethink how your project is structured.

I like to keep things simple. Use existing code libraries whenever possible (such as Enterprise Library, an O/R mapper, etc.). Don’t create some extra layer just because of what we might have to do in the future, when we don’t even know if we’re going to have to do it. Design your application to be flexible so that you can adapt to change, but don’t burden yourself with something that is just going to make everything more difficult in the process.

November 5, 2007by Jon Kruger
Page 2 of 2«12

About Me

I am a technical leader and software developer in Columbus, OH. Find out more here...

I am a technical leader and software developer in Columbus, OH, currently working as a Senior Engineering Manager at Upstart. Find out more here...