A short notice about object relational mapping framework generated queries…

I guess object relational mapping is an accepted paradigm for exchanging data between an object oriented domain layer and underlying databases. For most applications object relational mapping is more than sufficient. And if not, perhaps command query responsibility segregation might contribute well to your solution.

Being a more than frequent user, this very short blog post is not meant to question either of these popular paradigms. However, I would like to make it clear that applying object relational mapping might not always lead to optimal solutions, especially from a database perspective. Most object relational mapping framework generate the underlying queries to the database, based on the domain layer and the associations between the domain objects in this layer. The quality of these generated queries is strongly dependent on the quality of the domain model and layer. If the domain model is complex, so will the generated queries be. Rubbish in is rubbish out.

image

So it is noteworthy how the framework you’re using maps associations and properties to SQL statements. Some frameworks may choose remarkable construct for this mapping resulting in hard and unreadable queries, or queries that aren’t very much optimized for the underlying data model. So this short blog post is just to make you notice.

The problem actually comes from the enormous amount of features a full-grown object relational mapping framework needs to implement. Basically, everything and the kitchen sink. Driven by the good but blind ambition to serve as many developers as they possibly can, in any case more than all other competitors, the framework developers implement as many features as the code in the framework can handle. And sometimes this feature bloating may lead to peculiar results, where the framework might still function, but the original goals of providing a lightweight, straightforward, easy-to-use framework to solve most common mapping problems have long been abandoned.

For developers using such frameworks I guess the most decent piece of advice I can give is: don’t go into the dark corners of domain modeling, as the solutions resulting may be hard to maintain and to extend. Use middle-of-the-road constructs, and prefer simpler, more generic out-of-the-box solutions to more specific and elaborate domain models.

I’ll leave with an example of a query which was generated by a frequently used object relational mapping framework in the .Net space. I’m quite sure the database will have a hard time executing this particular query.

And yes, the following is indeed a single select query. Go figure.

SELECT

[Extent1].[ID] AS [ID],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN ’2X’ WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1) AND([UnionAll2].[C6] IS NOT NULL)))) THEN ’2X0X’ WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL)) THEN ’2X0X0X’ WHEN(([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND ([UnionAll1].[C6] IS NOT NULL)))) THEN’2X1X’ ELSE ’2X1X0X’ END AS [C1],

[Extent1].[MAPReportId] AS [MAPReportId],

[Extent1].[PartnerNumber] AS [PartnerNumber],

[Extent1].[CapturedVia] AS [CapturedVia],

[Extent1].[Currency] AS [Currency],

[Extent1].[DataAsOf] AS [DataAsOf],

[Extent1].[DateApproved] AS [DateApproved],

[Extent1].[DateCreated] AS [DateCreated],

[Extent1].[DateProcessed] AS [DateProcessed],

[Extent1].[DateReturned] AS [DateReturned],

[Extent1].[DateSubmittedToRo] AS [DateSubmittedToRo],

[Extent1].[PeriodCovered] AS [PeriodCovered],

[Extent1].[ProcessGeneralComments] AS [ProcessGeneralComments],

[Extent1].[ReasonReturned] AS [ReasonReturned],

