Showing posts with label Architecture. Show all posts
Showing posts with label Architecture. Show all posts

Monday, 25 June 2012

Using the CachingHandler in ASP.NET Web API


Introduction


[NOTE: Please also see updated post and the new framework called CacheCow
This class has been removed from WebApiContrib code and NO LONGER SUPPORTED]


[Level T3] Caching is an important concept in HTTP and comprises a sizeable chunk of the spec. ASP.NET Web API exposes full goodness of the HTTP spec and caching can be implemented as a message handler explained in Part 6 and 7. I have implemented a CachingHandler and contributed the code to the WebApiContrib in GitHub.

This post will have two sections: first a primer on HTTP caching and then how to use the handler. This code uses ASP.NET Web API RC and with .NET 4 (VS 2010 or 2012).

Background

NOTE: This topic is fairly advanced and complex. You do not necessarily need to know all this in order to use CachingHandler and are welcomed to skip it but more in-depth knowledge of HTTP could go a long way. 

Caching is a very important feature in the HTTP. RFC 2616 extensively covers this topic in section 13. Review of all the spec is beyond the scope of this post but we will briefly touch on the subject.

First of all let's get this straight: this is not about putting an object in memory as we do with HttpRuntime.Cache. In fact server does not store anything (more on this below), it only tells the client (or mid-stream cache or proxy servers) what can be cached, how long and validates the caching.

Basically, HTTP provides semantics and mechanism for the origin server, client and mid-stream proxy/cache servers to effectively reduce traffic by validating the version of the resource they have against the server and retrieve the resource only if it has changed. This process is usually referred to as cache validation.

In HTTP 1.0, server would return a LastModified header with the resource. A client/user agent could use this value and send it in the If-Modified-Since header in the subsequent GET requests. If the resource was not changed, server would respond with a 304 (Not Modified) otherwise the resource would be sent back with a new LastModified header. This would be also useful in PUT scenarios where a client sends a PUT request to update a resource only if it has not changed: a If-Unmodified-Since header is sent. If the resource has not changed, server fulfils the request and sends a 2xx response (usually 202 Accepted) otherwise a 412 (Precondition Failed) is sent.

For many reasons (including the fact that HTTP dates do not have milliseconds) it was felt that this mechanism was not adequate. In HTTP 1.1, ETag (Entity Tag) was introduced which is an opaque Id in the format of a quoted string that is returned with the resource. ETags can be strong (refer to RFC 2616 for more info) or weak in which case they start with w/ such as w/"12345". ETag works like a version ID for a resource - if two ETags (for the same resource) are equal, it means those two versions of the resource are the same.

ETag for the same resource could be different according to various headers. For example a client can send an Accept-Language header of de-DE or en-GB and server would send different ETags. Server can define this variability for each resource by using Vary header.

Cache validation for GET and PUT requests are similar but instead will use If-Match (for PUT) and If-None-Match (for GET).

Well... complex? Yeah, pretty much and yet I have not covered some other aspects and the edge cases. But don't worry! You will be abstracted from a lot of it if you use the CachingHandler.

Using CachingHandler right out of the box

OK, using the CachingHandler is straightforward especially if you go with the default settings. You can have a look at the CarManager sample in the WebApiContrib project. CarManager.Web sample demonstrate server side setup of the caching and CarManager.CachingClient for making calls to the server and testing various caching scenarios.

All you have to do is to create an ASP.NET Web API project and add the CachingHandler as a delegating handler as we learnt in Part 6:

GlobalConfiguration.Configuration.MessageHandlers.Add(cachingHandler);

And you are done! Now let's try the server with some scenarios. I would suggest that you use the CarManager sample, otherwise create a simple handler and implement GET, PUT and POST on it.

Now let's make some request and look at the response. I would suggest using Fiddler or Chrome's Postman to send requests and view the response.

So if we send a GET request:

GET http://localhost:8031/api/Cars HTTP/1.1
User-Agent: Fiddler
Host: localhost:8031

