About client side functions

If you followed this tutorial from the beginning you probably noticed that server side functions (aggregate and assign functions) can be called from the a client computer using the opal package functions datashield.aggregate and datashield.assign respectively. So why have client side functions?

Why client side functions?

The syntax of the commands to call server side function is not very easy to grasp and we want all users, including those not very proficient in R, to run DataSHIELD analysis. Hence, it is important to provide function with simplified syntax. The client side function are basically wrappers for commands that call server side functions. This simplification comes at a cost: The DataSHIELD developer has the ensure the complexity hidden to the user is properly encapsulated in the server side function and that is not always a straightforward task.

Developers should not call a client function from within another client for various reasons mentioned in the below warning box. Developers must familiarise themselves with datashield.aggregate and datashield.assign and use these functions to call server side functions.

Client function are for users not for developers

  • Client functions often display messages to inform the user or report errors. Because of that nesting client functions can have the negative effect of displaying multitude message that end up being confusing.
  • The process of updating server side functions across several studies in a consortium can be time consuming and it is hence preferable, whenever possible, to amend the client side when there is need to address an error or a request from a user that requires a change from the syntax. Therefore client functions are less stable then their server side counterparts. If we nest client functions within other client functions at some point the task of updating those nested functions can become daunting: you can call a function from any package but if the syntax of the function changes (e.g. change in the list of the argument or their type) it will not work.

It is obviously not advisable, and is against good programming practice, to re-invent the wheel so if you really need to do a task that a client function does well then the below tip offers an easy solution.

Do not call a client function from another client, use its code in an internal function instead

Instead of calling a client from another client create an internal function that uses the code of the client:

  • Extract the code of the client function that does the job.
  • Remove all the messages, checks and other lines required to format the output for the user.
  • Create an internal function and paste the now 'light' code in their.
  • Call this internal function from your client function, it will do the job and will not be affected by changes to the syntax of the client the code originated from.

An example of the use of this approach is the internal function tTestHelper2 which uses the thinned code of the function ds.glm called within the function ds.tTest in the package dsStatsClient.

It is important to note that when using this strategy the developer has to correct the internal function if a bug is found in the code of the initial client function!

DataSHIELD Wiki by DataSHIELD is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. Based on a work at http://www.datashield.ac.uk/wiki