[Extent1].[StatusID] AS [StatusID],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1)AND ([UnionAll2].[C6] IS NOT NULL)))) THEN [UnionAll1].[AverageLoanSize] WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL))THEN [UnionAll1].[AverageLoanSize] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND([UnionAll1].[C6] IS NOT NULL)))) THEN CAST(NULL AS float) END AS [C2],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1)AND ([UnionAll2].[C6] IS NOT NULL)))) THEN [UnionAll1].[AveragePortfolioOutstanding] WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6]IS NOT NULL)) THEN [UnionAll1].[AveragePortfolioOutstanding] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT(([UnionAll1].[C6] = 1) AND ([UnionAll1].[C6] IS NOT NULL)))) THEN CAST(NULL AS float) END AS [C3],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1)AND ([UnionAll2].[C6] IS NOT NULL)))) THEN [UnionAll1].[BoYPortfolioOutstanding] WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] ISNOT NULL)) THEN [UnionAll1].[BoYPortfolioOutstanding] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT(([UnionAll1].[C6] = 1) AND ([UnionAll1].[C6] IS NOT NULL)))) THEN CAST(NULL AS float) END AS [C4],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1)AND ([UnionAll2].[C6] IS NOT NULL)))) THEN [UnionAll1].[DepositsAmount] WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL))THEN [UnionAll1].[DepositsAmount] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND([UnionAll1].[C6] IS NOT NULL)))) THEN CAST(NULL AS float) END AS [C5],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS int) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1) AND([UnionAll2].[C6] IS NOT NULL)))) THEN [UnionAll1].[EoYNrBorrowers] WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL)) THEN[UnionAll1].[EoYNrBorrowers] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND([UnionAll1].[C6] IS NOT NULL)))) THEN CAST(NULL AS int) END AS [C6],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1)AND ([UnionAll2].[C6] IS NOT NULL)))) THEN [UnionAll1].[EoYPortfolioOutstanding] WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] ISNOT NULL)) THEN [UnionAll1].[EoYPortfolioOutstanding] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT(([UnionAll1].[C6] = 1) AND ([UnionAll1].[C6] IS NOT NULL)))) THEN CAST(NULL AS float) END AS [C7],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] =1) AND ([UnionAll2].[C6] IS NOT NULL)))) THEN [UnionAll1].[MFIPortfolioSize] WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOTNULL)) THEN [UnionAll1].[MFIPortfolioSize] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] =1) AND ([UnionAll1].[C6] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) END AS [C8],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS int) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1) AND([UnionAll2].[C6] IS NOT NULL)))) THEN [UnionAll1].[NrLoans] WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL)) THEN[UnionAll1].[NrLoans] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND([UnionAll1].[C6] IS NOT NULL)))) THEN CAST(NULL AS int) END AS [C9],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1)AND ([UnionAll2].[C6] IS NOT NULL)))) THEN [UnionAll1].[InvestmentOutstanding] WHEN (([UnionAll2].[C6] = 1) AND([UnionAll2].[C6] IS NOT NULL)) THEN [UnionAll1].[InvestmentOutstanding] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND ([UnionAll1].[C6] IS NOT NULL)))) THEN CAST(NULL AS float) END AS [C10],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1)AND ([UnionAll2].[C6] IS NOT NULL)))) THEN [UnionAll1].[LoanOutstanding] WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] ISNOT NULL)) THEN [UnionAll1].[LoanOutstanding] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT(([UnionAll1].[C6] = 1) AND ([UnionAll1].[C6] IS NOT NULL)))) THEN CAST(NULL AS float) END AS [C11],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1)AND ([UnionAll2].[C6] IS NOT NULL)))) THEN [UnionAll1].[OutstandingExposure] WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOTNULL)) THEN [UnionAll1].[OutstandingExposure] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT(([UnionAll1].[C6] = 1) AND ([UnionAll1].[C6] IS NOT NULL)))) THEN CAST(NULL AS float) END AS [C12],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] =1) AND ([UnionAll2].[C6] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL))THEN [UnionAll2].[C1] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND([UnionAll1].[C6] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) END AS [C13],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1)AND ([UnionAll2].[C6] IS NOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL)) THEN[UnionAll2].[C2] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND ([UnionAll1].[C6]IS NOT NULL)))) THEN CAST(NULL AS float) END AS [C14],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1)AND ([UnionAll2].[C6] IS NOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL)) THEN[UnionAll2].[C3] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND ([UnionAll1].[C6]IS NOT NULL)))) THEN CAST(NULL AS float) END AS [C15],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] =1) AND ([UnionAll2].[C6] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL))THEN [UnionAll2].[C4] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND([UnionAll1].[C6] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) END AS [C16],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS bit) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1) AND([UnionAll2].[C6] IS NOT NULL)))) THEN CAST(NULL AS bit) WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL)) THEN[UnionAll2].[C5] WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND ([UnionAll1].[C6]IS NOT NULL)))) THEN CAST(NULL AS bit) END AS [C17],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1)AND ([UnionAll2].[C6] IS NOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL)) THENCAST(NULL AS float) WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND([UnionAll1].[C6] IS NOT NULL)))) THEN [UnionAll2].[Exposure] ELSE [UnionAll2].[Exposure] END AS [C18],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1)AND ([UnionAll2].[C6] IS NOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL)) THENCAST(NULL AS float) WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND([UnionAll1].[C6] IS NOT NULL)))) THEN [UnionAll2].[InvestmentOutstanding] ELSE [UnionAll2].[InvestmentOutstanding]END AS [C19],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT (([UnionAll2].[C6] = 1)AND ([UnionAll2].[C6] IS NOT NULL)))) THEN CAST(NULL AS float) WHEN (([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL)) THENCAST(NULL AS float) WHEN (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] IS NOT NULL) AND ( NOT (([UnionAll1].[C6] = 1) AND([UnionAll1].[C6] IS NOT NULL)))) THEN [UnionAll2].[LoanOutstanding] ELSE [UnionAll2].[LoanOutstanding] END AS [C20],

