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.
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.
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
Decodableprotocol to allow using JSON serialization to describe the objects. These objects rely heavily upon the
RSDFactoryto determine how the objects should be encoded and decoded for a given application. The
RSDFactoryis a base class with a singleton
sharedproperty that is defined as read/write.
The structure of the task protocol is as follows:
RSDTaskis the interface for running a task. It includes properties and methods used to define the task flow.
RSDStepNavigatoris the interface for step navigation. This protocol defines methods for vending steps as appropriate.
RSDStepis 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.
RSDAsyncActionConfigurationis an array of configurations for defining asynchronous actions that run in the background and can continue across step boundaries.
RSDTaskResultis a sub-protocol of
RSDResultthat includes the results of a given task run.
RSDUIStepis used to define a single
display 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 a
RSDSectionStepis used to define a set of steps that are a logically grouped set of steps within a larger task. This protocol conforms to the
RSDTaskInfoStepis 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.
RSDUIStep protocol is further broken into sub-protocols that define additional step model UI/UX. These include:
RSDActiveUIStepdefines model information for an
activestep. This includes a step duration,
RSDActiveUIStepCommandoptions, and spoken instructions.
RSDTableStepdefines a model that uses a table or collection view presentation with sections and rows.
RSDThemedUIStepdefines additional information such as images, colors, and custom view identifiers.
RSDFormUIStepdefines one or more input fields.
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.
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
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:
RSDNavigationRulereturns a next step identifier that is then used to jump within the navigation.
RSDNavigationSkipRuleallows the step to be skipped based on the current task result.
RSDNavigationBackRulecan block backward navigation.
RSDSurveyNavigationStepimplements the logic of the
RSDNavigationRuleby using protocol extension to inspect the task result and compare the answers to a set of
RSDCohortAssignmentStepare 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 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.
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
There are several protocols that inherit from
RSDResult that are included in the core framework. These include:
RSDAnswerResultwhich is used to describe an answer to an input field question.
RSDCollectionResultwhich is used to describe a collection of other results.
RSDErrorResultwhich is used to describe a result that ended with an error.
RSDFileResultwhich is used to point to a file. This result type is generally used by asynchronous recorders.
RSDNavigationResultwhich is used to track custom navigation as a result of user action.
RSDTaskResultwhich is used to include all the results for a given task.
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
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
RSDTaskInfoStep that is vended to it by the step navigator.
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.
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
RSDMotionRecorder are only included in the iOS build.
There are two data source protocols included in the core framework which are used to set up a table view or collection view.
RSDPickerDataSourcedescribes information that can be used to build a picker UI element.
RSDTableDataSourceis the model for a table view controller. It provides the data source for a
UITableView, manages and stores answers provided through user input, and updates the
RSDResultwith those answers when they change.
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.