Posts tagged API

In Building Microservices with SenecaJS: Part 1, we finished writing a simple, RESTful microservice for products with hard-coded data. Now it’s time to hook into a real data store and showcase Seneca’s data abstraction layer. In this post, we will be looking at the JSON file store. In the next post, we will swap this out for a MongoDB store.

There are many advantages to using a file store or in-memory store. One of the advantages is the ease of testability since you don’t have to make an actual connection to the data store. You can run your tests on your local machine (in isolation) and you won’t have to worry about the data getting out sync as it maybe if you’re using a shared database.

There is a couple of changes that are needed to use Seneca’s data entity plugin. First, we need to include the dependencies on “seneca-entity” and the type of store we’re interested in using (jsonfile-store). Here is a snippet:

Now we’re ready to start using the file store. But, we don’t have data in our file store yet. So, it’s time to introduce another end-point to our API in which product information can be added (POST’ed).

In the previous snippet, we accessed the ‘products’ collection on the first line. If it doesn’t exist, it will be created with the first save. Then, in our add action/cmd, we saved the record using the save$ method from the entity plugin, capturing the new product information from the request body (assuming it is JSON). We now need to register the end-point by mapping it to our new action. This is done via the web plugin:

In the snippet above, we accessed the ‘products’ collection on the first line. Then, in our getProductById action, we loaded the record using the product id from request parameter. And that’s it. We have a fully functioning service communicating with a real data store. The full project code is listed on GitHub.

Resources:

Designing APIs is no walk in the park. In many instances, when your API becomes popular, it can be difficult or even impossible to change. Whether it’s a programming language or framework, a good API makes a world of difference for developers who use it.

Needless to say, an API needs to be simple. But what’s equally (or more) important is for an API to be simple to get started with. The point is, you need to have a low barrier to entry for new users. jQuery, as opposed to other JavaScript frameworks, does a fantastic job of allowing new developers to, not only become immediately productive with the framework, but also get excited about JavaScript development in general.

However, when not accompanied with good design principles, simplicity may lead to anti-patterns. For instance, the main strength of jQuery is perhaps one of its major weaknesses. The “kitchen sink” jQuery’s overloaded main method violates the single-responsibility principle of API design. It also violates another characteristic of good APIs; Self-documentation, though I’ll write a separate post on that at a later time. Consider the following use of jQuery’s main method below:

Obviously this function has multiple, vastly different responsibilities at this point. So, it’s best to actually separate out the responsibilities into different, self-documenting functions. And while jQuery appears to be overloading the function, it actually isn’t as there is no inherent overloading in JavaScript. After taking a deeper dive into the source code of jQuery, what’s actually happening is that jQuery is validating the arguments/parameters of the $(argument); call to determine which execution path to take. Here is what’s happening in (simplified) pseudo-code:

If argument is a “string”, then

check if argument is a selector and execute path

check if argument is html (regex) and execute path

If argument is an HTML Node, then execute path to wrap in jQuery object.

If argument is a function, then the “callback” path is taken for DOMReady.

This obviously increases the complexity of the code due to the presence of different execution paths. Thus, the maintainability of the code becomes a problem. Additionally, this impacts testing negatively as there are 7 different scenarios that could go wrong within the same function as opposed to one and only one. It is no surprise that jQuery has one of the highest cyclomatic complexity measures of most JavaScript frameworks out there. See image below (less is better).