CASE WHEN (( NOT (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL))) AND ( NOT (([UnionAll2].[C7] = 1) AND ([UnionAll2].[C7] ISNOT NULL)))) THEN CAST(NULL AS decimal(18,2)) WHEN (([UnionAll1].[C5] = 1) AND ([UnionAll1].[C5] IS NOT NULL) AND ( NOT(([UnionAll2].[C6] = 1) AND ([UnionAll2].[C6] IS NOT NULL)))) THEN CAST(NULL AS decimal(18,2)) WHEN (([UnionAll2].[C6] = 1) AND([UnionAll2].[C6] IS NOT NULL))

A book on pragmatic software architecture, patterns and frameworks?

One of the major items on my wish list – that is on the professional half of it – is to write a book that displays my ideas on software architecture, patterns and frameworks. Yes I know, there are many books on software architecture, and there are many books that explain patterns, and yes there also are a lot of books that show you how to work with framework A, B or C.

So you would say, why on earth would you want to write a book on these subjects? Well there’s three major reasons. First, there’s not a lot of books out there that combine all these subjects into one single coherent story that will actually help you to write your applications better. Second, maybe I’m a bit arrogant on this, but I feel like I have something to all the stuff that’s out there. And last but not least, I finally need to get this stuff out of my head! Maybe ambitious, but let´s see!

Order from the menu

To be honest, you might like or not like all of the ideas in this book, or even may totally disagree with some of them. Actually, you probably will. But on the whole, I hope this book will be able to inspire you and illuminate you in how to build software. It´s often a matter of taste. So consider this book as a menu. Just order from it what you like. You don´t need to copy the C# and .NET code examples from the book, but rather I hope that use can use them to shape your own ideas on software architecture, frameworks and patterns. Take from it what you like, and forget about the few things you don’t like. 

A first step

What’s the first step towards writing this book? I’ve been teaching about software architecture, patterns and frameworks for .NET for quite a number of years, and the material from these courses will be a good start, similar to the way I shaped my book on UML – from iterating over the material I had for my UML courses.

PIC091019003 

Along with the course material comes the work I’ve done in projects, and as a result the work we (the core team) do on our ever-evolving and improving ADF.NET framework.

Architecture and frameworks

