4

I'm working on a Web app that uses node.js on the server and AngularJS on the client. I'm new to Angular, but enables writing client-side applications that can be more self-contained than some other approaches.

Here is the scenario. On the server, I query a DB and then transform the results into a list of nodes and edge objects. These objects are sent to the client (browser), and the client displays them as a graph.

The code to parse the query results and build the graph is pretty generic and I expect to use it again subsequent apps. It can stay on the server. However, a lot of the code could be moved to the client because it is specific the sigma.js package that displays the graph.

Part of me wants to offload the processing the client. There is also talk of ditching sigma.js for the next application we build, so shoving it into the client sounds pretty appealing.

However, the client is already feels bloated and complicated. I could use something like the decorator pattern to keep the sigma.js specific code encapsulated while leaving room for more representations.

Which direction should I go? What should I taking into consideration?

  • I think sending html from server use more bandwidth on the long term, so you should avoid if their is a huge amount of data, whereas rendering only in the client increase your script file. Also, html on the server doesn't allow an API... – Vinz243 May 15 '14 at 18:53
1
+50

Which direction should I go? What should I taking into consideration?

I cannot tell you which direction to go because that will require careful consideration of your problem domain, end users and some testing. However, I can help you figure out what to take into consideration.

Load Balancing

Your application servers are fixed. You might have 2, 3 or even 4, but whatever the number, you have a certain number. You can scale horizontally by adding servers, but there is a direct linear cost to that.

On the other hand, you have N clients. Each user who visits your site has their own CPU and memory. In terms of executing your code, that is free CPU and memory :) Hard to pass that up.

Your clients also provide a level of isolation. The work of one client does not impact the work of another in regard to client-side code. If everything executed on the server, one HTTP request going awry can bog down a server that is shared by many users.

Security

Don't trust the client to do computations that affect data that gets shared with other users unless that computation is derived from data they have entered anyway. For example, it would be fine to use JavaScript in the browser to convert the user's entered "05-15-2014" into an ISO date, but if the server needs to record the time the client performed some action, don't ask the client to do supply the time. Just capture the time on the server when that request occurs.

Performance

Browsers can be slow to do a lot of number crunching. Until the recent JavaScript browser war, JavaScript in general was a slow language, not due to issues with the language, just the runtime implementations. If the server can calculate something using a nice fast server-grade CPU and send it down, that may perform better than letting the client do it.

Predictability

Client machines vary. There are users running Safari on a Mac, Chrome on a Windows 7 64-bit machine with 8 GB of RAM and users running IE8 on Windows XP 32-bit. You can't predict how your client-side code will perform because there are major factors outside of your control. Your servers on the other hand, are very much under your control. You can monitor their performance and scale them up or down as needed to balance performance and costs.

Bandwidth

Calculating something on the server may be faster, but if you end up having to push a large data set down to the client over the Internet, not only is there a latency component to that, but you are likely billed by bandwidth usage. Therefore, if you have a cheap calculation that results in a large data set (let's say an array of all even numbers up to 1 million), let the client do it.

Monitoring

Your servers are under your control and therefore you can monitor their performance. If requests to a specific page are returning results to the client after 5 seconds, it is easier to detect and debug that on your servers. There are tools and mechanisms to monitor client-side performance, but the trade-offs and complexities are usually higher (like how do you report the data back to a central place and report on it?), like:

  1. How do you report the data back to a central place?
  2. Performance hit of executing additional code
  3. For clients where the performance is extremely bad, you may not even get the measurements, which biases your metrics because the worst performance is what you need to know the most about.

Server-side performance can be monitored via log files.

3

There's one thing you mention in the last paragraph that stands out to me:

the client is already feels bloated and complicated.

The modern approach to client/server relationship is a parallel of the relationship between human and machine.

Client Akin to iOS programming, we ought to perceive the Angular front-end as a View-Controller. Don't use models in the frontend, use services. Those services connect to your models which live entirely on the server. The View-Controller is a direct instrument of the User. Your User uses the client to understand wtf is going on in their data within your application, and to express their wishes ("actions") within the system.

Server Here we use the Express framework (or whatever) to implement MVC architecture. I recommend pointing all of your angular services to /api/XXX routes that serve a proper hypermedia API. (My personal favorite MEAN implementation is https://github.com/DaftMonk/generator-angular-fullstack )

The next step here is to re-factor to create room for innovation. Create a Top-Level diagram of your whole application. Draw a vertical line down the middle of it, and write "Backend" on the left and "Frontend" on the right.

Where your application feels bloated, DRY it out. Where your application feels complicated, try an exercise where you re-imagine that part of it from zero. Amputate a giant bloated, complicated bad practice, especially if it's wasting your own development time.

Re-draw your Top-Level diagram three times from scratch, and just keep your mind limber and open to throwing out bad code if it saves your time in the future.

  • +1 for "we ought to perceive the Angular front-end as a View-Controller. Don't use models in the frontend, use services." – MrLane May 18 '14 at 23:45
1

I can conceive of a few considerations to be juggled, in priorty order:

Performance

  • Doing the display processing on the client may be slower than on the server - will the user notice?
  • Doing the display processing on the server will increase load, possibly slowing or delaying other requests.
  • Will the data transmitted from server to client be more or less if processing is done on the server? By how much?

If the performance hit of processing on the client is acceptable, it may be the best choice.

Changing the graph display library

It's a good idea to decouple the modules in a software product so that changes can be made to one without affecting the others, but unless you have a high degree of certainty that you'll need to change a given module, introducing complexity to support it could impose an unnecessary price.

Would a different graph display library require a different input graph representation? Then the server side will likely need to change with a new library, so it may be best to do the processing on the server to insulate the client side.

Would a different graph display library produce output that needs to be consumed differently? Then the client side will likely need to change, so it may be best to do the processing on the client side to insulate the server side.

Changes to the server API

Doing the processing on the server will require a change to your server API, but it doesn't have to replace the ability to request the existing JSON representation that you have now. To provide different representations for the same resource, define a custom media type for the display representation, such as application/vnd.example.my-graph-display, then use that when your client requests the resource for display. When the client needs the JSON representation, use application/json.


Finally, the solution to planning for a future replacement of Sigma.js with some other graph display library is the same whether it's done on the client or server: create an interface to abstract the library and write an Adapter to translate your interface calls into the Sigma.js API. When you switch graph display implementations, write a new adapter for it, and you can replace your implementation without changing the code that uses the interface.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.