Skip to content

Commit

Permalink
Improve Documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
PSchmiedmayer committed Jul 20, 2023
1 parent 5d8ce1b commit 1a466bf
Show file tree
Hide file tree
Showing 13 changed files with 156 additions and 238 deletions.
25 changes: 17 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,25 @@ For more information, please refer to the [API documentation](https://swiftpacka

## The Spezi Architecture

Spezi introduces a standards-based modular approach to building digital health applications. A standard builds the shared repository of data mapped to a common understanding that is used to exchange data between Spezi modules.
Spezi introduces a standards-based modular approach to building digital health applications.
A 'Standard' defines the key component that orchestrates the data flow in the application by meeting requirements defined by components.
You can learn more about the 'Standard' protocol and when it is advised to create your own standard in your application in the <doc:Standard> documentation.

We differentiate between five different types of modules:
- **Standard**: Acts as a shared repository and common ground of communication between modules. We, e.g., provide the FHIR standard as a great standard to build your digital health applications.
- **Data Sources**: Provide input to a standard and utilize the standard's data source registration functionality and adapters to transform data into the standardized format. Examples include the HealthKit data source.
- **Data Source User Interfaces**: Data source user interfaces are data sources that also present user interface components. This, e.g., includes the questionnaire module in the Spezi Swift Package.
- **Data Storage Providers**: Data storage providers obtain elements from a standard and persistently store them. Examples include uploading the data to a cloud storage provider such as the Firebase module.
- **Research Application User Interface**: Research application user interfaces display additional context in the application and include the onboarding, consent, and contacts modules to display great digital health applications.
A 'Component' defines a software subsystem providing distinct and reusable functionality.
Components can use the constraint mechanism to enforce a set of requirements to the standard used in the Spezi-based software where the component is used.
Components also define dependencies on each other to reuse functionality and can communicate with other components by offering and collecting information.
They can also conform to different additional protocols to provide additional access to Spezi features, such lifecycle management and triggering view updates in SwiftUI using the observable mechanisms in Swift.
You can learn more about components in the <doc:Component> documentation.

![System Architecture of the Spezi Framework](Sources/Spezi/Spezi.docc/Resources/SystemArchitecture.jpg)
To simplify the creation of components, a common set of functionalities typically used by components is summarized in the 'Module' protocol, making it an easy one-stop solution to support all these different functionalities and build a capable Spezi module.

> Note: Spezi relies on an ecosystem of modules. Think about what modules you want to build and contribute to the open-source community! Refer to 'Component' and 'Module' documentation to learn more about building your modules.
You can find a list of modules and reusable Swift Packages offered by the Spezi team at Stanford at https://swiftpackageindex.com/StanfordSpezi.
Learn more about Spezi at https://spezi.stanford.edu.
Reach out to us on social media and use the [Stanford Spezi Discussion Forum](https://github.com/orgs/StanfordSpezi/discussions) to ask any Spezi-related questions or share the projects you built with Spezi.

Check out the [Stanford Biodesign Digital Health Group GitHub organization](), for example, applications built with Spezi and some of our related open-source and research projects.

The [API documentation](https://swiftpackageindex.com/StanfordSpezi/Spezi/documentation) includes a selector to switch between the different Swift Package Manager Targets, allowing you to explore the different modules that are included in the Spezi repository.

Expand Down
6 changes: 6 additions & 0 deletions Sources/Spezi/Capabilities/Lifecycle/LifecycleHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ import SwiftUI
/// Delegate methods are related to the `UIApplication` and ``Spezi/Spezi`` lifecycle.
///
/// Conform to the `LifecycleHandler` protocol to get updates about the application lifecycle similar to the `UIApplicationDelegate` on an app basis.
///
/// You can, e.g., implement the following functions to get informed about the application launching and being terminated:
/// - ``LifecycleHandler/willFinishLaunchingWithOptions(_:launchOptions:)-8jatp``
/// - ``LifecycleHandler/applicationWillTerminate(_:)-35fxv``
///
/// All methods supported by the component capability are listed blow.
public protocol LifecycleHandler {
/// Replicates the `application(_: UIApplication, willFinishLaunchingWithOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool`
/// functionality of the `UIApplicationDelegate`.
Expand Down
16 changes: 5 additions & 11 deletions Sources/Spezi/Configuration/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,30 @@

/// A ``Configuration`` defines the ``Standard`` and ``Component``s that are used in a Spezi project.
///
/// Register your different ``Component``s (or more sophisticated ``Module``s) using the ``SpeziAppDelegate/configuration`` property, e.g., using the
/// `FHIR` standard integrated into the Spezi Swift Package.
/// Ensure that your standard conforms to all protocols enforced by the ``Component``s. If your ``Component``s require protocol conformances
/// you must add them to your custom type conforming to ``Standard`` and passed to the initializer or extend a prebuild standard.
///
/// The ``Configuration`` initializer requires a ``Standard`` that is used in the Spezi project.
/// The standard defines a shared repository to facilitate communication between different modules.
/// Use ``Configuration/init(_:)`` to use default empty standard instance only conforming to ``Standard`` if you do not use any ``Component`` requiring custom protocol conformances.
///
/// The ``Configuration/init(standard:_:)``'s components result builder allows the definition of different components, including conditional statements or loops.
///
/// The following example demonstrates the usage of the `FHIR` standard and different built-in Spezi modules, including the `HealthKit` and `QuestionnaireDataSource` components:
/// The following example demonstrates the usage of an `ExampleStandard` standard and reusable Spezi modules, including the `HealthKit` and `QuestionnaireDataSource` components:
/// ```swift
/// import Spezi
/// import FHIR
/// import HealthKit
/// import HealthKitDataSource
/// import HealthKitToFHIRAdapter
/// import Questionnaires
/// import SwiftUI
///
///
/// class ExampleAppDelegate: SpeziAppDelegate {
/// override var configuration: Configuration {
/// Configuration(standard: FHIR()) {
/// Configuration(standard: ExampleStandard()) {
/// if HKHealthStore.isHealthDataAvailable() {
/// HealthKit {
/// CollectSample(
/// HKQuantityType(.stepCount),
/// deliverySetting: .background(.afterAuthorizationAndApplicationWillLaunch)
/// )
/// } adapter: {
/// HealthKitToFHIRAdapter()
/// }
/// }
/// QuestionnaireDataSource()
Expand Down
33 changes: 24 additions & 9 deletions Sources/Spezi/Spezi.docc/Component.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,40 @@ SPDX-License-Identifier: MIT

## Overview

The ``Component/ComponentStandard`` defines what Standard the component supports.
The ``Component/configure()-27tt1`` method is called on the initialization of Spezi.
A ``Component``'s initializer can be used to configure its behavior as a subsystem in Spezi-based software.

### The Component Standard
The ``Component/configure()-27tt1`` method is called on the initialization of the Spezi instance to perform a lightweight configuration of the component.
Both ``Component/Dependency`` and ``Component/DynamicDependencies`` are available and configured at this point.
It is advised that longer setup tasks are done in an asynchronous task and started during the call of the configure method.

A ``Component`` can support any generic standard or add additional constraints using an optional where clause:
### Component Constraints

Components can use the constraint mechanism to enforce a set of requirements to the ``Standard`` used in the Spezi-based software where the component is used.
This mechanism follows a two-step process:

#### 1. Standard Constraint

Define a standard constraint that is required by your component.
The constraint protocol **must** conform to the `Standard` protocol.
```swift
class ExampleComponent<ComponentStandard: Standard>: Component where ComponentStandard: /* ... */ {
/*... */
protocol ExampleConstraint: Standard {
// ...
}
```

``Component``s can also specify support for only one specific ``Standard`` using a `typealias` definition:

#### 2. Enforcing and Utilizing the Constraint with the `@StandardActor` Property Wrapper

Use the constraint in your component to access the `Standard` instance that conforms to the protocol.
```swift
class ExampleFHIRComponent: Component {
typealias ComponentStandard = FHIR
class ExampleComponent: Component {
@StandardActor var standard: any ExampleConstraint

// ...
}
```

> Note: You can learn more about creating a ``Standard`` that must meet the requirements of all components in the ``Standard`` documentation.
### Dependencies

Expand Down
126 changes: 0 additions & 126 deletions Sources/Spezi/Spezi.docc/ModuleCapabilities.md

This file was deleted.

Binary file not shown.

This file was deleted.

16 changes: 5 additions & 11 deletions Sources/Spezi/Spezi.docc/Setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,36 +40,30 @@ struct ExampleApp: App {

A ``Configuration`` defines the ``Standard`` and ``Component``s that are used in a Spezi project.

Register your different ``Component``s (or more sophisticated ``Module``s) using the ``SpeziAppDelegate/configuration`` property, e.g., using the
`FHIR` standard integrated into the Spezi Swift Package.
Ensure that your standard conforms to all protocols enforced by the ``Component``s. If your ``Component``s require protocol conformances
you must add them to your custom type conforming to ``Standard`` and passed to the initializer or extend a prebuild standard.

The ``Configuration`` initializer requires a ``Standard`` that is used in the Spezi project.
The standard defines a shared repository to facilitate communication between different modules.
Use ``Configuration/init(_:)`` to use default empty standard instance only conforming to ``Standard`` if you do not use any ``Component`` requiring custom protocol conformances.

The ``Configuration/init(standard:_:)``'s components result builder allows the definition of different components, including conditional statements or loops.

The following example demonstrates the usage of a `FHIR` standard and different built-in Spezi modules, including the `HealthKit` and `QuestionnaireDataSource` components:
The following example demonstrates the usage of an `ExampleStandard` standard and reusable Spezi modules, including the `HealthKit` and `QuestionnaireDataSource` components:
```swift
import Spezi
import FHIR
import HealthKit
import HealthKitDataSource
import HealthKitToFHIRAdapter
import Questionnaires
import SwiftUI


class ExampleAppDelegate: SpeziAppDelegate {
override var configuration: Configuration {
Configuration(standard: FHIR()) {
Configuration(standard: ExampleStandard()) {
if HKHealthStore.isHealthDataAvailable() {
HealthKit {
CollectSample(
HKQuantityType(.stepCount),
deliverySetting: .background(.afterAuthorizationAndApplicationWillLaunch)
)
} adapter: {
HealthKitToFHIRAdapter()
}
}
QuestionnaireDataSource()
Expand Down
Loading

0 comments on commit 1a466bf

Please sign in to comment.