So here’s the overview of the material in the software architecture and patterns course:

  • Introduction. All the usual bla bla and thanks you stuff.
  • How to set up your software architecture? A mild and brief introduction. Thinking about layers, elements in layers,  collaborations (yes CRC). And of cause you can not start without summing up some of the good practices, such as
  • (Software architecture != List<Framework>). How people mix up architecture and frameworks.
  • How frameworks can kill your project. It’s all about dependencies guys. This chapter will be a write out of my talk with the same name.
  • Some patterns to help avoid getting killed. Explaining the different variations of layer super types, my fine descriptor pattern, and the use of dependency injection and the manager-provider pattern.
  • Glue 1.0. My first framework. Short introduction into setting up a minimal framework, using your architecture and the above patterns, minimizing dependencies between your application code and the frameworks you use. It should provide you with the glue to keep your “regular” developers in the loop.
  • Extension methods and fluent interfaces. Have got a bit (not all by far!) to say on how to use them to enable your application developers to code easier and more natural using your first framework.
  • Lasagna and ingredients. What layers would you need in your application? Suggesting presentation, process, domain and data/services. And suggesting a lot of elements in the different layers.

Presentation

In the next chapters I will slowly go through the individual layers. First, let’s investigate the presentation layer:

  • Panels and lists. The basic patterns of presentation layer elements. And a straightforward implementation of a user interface independent panel. Just for the fun of it.
  • The master of detail. Introducing some typical user interface patterns, such as manage, select, search, master-detail, list-detail and the effect of those patterns on your architectural and Glue 1.0 framework requirements.
  • MVWTF. Looking at the different variations in model-view patterns, and discussing the relevance. But briefly, there’s enough said on this stuff.
  • Binding and persisting. Coupling and de-coupling your models, view-models, domain objects, whatever to and from the user interface.
  • The view-model. Sense and non-sense of view-models.
  • Validations. Things to validate and things not to validate in the user interface.

Process

Next the process layer gets a rub:

  • Why do I need a process layer? Explaining the least well-understood layer in application architectures.
  • An brief introduction to smart use cases. Still an excellent unit of work, implementation and testing for projects. This chapter will follow the lines of my presentation on this particular topic.
  • Implementing smart use cases. Introducing the task pattern, and re-iterating the manager-provider pattern. Great stuff I think! Also re-visiting the MVWTF patterns again. 
  • Unit and regression testing smart use cases. How you can write your own extensions to regular unit test framework to allow regression tests over your smart use cases.

Domain

The layer it all revolves about:

  • About being domain driven. Design, code and test, do it domain driven. Now I’m not going to repeat Eric Evans’ book here, but I do repeat (briefly) the basic concepts that derive from his work. Think of entities, repositories, factories, value objects and services.
  • Augmenting your domain. However, we are using some additional patterns in our projects that are useful patterns. Here I’ll discuss the smart reference pattern, revisit value objects, and talk about cached domain objects. I might even introduce you to search objects.
  • Business rules and validations. How do you write and where do you place your business rules, and what validations do you execute in the domain layer?
  • Independent state. Domain objects, or entities, have identity and state. This state can come from a lot of place – not all being SQL Server. So the big question here is: can I keep my domain objects independent of how we get and set its state. Well yes you can, hence the internal state patterns jumps in.

Data, services and the outside world

All the way down to the bottom, in the cellar of your application, lies the data / services layer:

  • Does the data layer really exist? Hey weren’t we using NHibernate or Entity Framework? So why do we need a data layer, and if so, what is in it?
  • Map and wrap. When querying data sources it is very likely that you will need to provide some sort of mapping from your world to the outside world. I’ll show you some simple patterns of to achieve this mapping, allowing you to wrap your domain objects around the outside world’s objects.
  • Creating queries. Again, do you really need to implement a query patterns. We do have LINQ do we? Well yes, but LINQ does not cover all your possible sources of data – a lot, but not all. So a brief introduction of the query pattern – and some implementation aspects might not be a bad idea.
  • On the way out. Somehow you will need to reach out to the outside world of your application. Virtually the outside world can be just about anything. A (set of) databases of course, but what about OData, JSON, plain or not so plain XML, restful or restless web services, Twitter, Entity Framework, NHibernate, Facebook, you name it. The gateway pattern should help you here.

