Research
Research contains the core logic for navigating Steps and Tasks to collect Results independently of any particular UI/UX implementation or back-end services. Key elements of this project are updating code to Swift 4 and creating a data model built around protocols, allowing the more modular composition of apps from independent components.
Overview
The Research framework is organized into groups for Model, Controller, DataSource, Permissions, Localization, Serialization, and Utilities. For the Model, Controller, and DataSource groups, there is a further division into Protocol and Objects where the Protocol group includes the definitions for the the protocols used throughout this framework and the Object group includes concrete, serializable implementations for those protocols.
Model
The Model group includes the information that is used to run a task and record the results of that task. It is divided into three groups.
- Types includes enums and structs that are used to define various object types.
- Protocol includes all the model protocols defined by the core framework.
- Objects includes implementations for each protocol. All the objects within the core framework conform to the
Decodable
protocol to allow using JSON serialization to describe the objects. These objects rely heavily upon theRSDFactory
to determine how the objects should be encoded and decoded for a given application. TheRSDFactory
is a base class with a singletonshared
property that is defined as read/write.
RSDTask
The structure of the task protocol is as follows:
RSDTask
is the interface for running a task. It includes properties and methods used to define the task flow.RSDStepNavigator
is the interface for step navigation. This protocol defines methods for vending steps as appropriate.RSDStep
is the interface that defines a given step in a clinical research protocol.progress()
returns the progress through the task for a given step with the current result.
RSDAsyncActionConfiguration
is an array of configurations for defining asynchronous actions that run in the background and can continue across step boundaries.RSDTaskResult
is a sub-protocol ofRSDResult
that includes the results of a given task run.
RSDStep
There are three main subprotocols to the RSDStep
protocol. These have custom handling that is used by the RSDTaskController
to determine how to navigate a step tree. These include:
RSDUIStep
is used to define a singledisplay unit
. Depending upon the available real-estate, more than one ui step may be displayed at a time – for example, on an iPad, you may choose to group a set of questions using aRSDSectionStep
.RSDSectionStep
is used to define a set of steps that are a logically grouped set of steps within a larger task. This protocol conforms to theRSDStep
,RSDTask
, andRSDConditionalStepNavigator
protocols.RSDTaskInfoStep
is used to display information about a task that can be displayed to the user while the task is fetched. This allows for the actual task to be fetched on demand from a web service or resource file.
The RSDUIStep
protocol is further broken into sub-protocols that define additional step model UI/UX. These include:
RSDActiveUIStep
defines model information for anactive
step. This includes a step duration,RSDActiveUIStepCommand
options, and spoken instructions.RSDTableStep
defines a model that uses a table or collection view presentation with sections and rows.RSDThemedUIStep
defines additional information such as images, colors, and custom view identifiers.RSDFormUIStep
defines one or more input fields.
Additionally, both RSDTask
and RSDUIStep
inherit from RSDUIActionHandler
which can be used to define the text, image, and action that would map to a given button. This allows customization of the UI/UX for a given button to be defined either for that specific step or globally for the entire task.
RSDStepNavigator
The step navigator vends the steps and progress for a task. This framework includes one implementation of the step navigator which is the RSDConditionalStepNavigator
. The conditional step navigator uses protocol extension to take an ordered list of steps, and check those steps against the input RSDTaskResult
to determine whether or not a given step should be skipped or if navigation should jump to a different step using the step identifier
.
For the conditional step navigator, navigation is handled by querying both a list of RSDTrackingRule
objects defined on RSDFactory.shared
and by checking the steps for conformance to a set of navigation rules. Specifically, this framework includes:
RSDNavigationRule
returns a next step identifier that is then used to jump within the navigation.RSDNavigationSkipRule
allows the step to be skipped based on the current task result.RSDNavigationBackRule
can block backward navigation.RSDSurveyNavigationStep
implements the logic of theRSDNavigationRule
by using protocol extension to inspect the task result and compare the answers to a set ofRSDSurveyRule
objects.RSDCohortNavigationStep
andRSDCohortAssignmentStep
are used to navigate based on cohorts to which the participant has been added.
The step results of navigating the task are added to the RSDTaskResult
on the stepHistory
. Results added to the step history are intended to be added sequentially in the order the steps were displayed to the user. A step result can be any result that conforms to the RSDResult
protocol. These results should be uniquely defined by their identifier
which matches the identifier
for the step.
RSDAsyncActionConfiguration
RSDAsyncActionConfiguration
objects define any configuration required for running a background action – for example, recording motion sensor information or pinging a weather service. Most of the work of setting up and running async actions is left to the specific application.
RSDResult
The results of running a task are described using RSDResult
objects. The base protocol requires conformance to the Encodable
protocol but does not require conformance to Decodable
. This allows using class objects that cannot be extended to conform to the Decodable
protocol, such as ORKResult
classes.
There are several protocols that inherit from RSDResult
that are included in the core framework. These include:
RSDAnswerResult
which is used to describe an answer to an input field question.RSDCollectionResult
which is used to describe a collection of other results.RSDErrorResult
which is used to describe a result that ended with an error.RSDFileResult
which is used to point to a file. This result type is generally used by asynchronous recorders.RSDNavigationResult
which is used to track custom navigation as a result of user action.RSDTaskResult
which is used to include all the results for a given task.
Controller
The default mechanism for running a task is to instantiate a controller that conforms to either RSDTaskController
or its sub-protocol, RSDUITaskController
. There are no implementations for either of these protocols included within this framework, although ResearchUI project includes RSDTaskViewController
which is a concrete implementation of RSDUITaskController
that is designed to be used for iPhone applications.
Once an instance of either RSDTaskViewController
or RSDUITaskController
has been instantiated, as part of its setup, it should instantiate a new instance of of RSDTaskViewModel
and use that object (and its children) to manage the task state. RSDUITaskController
is designed to use a protocol extension to manage most of the device-agnostic UX such as determining when to start/stop async actions, and managing step navigation including instantiating a new task path and result for each RSDSectionStep
and RSDTaskInfoStep
that is vended to it by the step navigator.
The RSDUITaskController
does not directly reference the RSDStepController
and there are no implementations of the step controller that are included in the Research framework. The ResearchUI framework includes RSDStepViewController
which is the base class implementation that is designed for use by iPhone applications. RSDStepController
uses the protocol extension to add UX that is device-agnostic.
The RSDAsyncAction
is a controller that can be used to run the async action associated with a given configuration. Currently, there are two concrete implementations of this protocol included within this framework; both RSDDistanceRecorder
and RSDMotionRecorder
are only included in the iOS build.
DataSource
There are two data source protocols included in the core framework which are used to set up a table view or collection view.
RSDPickerDataSource
describes information that can be used to build a picker UI element.RSDTableDataSource
is the model for a table view controller. It provides the data source for aUITableView
, manages and stores answers provided through user input, and updates theRSDResult
with those answers when they change.
License
Research is available under the BSD license:
Copyright © 2017-2019, Sage Bionetworks All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of Sage Bionetworks nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL SAGE BIONETWORKS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.