Difference between revisions of "Coding standards"

From DarkWiki
Jump to: navigation, search
(RESTlike versus RESTful)
(RESTlike versus RESTful)
Line 17: Line 17:
 
Pure REST''ful'' (i.e. [https://en.wikipedia.org/wiki/HATEOAS HATEOAS]) is something of a heavyweight abstraction (and enthused by the puritanical bore), and places demands on clients that they often simply cannot accommodate efficiently. Therefore, a REST''like'' approach is the happy medium, where we use the traditional contract approach (a specified set of URLs and payload definitions). This simple approach is understood by all and can be achieved in the smallest or oldest of architectures.
 
Pure REST''ful'' (i.e. [https://en.wikipedia.org/wiki/HATEOAS HATEOAS]) is something of a heavyweight abstraction (and enthused by the puritanical bore), and places demands on clients that they often simply cannot accommodate efficiently. Therefore, a REST''like'' approach is the happy medium, where we use the traditional contract approach (a specified set of URLs and payload definitions). This simple approach is understood by all and can be achieved in the smallest or oldest of architectures.
  
<q>An endpoint is invariably easier to implement than the client; focus on the client as that is your customer<q>
+
<blockquote>An endpoint is invariably easier to implement than the client; focus on the client as that is your customer.</blockquote>
  
 
Efficiency is the most important part of an API. Understanding is secondary. The second is a matter of the client-side developer learning once. Once done and let loose in the live environment, efficient operation is by far the most important consideration. Reducing the number of calls to achieve something is important. Savings of 10ms are important. Consider the object graph when designing your API, but it is only one aspect you need to consider; focus on ensuring there is no recursion, circular dependencies, etc. For example, provide a mechanism to get users, to get groups, and to get membership.
 
Efficiency is the most important part of an API. Understanding is secondary. The second is a matter of the client-side developer learning once. Once done and let loose in the live environment, efficient operation is by far the most important consideration. Reducing the number of calls to achieve something is important. Savings of 10ms are important. Consider the object graph when designing your API, but it is only one aspect you need to consider; focus on ensuring there is no recursion, circular dependencies, etc. For example, provide a mechanism to get users, to get groups, and to get membership.

Revision as of 07:04, 17 July 2019

Object properties

Getters

Avoid throwing exceptions. A getter should provide access to the field, and should not result in an exception. There are occasions when this rule can be relaxed (such as indeterminable exceptions like OutOfMemoryException, or deliberate exceptions such as IllegalStateException), but things like NullPointerExceptions should not occur.

Must be repeatable. Each call to a getter should result in the exact same response. As a general rule, you should not create new objects. If you do, you should make sure they are always guaranteed to be equal (this may be hard if you are not responsible for the other code). The desired behaviour is that of a const method in C++, so that calling the method on an object does not change the state of the object.

Setters

Order cannot matter. The order in which setters are called should have no effect on the end result. Calling setA() then setB() should end with the same result as setB() followed by setA().

RESTful URL endpoints

RESTlike versus RESTful

Pure RESTful (i.e. HATEOAS) is something of a heavyweight abstraction (and enthused by the puritanical bore), and places demands on clients that they often simply cannot accommodate efficiently. Therefore, a RESTlike approach is the happy medium, where we use the traditional contract approach (a specified set of URLs and payload definitions). This simple approach is understood by all and can be achieved in the smallest or oldest of architectures.

An endpoint is invariably easier to implement than the client; focus on the client as that is your customer.

Efficiency is the most important part of an API. Understanding is secondary. The second is a matter of the client-side developer learning once. Once done and let loose in the live environment, efficient operation is by far the most important consideration. Reducing the number of calls to achieve something is important. Savings of 10ms are important. Consider the object graph when designing your API, but it is only one aspect you need to consider; focus on ensuring there is no recursion, circular dependencies, etc. For example, provide a mechanism to get users, to get groups, and to get membership.

 /user-management/users/111
 /user-management/users/111/groups
 /user-management/groups/999
 /user-management/groups/999/members

Lastly, in anything other than trivial situations, it is rare that any part of the object graph can be updated by clients. In most cases, you'll find clients need to update only a tiny portion of the graph. You should only provide interfaces for those that are needed.

URL structure

The API endpoints should incorporate the plural of the entity (i.e. "users" rather than "user").

/<category>/<entities>/<entityId>
/<category>/<entitiesA>/<entityIdA>/<entitiesB>/<entityIdB>/<entitiesC>/<entityIdC>

When the identifier is something other than an identifier, we alter the path variable accordingly:

 /<entitiesByName>/<name>
 /<entitiesBySize>/<size>
 /<entitiesById>/<entityId>

As the "ById" pattern is so common, we choose to shorten it by removing the 'ById', so that it becomes:

 /<entities>/<entityId>

Optional parameters (such as those used for ordering results, for example) should not appear in the URL path, but in the query parameters.

Examples

Here are some examples:

/user-management/users/76516745
/user-management/usersById/76516745
/user-management/usersByName/fbloggs
/user-management/users/76516745/features
/user-management/users/76516745/features/{featureId}
/user-management/groups/1872/users?sort=name

Verbs

Method Purpose Example Notes
POST Create
/users
If the entity in the body contains a userId, it should try to use that identifier. This behaviour is useful for import/export between systems.
GET Read
/users/<userId>
PUT Update
/users/<userId>
If the entity in the body contains a different userId, it might try to effectively rename/move the entity.
DELETE Delete
/users/<userId>

Other actions should be implemented so that the "verb" appears at the end of the URL. For example, if there is a situation where you want to play (verb) a set of songs, the URL would look something like:

 /song-book/songs/197263541675243/play