Concluding

    Mildly put, this little blog post could well be the introduction for this new book – except for the thank you notes. Do you miss anything, or already agree or disagree? Want to help annotating or reviewing the manuscript in progress? Don´t hesitate to become a part of the writing process. Please comment here!

November 9, 2010 – Microsoft TechEd Europe. How frameworks can kill your projects.

[Session ARC203 at Microsoft TechEd Europe 2010 in Berlin]

When it comes to Microsoft .NET-connected development, more and more frameworks are entering the market, both from Microsoft and from open source. Think of ASP.NET MVC, Castle, Windows Workflow Foundation (WF), Entity Framework, Unity, Linq2SQL, ADO.NET Data Services, Windows Communication Foundation (WCF), nHibernate, Spring.NET, CSLA, NUnit, Enterprise Library, MEF or ADF.

IMAGE_004

Once you apply one or more frameworks to a project, the trouble begins. What if you require features that aren’t implemented in the framework? What if you decide that another framework would have been better and want to switch halfway through your project? What if the author of your favorite open source framework suddenly stops developing? What if the framework contains bugs or omissions? And what if a new version of the framework is released that is implemented differently?

image[8]

 

These and many more everyday problems can bring your project a halt, or at least require serious refactoring. During this highly interactive talk, Sander Hoogendoorn, chief architect of Capgemini’s agile Accelerated Delivery Platform and member of Microsoft’s Partner Advisory Council .NET, demonstrates pragmatic architectures and patterns that will help your projects avoid framework issues and to keep code independent of framework choices. Sander presents models of layered architectures, and looks at applying bridge patterns, managers-providers, dependency injection, descriptors and layer super-types, accompanied by lots of demos and (bad) code examples using blocks from Microsoft’s Enterprise Library, NHibernate, Log4Net, and the Entity Framework.

Join this interactive discussion to share your experience of improving the structure and quality of your software architecture and code, and to discuss how to avoid common pitfalls of applying frameworks to .NET software development.

Sander’s talk at TechEd US 2010. How frameworks can kill your projects and patterns to prevent getting killed

Last week, the Microsoft TechEd North America 2010 took place in the great city of New Orleans. I was lucky to be invited to do a talk on how frameworks can kill your projects.

When it comes to Microsoft .NET-connected development, more and more frameworks enter the market. Both from Microsoft and from open source. Think of ASP.NET MVC, Castle, Windows Workflow Foundation (WF), Entity Framework, Unity, Linq2SQL, ADO.NET Data Services, Windows Communication Foundation (WCF), nHibernate, Spring.NET, CSLA, NUnit, Enterprise Library or ADF.

Trouble begins

Once a project chooses to apply one or more frameworks, trouble begins. What if you require features that aren’t implemented in the framework? What if you decide that another framework would have been better and want to switch halfway through your project? What if the author of your favorite open source framework suddenly stops developing? What if the framework contains bugs or omissions? And, what if a new version of the framework is released that is implemented differently? These and many more everyday problems will cause your project to come to a halt, or at least make you perform serious refactoring.

Get Microsoft Silverlight  

Demos and (bad) code

During this highly interactive talk, Sander Hoogendoorn, chief architect of Capgemini’s agile Accelerated Delivery Platform, and member of Microsoft’s Partner Advisory Council .NET, demonstrates pragmatic architectures and patterns that will help your projects to stay away from framework issues, and how to keep code independent of framework choices. Sander presents models of layered architectures, and applying bridge patterns, managers-providers, dependency injection, descriptors, and layer super-types.

Of course, Sander illustrates these insightful patterns with lots of demos and (bad) code examples using blocks from Microsoft’s Enterprise Library, NHibernate, Log4Net, and the Entity Framework. Learn how to improve the structure and quality of your software architecture and code, and how to avoid the pitfalls of applying frameworks to .NET software development.

