views:

192

answers:

5

Hi! 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!

+3  A: 

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.

Don Werve
That was my problem too. But what would I use in the normal application then?It is going to be:Main application (on the web)this is linked via the API with the desktop applications. Or should I treat the API as an interface to the DB and my web application also uses the API to get and retrieve data?
Sebastian Hoitz
You'd definitely go for the second approach. If you can decouple the model from the other components you'll be able to use a web interface (almost) as easily as a winforms interface.
emaster70
Not to mention, when you need to refactor later, you can do all of that under cover of the API, and just expose new fields as need be -- if you go with a tightly-coupled interface, then changing functionality becomes much more painful.
Don Werve
A: 

Don't Repeat Yourself

Dustin Getz
Thanks, but the DRY principle itself does not answer this question though. I know about the DRY principle and that's why I have bad feelings about writing code twice. I might not have made that clear enough in my question.
Sebastian Hoitz
+1  A: 

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.

S.Lott
+1  A: 

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.

David Berger
+1  A: 

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.

Vikram