I'm currently writing a web software which is also going to be used by Client desktops via an API.
The problem I'm facing right now is: Should I implement every action of adding/updating/deleting objects in the application twice? Once as it sits in the normal code and once isolated for the API?
Or should I much rather use a system of OOP model classes that represent all objects in my database and use those for both the API and normal code?
Or develop the API first hand and use it from my normal web interface too?
This is something I have always wondered about. Thanks in advance!
Doing things twice is almost always a bad idea -- you're probably better off implementing the API, opening it up to the end-user, and also using it for the client code as well, with some extra hooks for stuff that is interface-specific.
This is why we have the REST (and SOAP) protocols.
The desktop makes RESTful requests to your web application. Your web application receives the REST requests and does the real work.
Your code exists in exactly one place -- the web.
First let me say that my experience is with Django, which is a rich web framework that already provides an ORM. I have to create models to represent my objects; I execute no raw sql.
So naturally I would recommend your second approach. Right off the bat I'll say that your third approach will be a headache. Why? Because you're going to want to do different post-processing. That's the nature of the game. When you put up a CRUD interface on the web, some things will be stored as fields in your model that the user wouldn't even recognize from the CRUD page. As an example, I have a CRUD page for news stories that have different companies associated with it. (This is a database foreign key.) Naturally, this is automatically supplied by login information. But the process for logging into the webpage (and where that login is stored) will be very different than for a remote API.
My preference is to combine a little bit of your first two approaches. There should definitely be actions that should occur every single time an object is saved. Put those in a save()
method (or update()
and insert()
if you want to break things up a bit more). You should not think about implementing this functionality twice.
However, there is deserialization/object construction and validation that will occur differently in the web interface and the remote API. This really ought to be implemented separately.
One might also look at validation as inherently different from deserialization and consider that some rules will be the same and others will be different. For example, in a web interface, I know that when I receive the story, I stamp the modification_time
myself, whereas for a remote API, I trust the client to stamp the time. This is intentional. On the other hand, any story that has no tags on it MUST receive a default
tag, regardless of where it comes from. You might prefer the liberty to make validator objects to just plug in after object construction.
A code example (in python):
def handle_remote_update(serialized_object):
#do some parsing
model_object = ModelObject(...)#fill in with parsed values
validator1.validate(model_object)
validator3.validate(model_object)
model_object.save()#All database code is in this method
#If you have to log to your system or notify listeners, that's also in this method
def handle_web_submission(post_dict):
#do some parsing
model_object = ModelObject(...)#fill in with parsed values
validator2.validate(model_object)#This wasn't executed above
validator3.validate(model_object)#This was
model_object.save()#Same code gets executed down here as above
Granted, I have only handled the case of insert
or possibly update
. What you need calling these functions is some method splitter, something that knows when the remote api is calling insert
versus delete
and calls a different function accordingly (and likewise for the web interface). If you are using a web framework, this might well be your urlconfig for the web interface portion.
REST has pretty much become a standard for providing an API over the web for the clients and gives you lot of flexibility & power as well. If you are working on .net platform, you can actually use ASTORIA [ADO.Net Data Services] which generates your REST based webservice by simply mapping your database objects.