October 19. Talk. “Silverlight, .NET RIA Services and code generation”

SDC Conference, Papendal, Arnhem (www.sdc.nl)

Next week the annual SDC conference will take place at Papendal, Arnhem. As usual the organising SDN community has put together a long list of international appraised speakers, and challenging subjects on the matter of software development and software architecture.

SONY DSC 

A bit to my surprise, this year I was invited to do 3 talks, with very different subjects: Silverlight and code generation, smart use cases in service oriented projects, and .NET extension methods.

Putting model driven development to the test

The SDC website refers to my Silverlight talk as follows:

To be quite honest, this talk is putting model driven development (MDD) to the test. Model driven development – generating code from a model – is a concept that has long promised high productivity and quality to projects. There are many different approaches to MDD, some of them highly theoretical, some of them painfully oversimplified. Think of generating code from UML models, or using Oslo and M. And whatever happened to (graphical and textual) DSL’s?

As always Sander and his team follow a very pragmatic, straightforward approach to the subject, generating code from domain models and smart use cases. One of the benefits of true model driven development is that it allows to generate code from the same model to different target environments. Having done projects where code was generated in Windows applications, ASP.NET applications, and Java web applications, Sander will now use this approach to Silverlight line-of-business applications. In this talk Sander elaborates on how code generation works, how templates can be defined for Tobago MDA, a freely available MDD code generators, and will (try to) build up a Silverlight applications on stage.

Introducing .NET RIA Services

Unfortunately, my team was minimized due to illness and projects, and I had to figure out most of it myself – a though late night job. Especially since I want to pay attention to .NET RIA Services, a brand new way of buidling client/server applications in a distributed environment, where a lot of code generation takes place under the covers.

Let’s just I I can do some demo’s on the 19th…

Read more: Sander at SDC 2009.

Survey. Which frameworks do you use in .Net projects?

Later this week I will be doing a talk at the Microsoft DevDays conference at the Congrescentrum in Den Haag. This talk is titled Navigating through the hypes, Software architectures and patterns to help avoiding your projects to crash. Read more about it at www.devdays.nl.

Please fill in the little survey I’m conducting at
Survey: Which frameworks do you use in .Net projects?

Benefits and pitfalls of using frameworks

In short, during this talk I will address both the benefits and pitfalls of applying frameworks to your projects. Be it Microsoft frameworks, open source frameworks or even self developed frameworks, there’s always a catch.

image

What if you require additional features that aren’t implemented in the framework? What if you decide that another framework would have been better and want to switch halfway your project? What if the author of your favorite open source framework suddenly stops developing? What if the framework contains bugs or omissions? And what if a new version of the framework is released that is implemented totally different? These and many more everyday problems will cause your project to come to a halt, or at least make you perform serious refactoring.

So, I will address some pragmatic software architectures and patterns that will help your projects to stay away from framework problems, and how to make your code less dependent of framework choices.

Which frameworks do you use?

This brings me to my question to you. I’m curious to which frameworks you use – Microsoft, open source and / or own developed, and what your experiences are with these frameworks. Where they helpful, challenging or just plain crap?

Please fill in the little survey I’m conducting at
Survey: Which frameworks do you use in .Net projects?

Navigating through the hypes, Software architectures and patterns to help avoiding your projects to crash – this year’s DevDays talk.

Good to hear that I’ve made the program of this year’s Microsoft DevDays. Will be a challenging talk on software architecture and patterns, titled just like this blog post. Here’s the description. Hope you like it.

Navigating through the hypes, Software architectures and patterns to help avoiding your projects to crash

When it comes to .Net software development, more and more frameworks enter the market. Both from Microsoft and in open source. Just think of all the very useful frameworks, such as ASP.NET MVC, Castle, WF, Entity Framework, Unity, Linq2SQL, ADO.NET Data Services, WCF, nHibernate, Spring.NET, CSLA, NUnit, Enterprise Library or ADF.

