Pages

Tuesday, 16 February 2010

Udi Dahan about Simplifying Multi-Tier Architecture

I listened to Udi Dahan talk about an alternative pattern to the classic multi-tier architecture during a Skills Matter event in London.

I knew the name was familiar but I couldn’t put my finger on it until I entered the room: he was at TechEd Barcelona in November 2008! Back then he gave a very sarcastic (and enjoyable) talk about interface-based programming, dependency injection and the abuses of the strategy pattern.

Udi is a good speaker. That’s quite a treat to have a TechEd-level presentation for free at Skills Matter.

The pattern is called CQRS. Despite the boring 4-letter acronym it is based on a few very simple ideas: take out from the standard UI/Services/Business logic/DAL everything that is related to queries (= pull data off the database to show it to the user) and leave only the commands (= use business rules to change data). Queries can simply use a 2-tier model with persistent views.

The video of the talk is available on Skills Matter website.

Presentation notes: (those are Udi’s ideas rephrased with my own words…)

Queries

  • Data is always stale, but why not show how stale it is with a timestamp? Doesn’t cost anything.
  • Representing data with objects is a bit of a waste because as far as queries go, data is not an object, it has no behaviour, it’s just data!
  • Consequence: go back to the simplest thing that works, the 2-tier architecture. 
  • The UI can talk directly to the DB since layers don’t add any value to queries. For each view in the UI there is one persistent view in the DB. The UI does a simple select *, no calculation. The persistent views have a column for every piece of data to be shown in the UI view.
  • Data duplication between persistent views is fine. Entities are covered separately by an OLTP model.

Search

  • Avoid generic search screens that allow users to compose an ad-hoc query with plenty of fields. Focus on the user’s intent only: design the most likely queries to be used and make them available by default with very limited amount of parameters.
  • For anything that’s not covered by a pre-designed query, use a very simple google-style 1-field full text search. You’d need a data model dedicated to this kind of search (SQL Server full-text search service for instance).

Persistent view model

  • The views don’t need foreign keys, but they do need indexes.

Security

  • Use the database for role-based access: user, superviser, each one has its own view with its own set of columns. Data is duplicated but that’s ok.
  • That’s actually more secure than a memory-based web cache.

Validation

  • Use the persistent view model to do preliminary validation (as the user types his name for instance). No need to wait until submission.
  • Validation is done within components identical on the client and the server.
  • Examples of things that can be checked early: uniqueness, related entity existence…
  • Validation result in correct in 99% of cases, which is good enough for preliminary validation. The purpose is to answer the question: does the data have chances to be good?
  • Validation does not have to be mixed with business rules: ranges, lengths, etc…

Commands

  • Commands encapsulate the business rules.
  • Rules answer the question: should we do this based on what’s currently in the DB?
  • Commands can use the usual UI/Services/Business Logic/DAL layers.
  • Because commands are successful most of the time you can get away with giving an immediate positive answer to the user. Notify him asynchronously if something goes wrong (per email for instance). “Thank you, we’ll let you know if there is a problem”.

User interface design

Tips to capture the user’s intent in the UI while taking advantage of the preliminary validation on the client:

  • a grid should be able to accept a column and reject another. There is not necessarily a transaction at the row level. Changing a user’s status is a different task from changing a shipping address and can be done separately.
  • a reservation system should allow people to book blocks of seats rather than forcing the user to tick seats individually until the finds an available block. The system could even look for an available block and notify the user when one is found. A good command ends with: “Thanks, you’ll get a confirmation soon”.
  • posting a comment to blog. The best way to confirm is to display the user’s comment in the page. You can do that on the client directly, no need to wait until the server updated the page.
  • cash machine: you can do a preliminary validation too (credit card valid, user authenticated, yesterday’s balance good…). If the balance was not good and the user is overdrawn, no big deal, it makes money to the bank anyway (just make sure there is a clause in the credit card’s small print).

Domain Models

  • They are not for validation (use components instead), not for queries (remove all objects used only to pull data and use a persistent view model instead).
  • Keep the domain model for the interesting stuff: the business logic. Remove from the domain model everything (tables or columns) that’s not directly used by business rules.

Sunday, 7 February 2010

Coding in Istanbul 3: Pair Coding with a Friend is Fun

Helping Jeff with his PHP work was a chance to practice some pair coding. I don’t get to do this at work!

I know Jeff since the engineering school. We graduated from the same place in Paris. At the time (about 14 years ago) we were always coding in pairs: nothing to do with agile, we simply had to! The school labs were equipped with one PC/Solaris station for two people at best. We often had to finish projects late at night. Eating pizza at someone’s place, three or four people on the same computer. Of course we couldn’t afford laptops. I even remember having to carry around my tower PC to a mate’s flat in order to finish a late project! Those were tough times… and pairing with people was natural: it didn’t look like an exotic feature from a new methodology. It was just what all students did. 

During our excursions in the coffee-shops and restaurants of Istanbul we both have our netbook. We tried phases where we worked separately, Jeff coding and me looking up some info. But what turns out to work best is to code on the same netbook taking turns at the keyboard. Less chances to get distracted this way. If one loses focus, the other puts him back on track. If one does a typo the other spots it immediately. If we both loose focus we just order another Latte.

We can sustain the pace for about two hours before we become useless.

Quite a good laugh actually…  Just like good old times! Too bad we don’t do that at work…

Tuesday, 2 February 2010

Coding in Istanbul 2: Reverse Engineering a LAMP Project

DSC_9879 (640x426)

We had a salad at Belvu restaurant, Fenerbahçe then carried on coding in True Blue, a cafe overlooking the Sea of Marmara with a nice view to the Princes Islands.

The stack of Jeff’s site is based on PHP/MySql/Apache. I’m more used to the world of C#/ADO.NET/Linq/T-SQL/SQL Server.

It’s funny how web development differs from enterprise apps!

I got into the habit of encapsulating everything and separating layers but the approach used by some PHP devs is more pragmatic. Business logic, data retrieval, building SQL queries and presentation: everything is done in the same .PHP file!

In Windows client development you typically let a data layer retrieve some data objects (via ADO.NET, Linq or something else) then you assign the data object to a grid control. The control takes care of displaying the content of the object, dynamically creating columns and adding rows… In the PHP files I saw the data layer bit (building the SQL, performing the query, retrieving data) appears just a few lines before a while loop that echoes  <td> tags to generate a table for each row of the result set. All layers in the same place.

Also in the code I saw SQL queries were always built on the fly. The first downside of building SQL queries with string concatenation is vulnerability to SQL injection (followed by performance loss due to always rebuilding the query plan and no transactional integrity)… The devs protected the code from injections by using specific PHP functions that parse all user inputs. Why not use stored procedures? Apparently stored procedures are a new thing in MySql: they arrived only in version 5. So I guess they got into the habit of doing away without them.

Regarding the development tools, when working with PHP in Dreamweaver -apart from a bit of color coding- you get absolutely ZERO compiler support. Indentation is manual and there is no intellisense. Comes pretty close to handcarving on stone tablets.

Another funny thing with MySQL: it comes with a large choice of database engines, each one having its pros and cons. It turns out that the default db engine in MySQL is optimised for speed and does not support foreign keys. So by default you work in a system where you can delete parents without deleting childrens and where children can contain a reference to a non existing parent. You’d better be sure that’s what you want, most of the time it’s not…