Domain-Specific Languages
By expressing the behavior of your application in a language that deals directly with your domain, you can effectively guarantee that the part of the application that expresses your intent is correct, even if the underlying implementation is faulty.
Without a domain-specific language, you can rapidly fall into the trap of having your API centered around specific use-cases. Slightly different use cases involve the creation of new methods, resulting in slower development time, excessive function overloading, and parameter creep. If the full scope of domain functionality is extended to clients in the form of a language, clients can compose the appropriate semantic for their particular use-case without service-level modifications. The trick is preventing clients do things they're not supposed to in this highly enabling model. More on that later.
"But Adam," I hear you say. "Imperative semantics don't necessarily imply API creep. You can model your domain with objects, govern transactional behavior with annotations, and keep the methods on those objects tight and relevant."
True. And that's a great way to write libraries. But it's a crappy way to write services.
Client-State-on-Server Antipattern
Consider Facebook, eBay, PayPal. Each of these services provides an API. They're not bad APIs, but they don't fully express the domain exposed on the websites proper. Unlike a traditional client application, the websites don't use the service API. They're tightly integrated at the service level, with service-level presentation and a bagful of use-case-specific AJAX. Since the websites don't need the API, the API can remain impoverished or absent, or, even uglier, simply be a documented, augmented version of the AJAX calls that were originally designed to make the website punchier. I call this the Client-State-on-Server Antipattern.
The problems with server-side MVC approaches extend beyond anemic external APIs. One problem is authentication. What can be done to what by whom is a domain-level concern. Service-coupled approaches, however allow this concern to bleed into the controller layer, and from what I've seen, most web projects gravitate in this direction. To create a degree of separation, some architectures prohibit the controller layer from directly handling domain objects, leading to the creation of managers with clumped sets of use-case-specific methods, divorced from the problem context that inspired the use-case.
Solution to the Antipattern
- Make your website use the same API as everybody else.
- Implement permissions at the domain level.
- Make your API a DSL interpreter, allowing your clients to exercise their domain intent cleanly and concisely in as few requests as possible.
None of these steps are trivial. There are two approaches to enforce #1. The first is to make a traditional MVC application that makes calls to a separate (different VM, different port) domain service. The second approach, which I'm more interested in, is to have all requests to the domain layer be made from the browser, by way of a fully-fledged client-heavy web application enabled by modern JavaScript engines and, nominally, HTML5 features.
In future posts, I'll explore various developer-friendly solutions in this problem space, as well as opportunities for novel architecture projects. I've got some rough design documentation typed up, and many of the concepts therein as well as discourses on relevant extant projects will pop up on this blog in due time. Fans of REST, XPath, cloud computing, parsers, custom editors, GWT, and code generation will all have something to chew on.
No comments:
Post a Comment