开发者

Rest API development for a complex hierarchical project

开发者 https://www.devze.com 2023-03-18 10:13 出处:网络
We have a complex fabric BPM solution. We now want to expose the fabric as set of rest APIs. We have an application, in application we have workflows, workflow can have actions. action have fields a

We have a complex fabric BPM solution. We now want to expose the fabric as set of rest APIs.

We have an application, in application we have workflows, workflow can have actions. action have fields and fields can have rules.

so right now the first set of api for fields or rules were made as

[Get] apps/1/workflows/1/actions/1/fields/4/rules

[Post]

apps/1/workflows/1/actions/1/fields/3/rules

but this doesn't look nice, these can get more complex, usually what i read is that keep the URI as simple as lean as possible, should not go in that depth.

so what should be the preferred uri for the above mentioned .

should we make fields and rules as separate resources? or how to go about it. if we make it as separate resources then how to get the specific field. won't it require lot of paramters which then again isn't that of a good approach.

edited again

What i wanted to confirm is that if making the making the deep URIs which i mentioned above is a good standard(which some ppl think is not a very good approach), but as you mentioned it is more like a choice.

So what if i don't chose to make the long URIs and keep it really lean for atleast version 1.

in the above URI example i have to give apps id, workflow id, action id and then field id to get to the required field. which will stay this way unless i have some sort of hash to identify that specific URI. so

apps/1/workflows/1/actions/1/fields/3/ru开发者_如何学编程les

becomes

/55667788

what if i want to keep the URIs readable yet small. e.g. Fields/ returns all the fields of app 1, workflow 1 action 1 but how to provide all those ids without making my URI so cluttered? keeping it to two levels? is it possible or am i goign in the wrong direction?


Well, there's a ton to be said about this topic, but I think specifically this revolves around URI templates. I think we need to use some better examples. If you mean the example URI to be (as you say in your question) ;

apps/1/workflows/1/actions/1/fields/4/rules

Then I'd say, no, here you're introducing semantics into the URI which are not needed, specifically /workflows/ /actions/ /fields/ /rules/. You should denote a URI template for this, and I would come up with something like this ;

{application}/{workflow}/{action}/{field}/{rule}

Basically we can translate an URI such as this ;

/yalla/4356/open_portfolio

Into ;

application = 'yalla'
workflow = '4356'
action = 'open_portfolio'
field = ''
rule = ''

And just see what HTTP method was used, and apply action classes based on that. Your mileage will vary.

However, at this point I'm a bit wary of {action} because in REST we try our hardest to work with a uniform interface, but then I don't know what sort of action you're referring to. It strikes me as a more traditional RPC way of thinking, which I'd try to break free from. For example, if you have a more traditional RPC structure like this ;

/yalla/4356/create_new_portfolio

you're breaking the guaranteed safety of a GET operation (like the classical blunder of using /delete_user as action URI and then have a spider crawling your site with GET ...). Instead I'd do this ;

/yalla/4356/portfolio

To this resource I'll GET to view, PUT to update, POST to create, and DELETE to, well, delete. In that sense, the {action} part of the URI template becomes a bit muddled. What do you want the API to cover?

First rule of creating good URIs is to create URIs that match the resources in your system, and not operations and actions. I'd create resources for your portfolios, but not the actions; those I'd bake inside my GET/POST/PUT/DELETE.

Also, I'm not sure at what point you need the fine granularity of {field} and {rule}, but this is up to you. It could well be that you'd like to update just a field value, and there's nothing wrong with that. I'd probably support that myself, but also support for a climb up the structure tree, so that you could update a field ;

PUT /yalla/4356/portfolio/name?value=new_value

But also update several fields ;

PUT /yalla/4356/portfolio?name=new_name&other=something

And so on, up and down the structure of the tree. This is good practice in that you give your developers/users the flexibility to choose themselves how they would like to work with your API, which is always a bonus.

Update: More clarification follows.

Since we are talking about REST and good use of URIs, there's nothing that says that this resource ;

/yalla/4356/portfolio

Couldn't also be ;

/454A876D786F

Both of these identifiers are representing the exact same thing. Every resource in your system can get a canonical identifier and URI like that, and you can use various paths into the structure. Even this specific field ;

/yalla/4356/portfolio/53464/A4576456/title

Can also have the URI ;

/3498756A8768976FF8976

Further, about the strictness of having something like this constraining your URIs ;

{application}/{workflow}/{action}/{field}/{rule}

