Can you build a RESTful Business Logic Layer?
I've built a RESTful service for the Data Access Layer (DAL) of my architecture:
POST http://example.com/data/User
GET|PUT|DELETE http://example.com/data/User/{UserId}
However, for the Business Logic Layer (BLL), a second non-RESTful service is used:
POST http://example.com/accountapi/register
POST http://example.com/accountapi/login
This BLL service, instead of开发者_StackOverflow making calls to the DAL service, it talks directly to the database.
How would you improve this architecture?
- Should the BLL service call the DAL service ?
- Should I drop the DAL service and only expose the BLL service ?
- Should I, somehow, inject business logic on my RESTful DAL service ? If yes, how ?
To answer the main question. No, not really. To answer the secondary questions. None of the above.
REST based architectures do not fit nicely into the standard 3 tier model. The simplistic view of the three tiered model looks like this:
Presentation Layer <-> Business Logic Layer <-> Data Layer
Consider for a moment breaking the presentation layer into two parts,
Rendering Layer <-> User Interface Content <-> BLL <-> DAL
If you think about a regular Web application, the browser takes HTML, CSS and Javascript content and renders them visually in a browser. It is the User Interface Content layer that the REST constraints apply to. This is most obvious if you think about the hypermedia constraint. REST interfaces are mean to be navigated just like user interfaces are. REST interfaces return representations of resources.
REST interfaces should return user interface content that is independent of how the user interface will be displayed.
REST Client <-> REST Interface <-> BLL <-> DAL
In my opinion REST clients come in two forms, either very thin media type rendering engines (e.g. Web browsers) or screen scrapers (spiders, mashups). I use the term "screen scraper" loosely because if you choose your media-types wisely it should be trivial for the client to scrape the data out of your user interface content.
Any attempt to expose Business Logic Layers as REST interfaces usually has a few effects. Developers end up asking how to do transactions in REST. They end up creating huge amounts of coupling between the client and the BLL interface because of the need to expose semantically rich representations. They forget all about the hypermedia constraint, because much of that linking information is not available in the business logic layer. And they start to complain about the performance overhead of HTTP and text based content types.
(1) Avoid having your (non-REST) web service business logic layer make further (RESTful) HTTP requests onto the data access layer. Doing so of course would be less efficient than making direct method calls. But much more importantly, it would require you to deploy the BLL web services and the DAL web services onto separate web server instances (or separate clusters). Otherwise you can have a case where all your HTTP worker threads are busy trying to serve up BLL responses, and each is blocked waiting fruitlessly for a free HTTP worker thread to serve it a DAL response. This can lead to stalls (if you do timeout/retry processing) or outright deadlocks (if you don't).
(2 and 3) If your web service clients need both business logic and data access, provide those as a unified set of services. Internally they both depend on the same data access layer method calls: it's just that the data oriented web service implementations make just one data access layer call while the business logic oriented web service implementations may make many DAL calls. You do most definitely want to structure the BLL and DAL layers separately beneath the web service layer though.
I like to think of the web services as just the part of the presentation layer oriented towards "users" who happen to be other programs.
If this is the same application, then you should probably have the BLL layer call the DAL layer directly in code instead of using a service call again. That would keep it more performant while keeping the fundamental purposes of the code separate (high cohesion).
Probably so. Your services should generally be course-grained components that perform a business function. Saving a user in the database isn't a business function, it's a specific implementation. The Register function abstracts that notion into a business function. The BLL layer can then enforce things like password strength, password encryption, uniqueness of usernames, etc. that aren't directly related to data access.
Probably not. See #2.
精彩评论