DEV Community

Aleksey Pastuhov
Aleksey Pastuhov

Posted on • Edited on

Evolution of Interaction

Originaly published on my blog apastuhov.com


If you write frontend application - I assume that it interacts with backend API server. If your app is small - you do not think about architecture and scaling. But if it is a big LTS application - you need to think about it! Why? Because You will develop and support that application in future, so just pray that you wont hate yourself in time. I want to tell you how people often develop an interaction between UI and API.

To be on the same page, lets define that Interaction - is an object/class/method/function that allows you to send requests to a backend server.

No silver bullet or Types of architecture

You can try to search some solution! And you may find some guidelines or libraries, also it may be a part of a framework you use, like angular.$resource. In general, there will be 4 types of Interaction architecture.

  • On-flight
  • Factory
  • Singleton
  • "Micro" services

So you will find that there is no silver bullet, which will be the best or the most popular.

I do not want to describe the implementation of every approach because it is your job. :) I want to show how you will use it, pros and cons.

On-flight or jQuery style

JQuery.. JQuery everywhere

I suppose you remember how popular jQuery was, maybe it is still the best tool for somebody. jQuery provided us a big amount of good things, one of them - is a short notation of the AJAX. No XmlHttpRequest more, just simple $.ajax.

So the first style - is to write an AJAX query immediately when you need it.

jQuery.ajax.get(
  'http://super-app.com/api/client',
  {
    success: function(data) {
      client = data;
    },
    error: function() {
      console.error('blah blah blah');
    }
  }
);
Enter fullscreen mode Exit fullscreen mode

I do not want even to discuss why that way is bad. If you will try to write SPA in a such way - you may find that all your requests are scattered by your application. And if you will make a small error - you will find it, only when user will do the action to run that query.

And as always - one day someone would say "We need some time for refactoring".

Factory

Factory

Now we have a configuration of all our requests, and you create them dynamically when you need. For example resource in angular 1.x, someone may say that example is not good, but I want to note that implementation may vary. The idea of the factory - generate objects (requests in our case) dynamically depending on some configuration.

Lets imagine two most popular interfaces with configuration:

request.setup({
  host: 'http://super-app.com/api/'
});
Enter fullscreen mode Exit fullscreen mode

Usage #1:

request(
  'GET',
  'client',
  function(data) {
    clientData = data;
  },
  function() {
    console.error('error handler');
  }
);
Enter fullscreen mode Exit fullscreen mode

Usage #2:

var client = request('client');
client.get(
  function(data) {
    clientData = data;
  },
  function() {
    console.error('error handler');
  }
);
Enter fullscreen mode Exit fullscreen mode

Singleton

S - Singleton

Singleton - is the most popular pattern in software development. So we have a single class to keep all requests and configurations.

api.getProjectList();
api.getProjectById(1);
api.updateClient(instance);
api.deleteUser(1);
// ... and so on
Enter fullscreen mode Exit fullscreen mode

The approach is not so bad, but api.js will grow in time. So it becomes really hard to change and to add new queries. Gritting one's teeth you will add new methods to the file, and one day you will decide that you need to split it.

I assume that your architecture will be next:

-/ api
 |- client.js
 |- project.js
 |- user.js
  \ api.js
Enter fullscreen mode Exit fullscreen mode

And usage will be changed to the next one:

api.project.getList();
api.project.getById(1);
api.client.update(instance);
api.user.delete(1);
// ... and so on
Enter fullscreen mode Exit fullscreen mode

It looks nice and understandable, but there is one small problem - separation of contests. So working with project API - you have an access to client API and you can remove it, instead of a project. That is why you need to isolate classes.

"Micro" services

M - Many singletons

No, wait! I do not want to talk about some big changes to split everything. I just want to note that every such file as ./app/api/client.js is a service. And we do not need that singleton to keep the composition of all that services.

projectApi.getList();
projectApi.getById(1);
clientApi.update(instance);
userApi.delete(1);
// ... and so on
Enter fullscreen mode Exit fullscreen mode

It seems that last solution is ideal. But the more services you have - the more imports and dependencies you need. Some can say that you need to separate by logic and make some groups of services. But it is a long way to discuss.

Summary

Every solution has pros and cons, and only you can define what is relevant for you.

I told you how to develop an interaction between UI and API. And I hope you defined what approach is the best for you! Write your comment and let me know!

P.S.:

I want to mention that the more you write - the more you repeat yourself and others. Who knows, maybe we will return to simple jQuery style one day. :)

Top comments (0)