We get back this response (or similar; some headers removed and body truncated for clarity):

HTTP/1.1 200 OK
ETag: "54e9a75f2dbb4edca672f7a2c4a73dca"
Vary: Accept
Cache-Control: no-transform, must-revalidate, max-age=604800, private
Last-Modified: Thu, 21 Jun 2012 23:35:46 GMT
Content-Type: application/json; charset=utf-8

[{"Id":1,"Make":"Vauxhall","Model":"Astra","BuildYear":1997,"Price":175.0....

So we see the ETag header here along with important caching headers. Now if we make another GET call, we get back the same response but ETag and last modified stays the same.

Generating same ETag is fine (showing our CachingHandler is doing something) but we have not yet seen any caching. That is where client has to do some work to do. It has to use If-None-Match with the ETag to conditionally ask for the resource: if it matches server, it will get back 304 but if not, server will return the new resource:
GET http://localhost:8031/api/Cars HTTP/1.1
User-Agent: Fiddler
Host: localhost:8031
If-None-Match: "54e9a75f2dbb4edca672f7a2c4a73dca"
Here we get back 304 (Not modified) as expected:
HTTP/1.1 304 Not Modified
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
ETag: "54e9a75f2dbb4edca672f7a2c4a73dca"
Server: Microsoft-IIS/8.0
Date: Sun, 24 Jun 2012 07:34:29 GMT

A typical server that can use CachingHandler

CachingHandler makes a few RESTful assumptions about the server for effective caching. Some of these assumptions can be overridden but generally not recommended. These assumptions are:

  • HTTP verbs (POST/GET/PUT/DELETE for CRUD operations) are used to modify resources - and not RPC-style resources (such as POST /api/Cars/Add). This is the most fundamental assumption.
  • All resources are to be modified through the same HTTP pipeline that implements caching. If a resource modified outside the pipeline, cache state needs to be updated by the same process.
  • Resource are organised in a natural cache-friendly manner: invalidation of related resources can be done with a minimal setup (more details upcoming).

Defining cache state

As we said, this has nothing to do with HttpRuntime.Cache! Unfortunately ASP.NET implementation makes it really confusing between the HTTP cache (where the resource gets cached on the client or midstream cache servers) and server caching (when the rendered output gets cached on the server).

Cache state is a collection of data that helps keep track of each resource along with its last modified date and ETag. It might initially seem that for a resource, there exists a single of such pieces of information. But as we touched upon above, a resource can have different representations each of which needs to be stored separately on the client while they will most likely invalidated together. 

For example, resource /api/disclaimer can exist in multiple languages as such client has to cache each representation separately but when disclaimer changes, all such representations need to be invalidated. That will require a storage of some sort to keep track of all this data. Current implementation comes with an in-memory storage but in a web farm scenario this needs to be a persistent store.

Cache state storage and cache invalidation

So we do not need to store the cache on the server, but we DO need to store ETag and various states on the server. If we only have a single server, this state can be stored in the memory. In a web farm (or even web garden) scenario a persisted store is needed. This store is called Entity Tag Store and is represented by a simple interface:

public interface IEntityTagStore
{
 bool TryGetValue(EntityTagKey key, out TimedEntityTagHeaderValue eTag);
 void AddOrUpdate(EntityTagKey key, TimedEntityTagHeaderValue eTag);
 bool TryRemove(EntityTagKey key);
 int RemoveAllByRoutePattern(string routePattern);
 void Clear();
}

We need to have an implementation of this interface so that the cache management can be abstracted away from controllers and instead done in the DelegatingHandlers.

Introducing some concepts (you may skip and come back to it later)

This store will keep track of the Etag (and related state stored in TimedEntityTagHeaderValue) based on an Entity Tag key which is calculated based on the resource URI and content of the important headers (which their list will be on the Vary header). In-Memory implementation for a single server is provided out of the box with CachingHandler - I would be creating a SQL-Server implementation of it very soon; watch this space.

It is important to note that change in the resource will most likely invalidate all forms of the resource so all permutations of important headers will be invalidated. So invalidation is usually performed at the resource level. Sometimes several related resources can be represented as a RoutePattern. By default, URI of a resource is its RoutePattern.

Also in some cases, change in a resource will invalidate linked resources. For example, a POST to /api/cars to add a car will invalidate /api/cars/fastest and /api/cars/mostExpensive. In this case, "/api/cars/*" can be defined as the linked RoutePattern (since /api/cars does not qualify for /api/cars/*).

Some assumptions in CachingHandler

  1. Re-emphasising that resource can only change through the HTTP API (using PUT, POST and DELETE verbs). If resources are to be changed outside the API, it is responsibility of the application to use IEntityTageStore to invalidate the cache for those resources.
  2. If no Vary header is defined by the application, CachingHandler creates weak ETags.
  3. Change in the resource will invalidates all forms of the resources (all permutations of important header values)

CarManager sample

I have considered a pretty complex and interrelated routing and caching requirement for the sample to display what is possible. Resources available are:

  1. /api/Car/{id}: GET, PUT and DELETE
  2. /api/Cars: GET and POST
  3. /api/Cars/MostExpensive: GET
  4. /api/Cars/Fastest: GET
So creating a car would invalidate cache for 2, 3 and 4. Updating car with id=1 invalidates 2,3 and 4 in addition to the car itself at /api/Car/1. Deleting a car will invalidate 2, 3 and 4.

The client sample (CarManager.CachingClinet) displays how to call the server with headers to validate the cache.

Configuring CachingHandler

Best place to start is the CarManager.Web sample to give an idea on how various setup can be used to configure complex caching requirements. Basically the points below can be used to configure the CachingHandler

Constructor

A list of request header names can be passed that will define the vary headers. If no vary header is passed, system only generates weak ETags. Also optionally an implementation of IEntityTagStore otherwise by default InMemoryEntityTagStore will be used.


EntityTagKeyGenerator

This is an opportunity to provide linked resource for a resource.

 Other customisation points

CachingHandler provides properties in the form of functions with default implementation that can be changed  to override the default behaviour which we will cover in the upcoming post on "Extending CachingHandler".


Conclusion

CachingHandler is a server-side DelegatingHandler which can be used to abstract away caching from individual ApiControllers so that controller logic can be coded without having to worry about caching. 

The  code is hosted on GitHub (currently sitting at my fork waiting to be merged merged!) and comes with both a client and server sample - CarManager.Web and CarManager.CachingClient.

Friday, 8 June 2012

What I think coupling is ...

Introduction

[Level C3] This post is a follow-up to the question/discussion-point Darrel Miller has started here. The question is that in the REST world, what is coupling and how we can achieve de-coupling. Although this post can be read independently, it is best to start with reading his post first. [This discussion carries on in the next related post]

Motivation

REST has a strong focus on decoupling client and server. With REST awareness and adoption increasing, the challenge to define new best practices has now become more apparent. This is particularly important in the light of how much nowadays can be achieved in the browser - a previously limited client. Rise of the Single Page Applications (SPAs) is a testament to the popularity of creating a rich-client in what was previously called thin-client. Diversity of available clients and their capabilities have - in a way - forced us towards REST and achieving de-coupling of client and server. 

But recently, some have felt that too much power and control has shifted towards the client and the server has been reduced to mere a data provider. One of such groups is ROCA that defines a set of best practices that are in clear opposition to SPA paradigms. I actually meant to have a post on ROCA (which I hopefully will soon) but I suppose this post can be a primer as the issue at question is relevant.

Background

Darrel defines coupling as "a measure of how changes in one thing might cause changes in the other". I would very much go with this definition but I would like to expand upon.

Coupling is a software design (logical) and architecture (physical) anti-pattern. Loose-coupling is on the other hand  a virtue that allows different compartments (intentionally avoiding using bloated words module or component) of the system to change independently. 

In the world of code (logical), we use Single-Responsibility principle (S from SOLID) to decouple pieces of code: a class needs to have a single reason to change. Arguably, rest of the SOLID principles deal with various degrees of decoupling. For example D is for not baking the dependency.

On the other hand, in SOA (physical) we loosely-couple the services. Services can be dependent on other services but they would be able to maintain a reasonable level of functionality if other services go down. The key tasks in building a successful SOA is defining service boundaries. Another important concept is achieving cohesion: keeping all related components of the service in the same service and resisting to break a service into two compartments when boundary is weak.

Defining boundary and achieving cohesion

Coupling in other words is baking knowledge of something in a compartment where it is concern of another compartment.

When I buy stuff from Amazon and it is delivered when I am not at home, they leave a card with which I can claim my package at the depot. The card has just an Id in the form of barcode. It does not have the row and shelf number my package is kept at the depot. If it had, it might have made it easier for the clerk to use the numbers on the card to fetch the package. But this way I am baking the knowledge of location into something it does not need to know and what if they had to change the location of the package? That is why the clerk zaps the barcode and location is shown in the system. They can happily change the location as long as the Id does not change.

On the other hand, the depot does not need to know what is in the package - it is not its concern. If it did, it might have been helpful in rare scenarios but that is not worth considering.

So the key to defining boundary and achieving cohesion is to understand whose concern it is for an abstraction. We will represent 3 models here: server-concern, client-concern and mixed-concern. In brief, it depends.

Server-Concern

In this case, only server needs to know about an abstraction. The problem happens when the concept oozes out to the client when client gets to know server implementation details (exposing server bowels).

Server-Concern
Server-Concern

Example

A typical example is getting the list of most recent contacts:
GET /api/contacts?lastUsedMoreThan=2012-05-06&count=20
GET /api/contacts/mostRecent 
In the first case, client gets to know that server keeps a value of lastUsed for contacts. This prevents server to optimise the algorithm by also including number of times we have used the contact. However, in the second case server hides its implementation so the change can be implemented without breaking the client.

Client-Concern

In this scenario, the abstraction is purely a client concept. The problem happens when server starts to make decisions for the client.

Client-Concern
Client-Concern

Example

A typical example is pagination:
GET /api/contacts/page/11
GET /api/contacts?skip=200&count=20
Number of pages available and number of each record in a page is a client concern. This kind of detail will be different on the iPhone from the desktop from the tablet (and what tablet). In the first case, server will make a decision on the number of records per page (and even understands the page as a resource) while in the second case, knowledge of pagination is confined to the client since it is its concern.

Mixed-Concern

In this scenario, both server and client need to work in accord for the feature to work. The problem happens when server or client assumes that the other definitely implements the abstraction.

Mixed-Concern
Mixed-Concern

Example

A typical example is HTTP caching. For HTTP caching to work, client and server need to work in tandem. Server needs to return with each resource, a Cache-Control header, an ETag or a LastModified and the client needs to use these parameters in its future conditional requests with If-Modified-Since or If-None-Match. 

Works
No assumption in implementation on the other side
helps both sides to carry on working without the feature


However, if server does not provide caching or the client does not use and respect the caching parameters from the server, system does not break - albeit it can result in an inferior or suboptimal experience.

Diversity and compromise

While we can have 3 above models, there are cases where same feature can be implemented differently. 

Let's bring an example from engineering. Where do you put AC/DC power transformer? My PC has the transformer in its power supply (item 6) which is equivalent of Client-Concern. My laptop uses a power adaptor and has no mains supply which is equivalent of Server-Concern. On the other hand, my electrical toothbrush has divided the transformer into both charger element and also inside the toothbrush so it works by magnetic induction (analogous to mixed-concern). This is clearly a compromise but the thinking behind it is make the toothbrush waterproof and safe.

Conclusion

Darrel's definition is excellent but we have expanded upon it since the change (maintenance) is one facet of the same concept. Others are concern (requirement) and knowledge of that concern in a compartment (implementation).

We discussed three models: server-concern, client-concern and mixed-concern. Each of these are valid patterns but they each come with its own anti-pattern to be aware of. So in short: it depends.

Saturday, 21 April 2012

Web API Governance - Life in a schemaless world (Take 2)

Introduction

[Level C4] While classic web services used WSDL for their schema and description, emerging Web API mainly relies on documentation. This requires human effort and with the rising popularity of Web API it could create problems in maintenance, change management and extension of Web APIs. The solution is automation and this article reviews challenges and possible solutions.

Rise of the Web API


NOTE: This is take 2 of my post, with some updates.

I am very excited at the moment. Microsoft has just released its beta version of its best HTTP implementation to date. ASP.NET Web API has embraced HTTP exposing its full goodness. No more clutter of SOAP-based RPC services. Lean and mean.

So life cannot be any better? Hmmm.. it can! Away from all the hustle and bustle and buzz of the REST APIs (whether they are really RESTful is another discussion which to be frank I am not interested any more), it is important to be objective and almost clinical about the technology. It is important to be able to look back, and see how far we have come so far and yet learn lessons from the past and use the solutions of the previous generation if they are still relevant (in IT terms it is 5-10 years depending on the technology).

There has been a movement in the industry to question the basics. This is good, it weeds out unnecessary abstractions. We have had RDBMS for years now we want NoSQL. We have had XML/SOAP now we want JSON. We have had complex layered server side architecture now we want close to the metal, like node.js or sinatra/nancyfx. Scripting was bad, type safety was good and now scripting is good and everyone wants to escape type safety.

OK, we have had SOAP services and we have never been happy with them. They were clunky, heavy and complex. Now we got Web API which is so much better. But let's have a look at the problems that classic Web Services started tackling and in fact, did a good job in some cases.

Governance in Web Services

This is an SOA term that revolved around managing and organising web services in a consistent fashion. This  would protect the clients as well as allowing the vendors to manage the life of the services. 

Some of the aspects of Governance include:
  1. Contract and description: mainly through WSDL
  2. Registry service and discovery: mainly through UDDI and later WS-Discovery
  3. Versioning
  4. Exception handling
  5. Security and access control: mainly through Web Service Extensions and later WS-Security
To be fair, the work in the area produced some useful technologies and standards. One problem being they are mainly based on the RPC style web services as such not quite useful in the REST style Web API. The issue is problems do still exist and question is whether we do have appropriate tools to address them.

What did we lose on the way?

OK, I am trying to imagine 3 years from now - I am sorry but I see chaos. A good proportion of existing Web Services will be moved to pure HTTP Web APIs. I think it is very likely that the RPC mentality stays with the developers and we end up with RPC style Web APIs. And now what? We are even more vulnerable with no classic Governance safety net.

With classic web services (and WCF), all you needed to point to a web service was its WSDL. It would provide the contract, schemata, faults, security requirements, endpoint addresses and some description. If you would update your service, the WSDL (which it could be generated on the fly) would be updated. In fact in most cases all you needed was the service endpoint address, from where you could get all informations you needed (e.g. by just placing ?wsdl at the end of the address).

We do have some replacements here in HTTP APIs. For example, we do not need SOAP fault to be defined in the WSDL, since we have HTTP error codes. We do not necessarily need WS-Security as we have OAuth/OpenID/etc token based federated security. Discovery is not really a big issue and hypermedia can help in this regard. 

OK, the question is do we need all that stuff? REST (and HTTP as its sole implementation) is Turing-complete. An agent should not need any priori knowledge to be able to use a service. It can use OPTIONS to discover verbs, it can use content-negotiation to ask for media types it can understand and use hypermedia to navigate through the resources of a server.

Turing-completeness is great but to be honest, it still belongs to Sci-Fi novels. We are not there yet. I believe for great development experience and maintenance, we still need schema. Most web APIs are about interacting with data. Probably somewhere around 80-90% of Web APIs out there serve JSON. What does application/json content type exactly tell about the actual JSON being served? Are we currently writing agents/applications that can intelligently adapt and consume whatever JSON being served to them? 

I was listening to one of the episodes of MashThis podcast and the theme that was coming on good Web API was always good documentation. Nothing beats a good documentation but how many of us developers are good in this? Human effort to create and maintain a good documentation covering schema and description is going to be big. I think we need some automation here.


Challenges

I originally suggested using media types so that client could request not the data but the schema of the data. In this update, I am going to look at other options as well as semantic challenges for providing schema and description. In fact, I am not going to propose a solution, I will use this post to describe the problem. I hope this will start a fruitful discussion so please feel free to join in.

HTTP and schema?

Schema for an HTTP API (intentionally not using the word REST API) might initially seem a little bit odd. Actually the word does not appear at all in the RFC 2616. As far as the HTTP is concerned, server will allow the agent to interact with the resource using URI using the verb and associated headers. It is up to the agent to engage in content negotiation and interpret the result.

I personally think the problem of schema and description is inherently orthogonal to HTTP. A resource does not necessarily have to have a schema - other than the schema assumed by the content-type. For example, when a server responds to a GET request for an XML page using /foo/api/2 URL, it just serves the page which ideally is conformant to XML schema. But even well-formed XML does not explain enough about the structure of the document and its internal schema. In fact XML instance will contain its schema but server (unlike RPC style web services) might not able to return an XML schema - since /foo/api/3 might have a completely different schema.

But let's bear in mind this can simply be an option. Server might support the schema/description and return, or it can return a 404 error. In fact, schema can be service-specific or URI specific, i.e. it could refer to /foo/api/{id} or /foo/api/690. In this case, while schema is relevant for different ids (as they have different schema), service description will be the same. Hence any solution must consider this variability.

URIs and URIs routing formats

It is very common in the Web API space to provide URIs containing placeholders to pass data fragments to the API. In our example, /foo/api/690 means id=690. Alternatively, data could be sent as query string parameter such as /foo/api?id=690.

The schema or description could be different based on the parameters passed.

One issue to be considered is that it is possible agent does not know about an actual existing resource (for example does not know a valid id to be passed to return an actual resource) and all it knows is the URI format. Solution must be flexible enough to provide a schema for the API method if a generic schema exist for the URI format (i.e. all documents at /foo/api/{id} have similar schema)

Priori knowledge

One of the main focuses of HTTP spec is to remove the requirement of the priori knowledge from the agents. Agent is encouraged to explore server resources and functionality (e.g. OPTIONS) and server guides the agent using hypermedia.

With developing Web API that requires documentation, we are adding back this priori knowledge requirement. This is not good. But in the absence of a standard we will end up with nothing much better than a convention - which itself is a priori knowledge. So ideally this process must involve a standard or even a standard proposal. A lot of useful technologies out in the cloud are still in the proposal phase, namely OData, JSON Schema and HAL.

Security

A schema must ideally provide a detail on the security requirements of the service. This is especially important for authentication schemes supported by the server (e.g. basic authentication, federated identiy, etc).

Schem and description as a single resource?

Decision needs to be taken to whether serve description and schema of the service separately or provide them as a single document. The more I think about it, the more I feel it probably has to be a single document.

Possible Solutions


1- Using content type

Since JSON and XML are two most popular formats being served, for now serving schema can practically be limited to these media types.

Let's Look at this request:
GET http://localhost:50459/api/HelloWorld/1.1
User-Agent: Fiddler
Host: localhost:50459
And response is:
HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Tue, 17 Apr 2012 21:46:38 GMT
Content-Type: application/json; charset=utf-8
Connection: Close 
"This"
So as we can see, media type returned is JSON and the value is a simple string. Now if we send a request asking for a JSON schema with accept header of  application/schema+json, we get back this:

GET http://localhost:50459/api/HelloWorld/1.1
Accept: application/schema+json
Host: localhost:50459 
And response is:
HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Tue, 17 Apr 2012 21:46:38 GMT
Content-Type: application/schema+json; charset=utf-8
Connection: Close 
{
  "type": "string"
It is true that JSON schema is still in draft status but with this format becoming more and more popular, it is inevitable that we restore some structure in our Web API.

Since XML already has an established schema language, we can use XML Schema but one problem is that XML Schema has a content type of application/xml or text/xml. So either we nominate an alternative content type (such as application/schema+xml) or use URI to denote request for schema (ideally in the format of optional query string parameter although that will still be part of the URI).

Same applies to the description of the service. It is ideal that the documentation of the service id provided by the service itself. For description, agent can use a special content type (for example x-text/docs) or using a query string parameter.

2- Using hypermedia

Server can include separate links to schema and description while serving the actual resource. Payload can be HAL or alternative implementations of hypermedia.

A HAL payload can look something like:

{
  "_links": {
    "description": { "href": "/description" },
    "schema": { "href": "../../schema?type=MyDto" }}
  },
  "_embedded": {
    "MyDto": [
...

Server could have an implementation convention to treat description and schema URL fragments as special paths and serve appropriate resources. Please note that all the data needed to provide the schema could be located in the URL, e.g. type of the serialised payload is appended as a query string parameter so the server does not even have to know about the API method queried about.

This imposes a burden on the agent to understand such complex structures.

Also bear in mind, an ideal solution must be able to explain the output schema as well as input schema. For POST and PUT verbs, a JSON payload could be sent to the server to be stored and server must be able to provide not only the output but also input schema.

3- Using a URL convention

Basically in this solution, agent has a priori knowledge of a convention (or a standard) by which can interrogate the server and ask for schema and description of the services available on the API server. For example /foo/api/$list could provide a list of methods (I know, it sounds like RPC but I have no better word) avilable on the server. $schema can provide the schema and $description the description for the service.

Conclusion

Web API needs to look back and consider solving some of the problems solved by classic Web Services. It is very likely that with the migration of classic web services to Web API we find ourselves in a chaotic situation. This area needs to be explored and all options to be considered hence a debate on the subject is welcome. It is likely that we might need a convention/standard for describing our Web APIs.

Sunday, 25 March 2012

Dependency Injection for Singletons

[Level T2]

This is more of a hypothetical and perhaps philosophical question, but anyway I will shoot:
Now that most DI frameworks support singleton lifetime would you still manually implement the Singleton pattern?
I have seen a lot people answering NO to the question. They believe that the decision to use a singleton pattern can change and changing the lifetime of the object is just change in one line of code or configuration.

But I would answer YES.

Reality is, the reason to use Singleton pattern is usually:

  • Creating the object is expensive
  • Object uses (and commonly caches) data that are expensive to create
  • Object has to collect and keep some state/statistics
Which of above is likely to change over time? I would say practically none. When relying on DI frameworks to do the singleton pattern for you, your class loses its design coherency when it does not communicate its need to be implemented as singleton.


So I personally would implement the Singleton pattern and then register the instance (this is Windsor):

UniversalContainer.Container.Register(
    Component.For<IXsltTransformer>()
    .Instance(XsltTransformerWithCaching.Current)); // .Current is the singleton instance 

As it can be seen, the class XsltTransformerWithCaching is responsible for performing XSLT or XML documents. As we all know, XSLT processor in C# spits out the code for the transformation and builds an assembly at runtime (similar to Serialisation) and if done over and over again, it can cause "memory leaks". As we all know, once an assembly is loaded, it cannot be unloaded - and do not ask for it, it cannot be done.

So I would prefer to bake the singleton into the class.