Go to episode three.
Go to episode two.
Go to episode one.
In case you’re wondering why doesn’t this dude come to his point, you’ve probably missed it. I’ve made it already. The point is: you should always have a single point of truth, and at most have it reproduced on the server side. Which in most cases you don’t control anyway. Centralize your domain or business logic in the domain or business layer. Do not go directly from your front end to the server, but always use the domain layer as an intermediate. The longer I’m in this business, the more I am convinced of this simple, but golden rule.
Client / service architecture
Now you’re probably wondering why I am still blabbering on about this client / server technology. Client / server is dead and long gone isn’t it? Well, it should have been. But it isn’t. A lot of water went under the bridge since 1996, but this two-layered architecture is hard to wash out – in a sense it’s a bit like waterfall or Cobol. It’s still here in our everyday projects, on a day-to-day basis. Even though we are now building applications in service oriented architectures, and have build in a component based model before that, and perhaps in the near future are even building in a cloud model. Let’s call this client/service architecture.
Much to my liking, I get to do a lot of code audits, mostly on .NET applications. Code in these newer styled projects, such as web, service oriented, or even cloud is not that different from our old client/server code. Or if you just witness presentations at conferences on new technologies, or on emerging frameworks, such as ASP.NET MVC or ADO.NET Data Services. Or scroll around the average code example on web sites and blogs. Nothing changes. Developers are still binding their DataSet to their DataGrid. Please check out the following code.
private void ManageCustomer_Load(object sender, System.EventArgs e)
string connString = "server=(local)\\SQLEXPRESS;database=MyDatabase;Integrated Security=SSPI";
string sql = @"select * from customers";
SqlConnection conn = new SqlConnection(connString);
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
DataSet ds = new DataSet();
The Hello World excuse
I just picked this code example from an arbitrary web site. It comes from an ASP.NET web page. There’s two options: either this is a Hello World style demo, or it represents the architectural style of the whole application. In the first option, the developer is forgiven. The developer in question will use Hello World as an excuse not to practice good architecture. There’s probably very little time during his demo to explain about good architecture – although I think you should always explain about good architecture, as many developers will just follow the code examples offered and build them into their real-life applications. “But hey, I only wanted to demonstrate this new piece of technology.” Sorry, that’s no excuse.
Hence, the second option: this code example could actually represent the architectural style for a real-life application. In which case you’re screwed. Having a connection string and a SQL statement set up – in strings – on every web page is probably not what you should do. Even though these mistakes will already kill you in maintenance mode, this is not what I wanted to express. Things get worse: this code does not have room for business logic. A DataSet with customers in it is retrieved from the database, and a grid view called grdCustomers is filled with this data. What if I want to run some business logic on my customers? Where do I put it?
The service oriented Hello World excuse
Let’s move on. You might consider that the previous code example is from the old world as it is still centered around the database. Even though it is quite recent code. Let’s consider a real new age code example.
private void GetAccountsData()
CrmAuthenticationToken token = new CrmAuthenticationToken();
token.OrganizationName = "MicrosoftCRM";
token.AuthenticationType = 0;
CrmService service = new CrmService();
service.CrmAuthenticationTokenValue = token;
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
string fetchXml = @"<fetch mapping='logical'>
<entity name = 'account'>
<attribute name = 'name'/>
<attribute name = 'telephone1'/>
<attribute name = 'address1_city'/>
<attribute name = 'address1_country'/>
<attribute name = 'websiteurl'/>
<order attribute = 'name' descending='false' />
result = service.Fetch(fetchXml);
This particular code example comes from a SharePoint WebPart. This web part is used to represent a list of accounts and select an account from this list. These account are retrieved not from a database, but from a service in Microsoft CRM. The accounts retrieved are stored in an instance variable called _crmData. Unfortunately, this variable is not a collection of Account objects, but rather is defined as a DataSet.
DataSet _crmData = new DataSet();
And to complete this service oriented example, the instance variable _crmData is then used to render the web part by binding the GridView to the first table in the DataSet.
protected override void OnPreRender(EventArgs e)
grdCrmAccounts.DataSource = _crmData.Tables;
lblHeader.Text = "Accounts from Microsoft CRM";
lblHeader.ID = "header";
All in all, again this is a typical Hello World demo scenario that was presented to illustrate the combination of SharePoint and Microsoft CRM. But again, this kind of code will also appear in real-life applications without any doubt. It’s easy to see what’s missing here. There is no location to put our possible business logic.
In a service oriented scenario this means we totally rely on the definition and signature of the objects from the server, in this particular example on the definition of the Account object in Microsoft CRM. Although relying on services sound reliable, it is in fact no more reliable then to trust on the definition of a table called Accounts in an underlying database. Hence the phrase client/service architecture.
Hi, did this post have an episode five??
This actually looked very interesting, very nice contribution but still lacks a part I consider very important… the one that should state: "so… that's the wrong thing… now this is a solution…"
Thank you very much for your contribution!
Hi. You're right. I was planning on writing parts 5 to 8, but somehow never got around to that. Hope to put the whole damn thing in a book one day.