5

In the previous months I have been asking a lot of questions concerning the architecture of an application I'm working on. Thanks to the answers the architectural design has changed - in fact, it has really been simplified as shown in the following graph:

architecture

Internally I have a two services (NOT WCF!) that follow CQS principles. It means that the query service simply returns database views; while the command service has a full domain model that contains all business logic, and repositories to access the database (no event mechanism or other complex pattern here). Both services use the same database. These services are class libraries, NO WCF services, because they are used only internally so I don't need the overhead of WCF (don't distribute your objects, Martin Fowler's first law).

These internal operations are used by the ASP.NET MVC site and the PartnerService. This PartnerService is a WCF service, which exposes the functionality I would like to be exposed to partners.

If I ever need to scale because of high traffic, I could add web servers and/or migrate parts to a full CQRS system (my contracts are already designed for it).

Does anyone see any problems with this?

One thing I see is that if the query or command service changes, this impacts both the web site and partner service directly, so I have to deploy the changes to both. But I don't know if this is an issue...?

Any feedback is appreciated! Thanks!

Byrne Reese
  • 1,057
  • 1
  • 12
  • 16
L-Four
  • 333
  • 2
  • 10

3 Answers3

4

I think you are on to a winner here.

You have several options for scaling (from easiest to requires some effort).

  1. Buy a bigger machine.
  2. Run each component on its own server.
  3. Run more servers for each component (except for the Database)
  4. Replicate the database and service the "visitors" queries from the replication.
  5. Partition the database by "member id" and run several separate instances of the database to service that group of members.

If you need to scale any more then you are "facebook" and can afford a rewrite.

James Anderson
  • 18,049
  • 1
  • 42
  • 72
  • Thanks for the insight! As for your second remark 'Run each component on its own server' -> this would mean that I then turn query service and command service into real WCF services I guess? – L-Four Sep 07 '11 at 05:55
2

One thing you could do to allow a little more flexibility on the query side of things things, is define your contracts with extension points. Fowler discusses this here:

http://martinfowler.com/articles/consumerDrivenContracts.html#ExtensionPoints

It essentially allows you to add properties that are exposed through the service without breaking existing consumers, so if the website needs another property exposed, you can supply it through the service without breaking the partner service.

"This allows the ProductSearch service to return results that include product descriptions, and consumers using the new schema to validate the entire document. Consumers using the old schema will not break, though they will not process the description."

That whole article is a good read wrt services evolving over time.

Paul
  • 161
  • 3
  • Thank you. But the query service would not be exposed using wcf... But I can apply this to the PartnerService, which is wcf, so it is always backwards compatible. –  Sep 06 '11 at 16:08
2

The only question I would have is how the command service processes your commands. Are they handled asychronously or is your client waiting for the command service to process the command and complete the write to the repository before returning an ack/nack? If you're looking for scalability, that may be one area that you could focus on to improve scalability.

Other than that, it looks good on the surface.

Good luck!!

  • That would be asynchronously, the commands don't return anything. Before executing the command, I would make sure that they are valid, the client would for example do something like: if (CanAddCategory(category)) ExecuteCommand(AddCategoryCommand(category)) where CanAddCategory is an operation on the query service and ExecuteCommand is on the command service... –  Sep 06 '11 at 19:06