Once a project chooses to apply one or more frameworks, trouble begins. What if you require additional features that aren’t implemented in the framework? What if you decide that another framework would have been better and want to switch halfway your project? What if the author of your favorite open source framework suddenly stops developing? What if the framework contains bugs or omissions? And what if a new version of the framework is released that is implemented totally different? These and many more everyday problems will cause your project to come to a halt, or at least make you perform serious refactoring.

During this highly interactive talk Sander Hoogendoorn, principal technology officer at Capgemini, chief architect of Capgemini’s agile Accelerated Delivery Platform, and member of Microsoft’s Visual Studio Advisory Board, will demonstrate pragmatic software architectures and patterns that will help your projects to stay away from framework problems, and how to keep your code independent of framework choices. In his well known slightly ironic style Sander will present different models of layered architectures, and explain and use bridge patterns, managers, dependency injection, descriptors, and layer super-types.

Of course, the speaker will illustrate these insightful patterns with lots of demo’s and (bad) code examples using blocks from Microsoft’s Enterprise Library, nHibernate, Log4Net, and the Entity Framework. Delegates will benefit from this talk by learning how to improve the structure and quality of their software architecture and code, and how to avoid the pitfalls of applying frameworks to .Net software development.

Why do we need software architecture?

Over the past twenty or so years I have been involved in many software development projects, code reviews, and software factory implementations. Although I had stretched the virtues of good software architecture for decades, it wasn’t until a series of recent event, that I really started re-valuing of having a sound software architecture in place. And to me a well-defined software architecture merely describes the patterns used, the layers applied, the types of classes in these layers, and how they collaborate. Primary goal would be to create structure and a clear separation of concerns in your application code.

Code is like ivy

In October and November, I was running a code audit on a 1.4 million lines of code ASP.NET web application, the second large audit I did in a short period of time. Both products where web applications that were targeted at big audiences, and that were meant to last for a long time. And in both cases the software architecture was set up really bad. In one example, I couldn’t even discover a decent software architecture through the code. In just three years this application had grown from a small web application to an enterprise web portal, and a few dozen developers, partly external from the company, had written code in a wide variety of styles. With no architecture in place, the code grew like ivy on a moisty garden shed, resulting in poor maintainability and low productivity in adding new features to the product.

Midst November, I found myself in Barcelona, visiting the Microsoft TechEd conference, where a number of new frameworks were presented – although most of them still in beta. Some of these framework already made their way into full swing projects, one the largest run for one of our Belgian customers. Looking at the presentations, and talking to developers, it occurred to me that a lot of people have their software architecture dictated by the frameworks they apply.

Just think of this. One of the developers I talked claimed to have a good software architecture just because he was using the ASP.NET MVC framework. My vision however is different. It should simply be the other way round. You have a sound software architecture in place, that expresses the business needs and the technical concepts to implement these business needs. Then if you’re interested in applying a particular new framework, you should only need to map the concepts of that framework, say ASP.NET MVC or the Entity Framework, to the concepts in your software architecture. And if it fits, use it. And if it doesn’t either don’t use it, or encapsulate it, so that it will fit in.

Benefits of a sound software architecture

So concluding, if your organization has a software architecture in place, this will offer some rather relevant benefits, which include:

  • Higher productivity. It is easier to add new features to existing software, since the structure is already in place, and the location for every new piece of code is known beforehand.
  • Better code maintainability. It is easier to maintain existing software, as the structure of the code is visible and known, so it’s easier to find bugs and anomalies.
  • Higher adaptability. New technical features, such a different front ends, or adding a business rule engine are easier to achieve, as your software architecture creates a clear separation of concerns.
  • Hype agnostic. Last but not least, it will allow you to see hypes and fads in the industry – or which there are a lot – in the light of your current structure, and to fit these hypes and fads in if so required.

So?

So why is it so many organizations and project to not adhere to having such a software architecture in place? It’s beneficial and it doesn’t require a big up front state of art research & development. Just common sense and best practices.