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
+18-15Lines changed: 18 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,7 @@ WooCommerce iOS's architecture is the result of a **massive team effort** which
5
5
coding rounds, and most of all: the sum of past experiences on the platform.
6
6
7
7
The goal of the current document is to discuss several principles that strongly influenced our current architecture approach, along with providing
8
-
details on how each one of the layer works internally.
8
+
details on how each one of the layers work internally.
9
9
10
10
11
11
@@ -17,7 +17,7 @@ Throughout the entire architecture design process, we've priorized several key c
17
17
18
18
1.**Do NOT Reinvent the Wheel**
19
19
20
-
Our main goal is to exploit as much as possible all of the things the platform already offers thru it's SDK,
20
+
Our main goal is to exploit as much as possible all of the things the platform already offers through its SDK,
21
21
for obvious reasons.
22
22
23
23
The -non extensive- list of tools we've built upon include: [CoreData, NotificationCenter, KVO]
@@ -42,8 +42,8 @@ Throughout the entire architecture design process, we've priorized several key c
42
42
43
43
3.**Immutability**
44
44
45
-
For a wide variety of reasons, we've opted for exposing Mutable Entities **ONLY** to our Service Layer.
46
-
The main app's ViewControllers can access to [Remote, Cached] Entities only through ReadOnly instances.
45
+
For a wide variety of reasons, we've opted for exposing Mutable Entities **ONLY** to our Service Layer (Yosemite.framework).
46
+
The main app's ViewControllers can gain access to [Remote, Cached] Entities only through ReadOnly instances.
47
47
48
48
(A) Thread Safe: We're shielded from known CoreData Threading nightmares
49
49
(B) A valid object will always remain valid. This is not entirely true with plain NSManagedObjects!
@@ -73,14 +73,14 @@ replace CoreData with any other database. Key notes:
73
73
1.**CoreDataManager**
74
74
75
75
In charge of bootstrapping the entire CoreData stack: contains a NSPersistentContainer instance, and
76
-
is responsible for loading both, the Data Model and the actual `.sqlite` file.
76
+
is responsible for loading both the Data Model and the actual `.sqlite` file.
77
77
78
78
2.**StorageManagerType**
79
79
80
80
Defines the public API that's expected to be conformed by any actual implementation that intends to contain
81
81
and grant access to StorageType instances.
82
82
83
-
**Conformed by CoreDatManager.**
83
+
**Conformed by CoreDataManager.**
84
84
85
85
3.**StorageType**
86
86
@@ -181,7 +181,7 @@ of performing this task for us:
181
181
Related Endpoints are expected to be accessible by means of a concrete `Remote` implementation. The `Remote` base class offers few
182
182
convenience methods for enqueuing requests and parsing responses in a standard and cohesive way `(Mappers)`.
183
183
184
-
`Remote(s)` receive a Network concrete instance via it's initializer. This allows us to Unit Test it's behavior, by means of the `MockupNetwork`
184
+
`Remote(s)` receive a Network concrete instance via its initializer. This allows us to Unit Test it's behavior, by means of the `MockupNetwork`
185
185
tool, which was designed to simulate Backend Responses.
186
186
187
187
@@ -196,7 +196,7 @@ Storage layers.
196
196
197
197
### Main Concepts
198
198
199
-
We've borrowed several concepts from the [WordPress's FluxC library](https://github.com/wordpress-mobile/WordPress-FluxC-Android), and tailored them down
199
+
We've borrowed several concepts from the [WordPress FluxC library](https://github.com/wordpress-mobile/WordPress-FluxC-Android), and tailored them down
200
200
for the iOS platform (and our specific requirements):
201
201
202
202
@@ -207,6 +207,9 @@ for the iOS platform (and our specific requirements):
207
207
208
208
*Allowed* to have a Closure Callback to indicate Success / Failure scenarios.
209
209
210
+
**NOTE:** Success callbacks can return data, but the "preferred" mechanism is via the EntityListener or
211
+
ResultsController tools.
212
+
210
213
2.**Stores**
211
214
212
215
Stores offer sets of related API's that allow you to perform related tasks. Typically each Model Entity will have an
@@ -247,15 +250,15 @@ for the iOS platform (and our specific requirements):
247
250
SomeAction >> Dispatcher >> SomeStore
248
251
249
252
A. [Main App] SomeAction is built and enqueued in the main dispatcher
250
-
B. [Yosemite] The dispatcher looks up for processors that support SomeAction.Type
253
+
B. [Yosemite] The dispatcher looks up for the processor that support SomeAction.Type, and relays the Action.
251
254
C. [Yosemite] SomeStore receives the action, and performs a task
252
255
D. [Yosemite] Upon completion, SomeStore *may* (or may not) run the Action's callback (if any).
253
256
254
257
2. Observing a Collection of Entities
255
258
256
259
ResultsController >> Observer
257
260
258
-
A. [Main App] An observer (typically a ViewController) initializes a ResultsController, and subscribes to it's callbacks
261
+
A. [Main App] An observer (typically a ViewController) initializes a ResultsController, and subscribes to its callbacks
259
262
B. [Yosemite] ResultsController listens to Storage Layer changes that match the target criteria (Entity / Predicate)
260
263
C. [Yosemite] Whenever there are changes, the observer gets notified
261
264
D. [Yosemite] ResultsController *grants ReadOnly Access* to the stored entities
@@ -276,7 +279,7 @@ It's important to note that in the proposed architecture Model Entities must be
276
279
277
280
A. **Storage.framework**
278
281
279
-
New entities are defined in the CoreData Model, and it's code is generated thru the Model Editor.
282
+
New entities are defined in the CoreData Model, and its code is generated thru the Model Editor.
280
283
281
284
B. **Networking.framework**
282
285
@@ -288,7 +291,7 @@ In order to avoid code duplication we've taken a few shortcuts:
288
291
This allows us to avoid the need for importing `Networking` in the main app, and also lets us avoid reimplementing, yet again,
289
292
the same entities that have been defined twice.
290
293
291
-
* Since ResultsController uses internally a FRC, the Storage.Model *TYPE* is required for it's initialization.
294
+
* Since ResultsController uses internally a FRC, the Storage.Model *TYPE* is required for its initialization.
292
295
We may revisit and fix this shortcoming in upcoming iterations.
293
296
294
297
As a workaround to prevent the need for `import Storage` statements, all of the Storage.Entities that are used in
@@ -304,13 +307,13 @@ into a ReadOnly instance:
304
307
305
308
***ReadOnlyConvertible**
306
309
307
-
Protocol conformed by all of the Storage.Entities, allows us to obtain a ReadOnly Type matching the Receiver's Payload.
308
-
Additionally, this protocol define an API to update the receiver's fields, given a ReadOnly instance (potentially a Backend
310
+
Protocol implemented by all of the Storage.Entities, allows us to obtain a ReadOnly Type matching the Receiver's Payload.
311
+
Additionally, this protocol defines an API to update the receiver's fields, given a ReadOnly instance (potentially a Backend
309
312
response we've received from the Networking layer)
310
313
311
314
***ReadOnlyType**
312
315
313
-
Protocol conformed by *STRONG* Storage.Entities. Allows us to determine if a ReadOnly type represents a given Mutable instance.
316
+
Protocol implemented by *STRONG* Storage.Entities. Allows us to determine if a ReadOnly type represents a given Mutable instance.
314
317
Few notes that led us to this approach:
315
318
316
319
A. Why is it only supported by *Strong* stored types?: because in order to determine if A represents B, a
0 commit comments