It is just an example. Here's several examples to get your thoughts going ;

/apps/{application}/{workflow}/{action}/{field}/{rule}
/workflows/{workflow}/{action}/{field}/{rule}
/action/{action}
/id/{id}
/api/{application}/{api}/{version}/{resource}
/property/{property}
/forms/{form}/{field}

The serious RESTafarian would not worry too much about structure in URIs. I quite often deliberately choose non-semantic identifiers for things / entities / topics, using a lot of

/3498756A8768976FF8976

for all manner of things, even relationships between things. The above URI might be; a topic, a subject, a category, a relationship, a role, a field, an action, a form, an application, and on and on it goes.

I come from the world of Topic Maps (and you can see one of my answers to something slightly different talk about it and how it works over here) in which every thing you talk about, every aspect of your model, is represented with a topic, and all topics have identifiers. (I could complicate it and state that there are three kinds of identifiers; internal, local and external, where the latter two use URIs, but I'm not sure that explain much at this point :) For example, here is a topic representing an application ;

PUT /1234 name='My app'&type='application'

This means I can talk about or refer to my application using that identifier anywhere in my system (you would normally have a cache of types handy). Create identifiers that are unique to every little thing, and the RESTful interface would be far, far easier to deal with.

As to your latest edit, I'm not quite sure I understand what you're asking there, so maybe if you provide some examples would be helpful. But do you mean if you made some of those sub-properties unique URIs in their own right? Like ;

/3498756A8768976FF8976

When you get this resource, you will get a response back. Not sure what representation you're going with, it could be XML or JSON, or HTML with embedded metadata, but let's choose XML just because the example will be simple ;

<response>
   <resource id="3498756A8768976FF8976">
      <type id="field" />
      <alias uri="some/other/path" />
      <alias uri="and/another/example" />
      <relationships>
         <parent id="4563456456" type="form" />
         <child id="5784567345" type="rule" />
         <child id="3457698786" type="rule" />
      </relationships>
   </resource>
</response>

Without knowing too much about your systems requirements, here is an example where the field (which is the <resource> with its id in it), which you can get through (and even if I say that the id is 'type', I really mean some other ambiguous id like 3459867354 that represent 'field', and the same for other id's that spell out in name; they're really just id's and spelled out for ease of understanding :), and it has a few aliases. You map in the relationships, and we can see that this field belongs to a certain form, and that it also has two rules attached. You can next query any of those id's to get metadata about where they belong and what they are and do.

You can of course extend this with documentation directly in the XML representation, examples, hints, usage, statistics, whatever else you feel people need.

But I have to say a few things about creating a RESTful system. REST clients should be able to understand forms, so if I ask for a XHTML representation (as opposed to XML above), it can contain actions available to me ;

<html>
    <body>
       <form action="/apps/1234" method="get">
          <input type="submit" title="View 1234 application" />
       </form>
       <form action="/apps/1234/567" method="get">
          <input type="submit" title="View 1234 applications' portfolio" />
       </form>
       <form action="/apps/1234" method="post">
          <input type="text" name="query" title="What to search for?" />
          <input type="submit" title="Search application 1234" />
       </form>
    </body>
</html>

A REST client can use and browse through a full application automatically based on this. There's tons of interesting things to say about this, of course, but I fear I'm going into novel mode, and perhaps outside the scope of your question, but suffice to say, if you focus on a myriad of forms being the interface into your application, you don't even have to worry about URI templates; just point to a resource, get the XHTML forms, and your API should be fairly easy to use and completely self-documented.

Second edit:

I always avoid plurals for structured access to items. For example, I would use ;

/product/345634

for a specific product, and just use ;

/product

for a list of all products. For example, to create a new product, you POST to /product, and you should get a /product/{new_id} back if successful. If you want to, you could also do ;

/product/3456345
/products

But I wouldn't recommend it. As to two levels vs. any kind of level, I don't think you should worry too much about how cluttered it's going to be. URIs that are deep in the system are rarely if ever interpreted by humans. Does it really matter if your URIs are long?

Having said that, though, of course you could do ;

/field
/workflow
/action
/application

to get to collections of those types. Again, what is the requirement of those you create this API for? If it's only for aesthetic reasons, ie. your own opinion of cluttered URIs, then I'd say you're worrying about the wrong thing. Short URIs don't necessary make your API easier to understand. I'd go with the full structured I talked about early in this answer.

Anyway, hope that helps a little, and feel free to clarify and I'll expound further.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号