PDA

View Full Version : Thin or Fat Client



Adam Davies
30 Sep 2011, 5:17 AM
Fat-client systems are where all the processing and state should be maintained client-side and not much processing done server side (just get and set data).

My view is that the processing should be done on the server and the client should just get and display data and post updates to the server. Only processing on clients should be client side validation and maybe a few other minimal things.

It seems that gxt and gwt encourage a fat-client approch.

Anyone have any views on this?

Colin Alworth
30 Sep 2011, 9:15 AM
There are cases where when building an RIA app (with or without GWT and GXT) it would make sense to deal with lots of the rules and state on the client, but in any case where the business rules must be maintained, the server needs to be the authoritative source. If just storing and managing data for the client to view and use (a notepad, or metrics app spring to mind), the client can own and control it all, as the worst the client can do is see and manipulate data available locally, but if you are passing data back to the server that can affect others, you need to consider how arbitrary changes can affect those other users.

So it really depends on where your definition of 'client' begins and ends. If you are building, say, a shopping cart, you want to keep all the items and the arithmetic on the client, and perhaps even support for adding some new item to the cart. But these actions must be passed to the server, to allow it to verify that no rules have been broken, such as the user changing the price through firebug or the like. If on the other hand you are building a game, and the only get/set communication with the server is to log scores, letting the client deal with almost everything is probably okay - the impact of cheating is pretty minimal, if it turns out to even be possible.

Because GWT apps are in the end compiled to JS, they are relatively easy to tamper with - certainly easier than modern computer games or smartphone firmware, which are often cracked within days of being released. Because in the end you control the server, this is not a threat to web development, as you can check your business rules there.

If data is per-user, using the server as a way to persist data (i.e. just get/set) is probably sufficient - much like how many smartphone apps work (and for the same reasons as listed above, smartphone apps shouldn't be trusted implicitly by the server).

GXT offers a number of widgets, data binding tools, and abstractions to load and page data into simple to construct visualizations. The Proxy and Loader classes can be used to provide several windows into your server, and through RPC (or any other preferred method for js to send data to the server) you can send data back again and let your server verify that all the rules are being followed. While a lot of functionality can be offered in the browser, there is no requirement that the browser also owns the logic itself.

I hope this helps, and I hope it is clear how ambiguous the terms fat and thin are when referring to apps running on the browser and server.

Adam Davies
4 Oct 2011, 12:14 AM
I agree more or less with what you have described above. However, I think its easy to decide where the line is between client and server. If it runs in the browser then its client, if it runs on the server then its server. JSPs for example are server side but mostly to display client data.

I have come to the conclusion that client code should be there to execute client side logic. So this would be to display data specific to that particular client. The shopping cart I don’t believe is a good example. Mostly because you want to store server side what is in the shopping cart (as Amazon does).
However, if you had an accounting system that displayed the summary of all invoices or payments over the last month, should the code be client side or server side. I belive it should be server side because:


Server side code is better at number crunching, than Javascript is.
The source-of-truth data is on the server side. So this is where the processing should be done.
If the processing is done on the client side then there is a possibility/probability that the data on the client side will be stale.


The only advantage as I can see of doing processing on the client side is that you can do a big download of all the data and then you have it all local for calculating. A bit like a how a spreadsheet may work.

In general, I think less processing on the client the better. I feel technologies like GXT, because they blur the boundaries between client and server, and because of the rich widgets, client side data models, and difficult implementation models lead people into trying to put all the processing on the client side.

This, in my view, is a costly mistake, because of the security concerns you outline above and because of the increase in complexity because eventually, you have to implement the code on server side anyway to check the validity of save/update points.

Adam

Colin Alworth
4 Oct 2011, 6:25 AM
You make some great points - thinking about this sort of thing before you dig too deep is important, and this is the way you decide what logic goes where.

One point I believe you are in error on: Most Javascript engines are very good at math, and compared to the performance of actually rendering NxM values on a spreadsheet, math takes no time at all.

Another thing to consider - if your validation can be done using JSR-303 rules, GWT now has a way of running those rules on the client as they will be run on the server, and GXT 3 will support any validation system that can push errors in the editor framework, including this. Might be worth a look to only have to declare your validations once.

Complex client code isn't always used for validation that business rules are followed - there are plenty of other things a GWT-based app can do much more easily than its JSP counterparts. Load a list of data to the client, allowing the user to page, filter to the item they want, bind that item to a form, allowing them to modify it, keep making changes until happy, then click save to push all changes at once (and get all validation errors that the server knows about but the client was unable to resolve). This can be accomplished in two round trip calls to the server, one to load a List<DataRow> from the server, and another to attempt to save only the Set of modified DataRow entries. If the server sends back 5 errors in a list/set, they can be projected back on to the rows that are not correct yet. In a case like this, the client only does the trivial validation which would annoy them if they had to wait until the complete server response was back - these validations are best used to say 'this field cannot be blank' or 'this field must contain a number between 0 and 100'. If the user circumvents these, they gain nothing, because they are only a way to check the user's mistakes before passed to the server, which does the real validation.

In my experience, minimizing the size and frequency of round trip calls to the server is important for good user perception of performance. If you need to make frequent calls, make sure they are tiny, and always try to map them to actions that make sense to take some time (clicking a button is good, focusing a field is bad). Full page refresh to finish a save can have issues with losing other data - complex session-heavy server-side frameworks can be an answer to this (I like wicket, for what it is worth), but in many cases it is easier to only have the server concerned with the data, and let the client do the binding, and avoid the refreshes.

Many developers like the GWT way of doing things because they blur that client/server line, and limit the potential hiccups that can occur during development. At the same time, as you point out, they must remain away of the line, but this is a detail that should be drawn at spec time, that validation (both business and security) needs to stay on the server side.

Adam Davies
4 Oct 2011, 7:48 AM
Thanks, I like your response.

The rich widgets of GXT are great and binding between grids and forms is very useful.
However, one point I would value your opinion on is grid paging. From what I have seen grids can either download all the data and page on the client side, or they can send a paging request to the server (with the help of PagingLoadConfig).

So this leads to the question of when is best to page on the client, and when is it best to page on the server? The problem with paging on the server is that the PagingLoadConfig is predominantly client code relating to the current page in the grid and thus stops the method from being usable in a more generic getAllInvoices kind of a way. However, paging on the client means that you may have to download loads of data that the user may not page through anyway.

Having said this though, I still think we are putting too much code on the client. It’s not just a case of editing items and sending them to the backend. We have a model where we get almost all the data required by our application and then display them to the user as and when the user requires. My feeling is that we should be only getting the data the user requires. This will result in more calls but of only a small dataset. Consequently I think this would transfer to mobile apps easier because of the smaller client memory footprint and because of less net-traffic (assuming the client does not view all possible data), and quicker start-up time.
For the paging I think it is best to do it on the server because mostly users will not page through all their data. This also fits in with my belief that servers are better at number crunching and filtering data for sending to customers.

Thanks for responses, it’s been good food for thought.