You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ARCHITECTURE.md
+38-23Lines changed: 38 additions & 23 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -69,28 +69,33 @@ Throughout the entire architecture design process, we've priorized several key c
69
69
CoreData interactions are contained within the Storage framework. A set of protocols has been defined, which would, in theory, allow us to
70
70
replace CoreData with any other database. Key notes:
71
71
72
-
1. CoreDataManager
72
+
73
+
1.**CoreDataManager**
74
+
73
75
In charge of bootstrapping the entire CoreData stack: contains a NSPersistentContainer instance, and
74
76
is responsible for loading both, the Data Model and the actual `.sqlite` file.
75
77
76
-
2. StorageManagerType
78
+
2.**StorageManagerType**
79
+
77
80
Defines the public API that's expected to be conformed by any actual implementation that intends to contain
78
81
and grant access to StorageType instances.
79
82
80
83
**Conformed by CoreDatManager.**
81
84
82
-
2. StorageType
85
+
3.**StorageType**
86
+
83
87
Defines a set of framework-agnostic API's for CRUD operations over collections of Objects.
84
88
Every instance of this type is expected to be associated with a particular GCD Queue (Thread).
85
89
86
90
**Conformed by NSManagedObjectContext**
87
91
88
-
3. Object
92
+
4.**Object**
93
+
89
94
Defines required methods / properties, to be implemented by Stored Objects.
90
95
91
96
**Conformed by NSManagedObject.**
92
97
93
-
4. StorageType+Extensions
98
+
5.**StorageType+Extensions**
94
99
95
100
The extension `StorageType+Extensions` defines a set of convenience methods, aimed at easing out WC specific
96
101
tasks (such as: `loadOrder(orderID:)`).
@@ -134,13 +139,13 @@ Since our Model entities conform to `Decodable`, this results in small-footprint
134
139
135
140
The networking layer is **entirely decoupled** from third party frameworks. We rely upon component injection to actually perform network requests:
136
141
137
-
1. NetworkType
142
+
1.**NetworkType**
138
143
Defines a set of API's, to be implemented by any class that offers actual Network Access.
139
144
140
-
2. AlamofireNetwork
145
+
2.**AlamofireNetwork**
141
146
Thin wrapper around the Alamofire library.
142
147
143
-
3. MockupNetwork
148
+
3.**MockupNetwork**
144
149
As the name implies, the Mockup Network is extensively used in Unit Tests. Allows us to simulate backend
145
150
responses without requiring third party tools. No more NSURLSession swizzling!
146
151
@@ -151,15 +156,15 @@ The networking layer is **entirely decoupled** from third party frameworks. We r
151
156
Rather than building URL instances in multiple spots, we've opted for implementing three core tools, that, once fully initialized, are capable
152
157
of performing this task for us:
153
158
154
-
1. DotcomRequest
159
+
1.**DotcomRequest**
155
160
Represents a WordPress.com request. Set the proper API Version, method, path and parameters, and this structure
156
161
will generate a URLRequest for you.
157
162
158
-
2. JetpackRequest
163
+
2.**JetpackRequest**
159
164
Analog to DotcomRequest, this structure represents a Jetpack Endpoint request. Capable of building a ready-to-use
160
165
URLRequest for a "Jetpack Tunneled" endpoint.
161
166
162
-
3. AuthenticatedRequest
167
+
3.**AuthenticatedRequest**
163
168
Injects a set of Credentials into anything that conforms to the URLConvertible protocol. Usually wraps up
164
169
a DotcomRequest (OR) JetpackRequest.
165
170
@@ -188,13 +193,16 @@ Storage layers.
188
193
We've borrowed several concepts from the [WordPress's FluxC library](https://github.com/wordpress-mobile/WordPress-FluxC-Android), and tailored them down
189
194
for the iOS platform (and our specific requirements):
190
195
191
-
1. Actions
196
+
197
+
1.**Actions**
198
+
192
199
Lightweight entities expected to contain anything required to perform a specific task.
193
200
Usually implemented by means of Swift enums, but can be literally any type that conforms to the Action protocol.
194
201
195
202
*Allowed* to have a Closure Callback to indicate Success / Failure scenarios.
196
203
197
-
2. Stores
204
+
2.**Stores**
205
+
198
206
Stores offer sets of related API's that allow you to perform related tasks. Typically each Model Entity will have an
199
207
associated Store.
200
208
@@ -204,20 +212,23 @@ for the iOS platform (and our specific requirements):
204
212
Differing from our Android counterpart, Yosemite.Stores are *only expected process Actions*, and do not expose
205
213
Public API's to retrieve / observe objects. The name has been kept *for historic reasons*.
206
214
207
-
3. Dispatcher
215
+
3.**Dispatcher**
216
+
208
217
Binds together Actions and ActionProcessors (Stores), with key differences from FluxC:
209
218
210
219
- ActionProcessors must register themselves to handle a specific ActionType.
211
220
- Each ActionType may only have one ActionProcessor associated.
212
221
- Since each ActionType may be only handled by a single ActionProcessor, a Yosemite.Action is *allowed* to have
213
222
a Callback Closure.
214
223
215
-
4. ResultsController
224
+
4.**ResultsController**
225
+
216
226
Associated with a Stored.Entity, allows you to query the Storage layer, but grants you access to the *ReadOnly* version
217
227
of the Observed Entities.
218
228
Internally, implemented as a thin wrapper around NSFetchedResultsController.
219
229
220
-
5. EntityListener
230
+
5.**EntityListener**
231
+
221
232
Allows you to observe changes performed over DataModel Entities. Whenever the observed entity is Updated / Deleted,
222
233
callbacks will be executed.
223
234
@@ -257,19 +268,21 @@ for the iOS platform (and our specific requirements):
257
268
258
269
It's important to note that in the proposed architecture Model Entities must be defined in two spots:
259
270
260
-
A. Storage.framework
271
+
A. **Storage.framework**
272
+
261
273
New entities are defined in the CoreData Model, and it's code is generated thru the Model Editor.
262
274
263
-
B. Networking.framework
275
+
B. **Networking.framework**
276
+
264
277
Entities are typically implemented as `structs` with readonly properties, and Decodable conformance.
265
278
266
-
In order to avoid code duplication we've taken a shortcut:
279
+
In order to avoid code duplication we've taken a few shortcuts:
267
280
268
-
1. All of the 'Networking Entities' are typealiased as 'Yosemite Entities', and exposed publicly (Model.swift).
281
+
* All of the 'Networking Entities' are typealiased as 'Yosemite Entities', and exposed publicly (Model.swift).
269
282
This allows us to avoid the need for importing `Networking` in the main app, and also lets us avoid reimplementing, yet again,
270
283
the same entities that have been defined twice.
271
284
272
-
2. Since ResultsController uses internally a FRC, the Storage.Model *TYPE* is required for it's initialization.
285
+
* Since ResultsController uses internally a FRC, the Storage.Model *TYPE* is required for it's initialization.
273
286
We may revisit and fix this shortcoming in upcoming iterations.
274
287
275
288
As a workaround to prevent the need for `import Storage` statements, all of the Storage.Entities that are used in
@@ -283,12 +296,14 @@ It's important to note that the Main App is only expected to interact with ReadO
283
296
into a ReadOnly instance:
284
297
285
298
286
-
1. ReadOnlyConvertible
299
+
***ReadOnlyConvertible**
300
+
287
301
Protocol conformed by all of the Storage.Entities, allows us to obtain a ReadOnly Type matching the Receiver's Payload.
288
302
Additionally, this protocol define an API to update the receiver's fields, given a ReadOnly instance (potentially a Backend
289
303
response we've received from the Networking layer)
290
304
291
-
2. ReadOnlyType
305
+
***ReadOnlyType**
306
+
292
307
Protocol conformed by *STRONG* Storage.Entities. Allows us to determine if a ReadOnly type represents a given Mutable instance.
0 commit comments