Commerce Server as a Repository
Working with Enterprise Applications like large e-commerce sites often requires interaction with different systems for different purposes, like:
- Retrieving catalog data (products and categories)
- Retrieving customer information
- Retrieving inventory skus
- Retrieving prices
- Sending fullfilled orders
- … and the list continues …
In Vertica most of our projects are based on the principles of Domain-Driven Design. In short DDD is all about keeping the focus on the domain – e.g. a B2B-driven e-commerce site. The way we structure Commerce Server is to look at Commerce Server as a number of repositories applying the Repository Pattern. That means that we have somewhat few classes that encapsulate all Commerce Server specific logic and return not Commerce Server data types (Microsoft.CommerceServer…*) but data types that we have defined in our own application.
This is illustrated in the image below.
- We need to map from Commerce Server types (ICommerceEntity in CS 2009)
- Solution: We have created functionality that based on attributes and conventions can do the mappings automatically
- All Commerce Server code/queries are encapsulated in few classes
- Not all developers need to know about Commerce Server
- Upgrading to newer versions becomes less painfull
- Commerce Server repositories are mockable allowing us to unit-test functionality in caller classes
- We cache only lightweight objects that we own and not the large DataSets returned by Commerce Server
- We can use distributed caching
Properly there are more pros and cons than mentioned above. Please feel free to add your comment on this.
My point is that while Commerce Server is definitely a great platform and a good investment, and I’ll explain why I think so in the section below, it is reasonable to think outside the box when you develop your application. You don’t need to store anything in Commerce Server and you don’t need to spent that much time with their API’s rather than spending the time on the actual feature that you are implementing.
Commerce Server as a platform provides data storage, end-points and APIs for many of these purposes via the different subsystems (Catalog System, Orders System, Marketing System etc.). Most of these subsystems can be widely extended to fit business requirements, like having different product types, customized order schema and custom data entities. Also the product comes with out of the box client tools that that supports working on these different entities in Commerce Server, like creating products in Catalog Manager, viewing orders in Customer and Orders Manager and setting up campaigns in the Marketing Manager.
This is great stuff. If we were to implement the functionality that Commerce Server offers by ourselves most of us properly would not have gotten further than implementing a basic catalog system that could handle multiple products in multiple categories for the same budget than if we had bought a standard license to Commerce Server.
You can build a complete webshop by just utilizing the various components and subsystems in Commerce Server. Microsoft did it in Commerce Server 2007 with the ASP.NET StarterSite. In Commerce Server 2009 they did it again with the StoreFront/Contemporary Site in SharePoint/MOSS.
The problem is that in real world projects the business requirements to presenting data are often quite different that what can be expressed in e.g. a Catalog System. Pricing is one example. In Commerce Server a price is expressed as a single property on a product/variant in the Catalog System. If you add this product to your basket, the price will automatically be set on the Line Item. If you are building an international e-commerce site you properly need to express your price in different currencies. To do that, you would have to create different virtual catalogs, and your application logic would have to adapted to that making your design more complex and harder to maintain. Another scenario is when your price is dependent on the customer buying it – again you would need to have customer specific catalogs and maintain the prices there. In most of the B2B sites that I’ve seen prices are not even “static data” stored in some database, instead they are requested at runtime from the back-end ERP system.
To address the problem with custom pricing we need to tweak Commerce Server to override the price retrieved from the Product in the Catalog System with a price coming from ERP. This can be accomplished by creating a simple pipeline component.
As mentioned earlier there are many ways to extend Commerce Server to fit your business needs. The Profiles System allow you to create new data entities if you need to store custom data, like users, logins, roles, accounts, gift certificates, <insert data here> and the API on top supports all CRUD operations and returns .NET objects (like what you would expect from any ORM – object relational mapping software . While this might sound great: that you can extend and store any data that you would like in the Profiles System, it comes with a price. The price is bad performance (using non-parameterized OLEDB-queries, really bad support for one-to-many/many-to-many relationsships and cumbersome and ineffective extensibility/development model. And why would you even consider using anything remotely cumbersome when we have ORMs frameworks like Castle Active Record, NHibernate and Entity Framework to just name a few that very easily allows you to map data from a database and into your domain?
Besides using a ORM instead of the Profiles System we use and apply a number of different technologies and principles in our applications, like:
- Clean separation of UI and model
- Dependency Injection pattern
- With a Inversion of Control container in place
- With Mocking framework in place
- Aspect Oriented Programming – DynamicProxy
- Domain Events
I hope to see some comments on this blog-post as application design usually is very subjective 🙂
Brian Holmgård Kristensen