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
+19-18Lines changed: 19 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@ Navitia provides two routes that TNPR uses:
14
14
15
15
### Layers
16
16
17
-
TNPR follows the MVVM architecture. Well, at leat it follows my interpretation of it.
17
+
TNPR follows the MVVM architecture. Well, at least it follows my interpretation of it.
18
18
19
19

20
20
@@ -26,7 +26,7 @@ In this diagram, you see:
26
26
- The ViewModel: as [the Presentation Model described by Martin Fowler](https://martinfowler.com/eaaDev/PresentationModel.html), this is "an abstract of the view that is not dependent on a specific GUI framework".
27
27
So theoretically, it could be reused in any app targeting any UI framework e.g. Android, iOS or the web using Kotlin Multiplatform, Android or the desktop using Compose...
28
28
- The Model: this is where TNPR's "intelligence" resides.
29
-
When the app has to process data, it does it by converting the data into internal representation that is not at all tied to the view (ViewModel → Model), does the processing (`processingModel = model(data)`), and then converts the data into a representation (`uiState.updatedWith(processingModel)`) that can be easily displayed by the View (Model → ViewModel).
29
+
When the app has to process data, it does it by converting the data into internal representation that is not at all tied to the View (ViewModel → Model), does the processing (`processingModel = model(data)`), and then converts the data into a representation (`uiState.updatedWith(processingModel)`) that can be easily displayed by the View (Model → ViewModel).
30
30
TNPR does not have a proper `model` package or classes, but the `model(data)` is defined as a pure function: it only converts data, applying computations in the process.
31
31
- The "cloud" (mainly Navitia web services)
32
32
@@ -35,17 +35,18 @@ To learn more about that, see [the MVVM experiment section](#mvvm-viewviewmodelm
35
35
### Dependencies
36
36
37
37
The dependencies of TNPR can be represented in two ways:
38
-
- Abstract, where each dependency is labeled in a generic way, independant of the framework: "standard library", "type-safe HTTP client"...
39
-
This exact representation of the dependencies could apply to the same application not targeting Android, but instead a web browser or a desktop OS.
40
-
- Concrete, where each dependency is labeled specifically as the implementation that is used in TNPR: "standard libary" → `kotlin.stdlib`, "type-safe HTTP client" → `com.squareup.retrofit2`.
38
+
39
+
-**Abstract**, where each dependency is labeled in a generic way, independant of the framework: "standard library", "type-safe HTTP client"...
40
+
This representation of the dependencies could apply to the same application not targeting Android, but instead a web browser or a desktop OS.
41
+
-**Concrete**, where each dependency is labeled specifically as the implementation that is used in TNPR: "standard libary" → `kotlin.stdlib`, "type-safe HTTP client" → `com.squareup.retrofit2`.
Each diagram is split into high-level packages: Application, Network, UI, Runtime environment and Language.
47
48
48
-
Read on to learn about these packages.
49
+
Read on to learn more about these packages.
49
50
50
51
#### Application (`me.cpele`)
51
52
@@ -65,15 +66,15 @@ These libraries have been chosen because they are well established and widely kn
65
66
66
67
Some UI components come from [Material Components](https://material.io/components?platform=android).
67
68
68
-
Why? Material components are cross-platform, abundantly documented and commonly used.
69
+
Why? Material components are cross-platform, documented and commonly used.
69
70
70
71
## Language: `org.jetbrains`
71
72
72
73
The app depends on this package that provides the Kotlin standard library (`kotlin.stdlib`) and the Coroutines library (`kotlinx.coroutines`).
73
74
74
-
Coroutines are used to implement asynchronous operations like calls to web services.
75
+
Coroutines are used to implement asynchronous operations like calling web services.
75
76
76
-
Flows are used to implement asynchronous operations reperesented as streams, for example it allows to handle the user input in the Autosuggest screen.
77
+
`Flow`s are used to implement asynchronous operations reperesented as streams, for example it allows to handle the user input in the Autosuggest screen.
77
78
78
79
## Runtime environment: `androidx`
79
80
@@ -85,7 +86,7 @@ The `core` subpackage is for extensions of the Android SDK, it brings e.g. `View
85
86
86
87
`appcompat` implements components that supersed those that come with the Android SDK, it has better backward and forward compatibiliy e.g. `ActivityCompat`.
87
88
88
-
`navigation` is the Jetpack component to implement navigation. It has drawbacks, mostly in the dependency relations it requires, but it was a simple way to design the app's navigation efficiently. It also provides editing tools that offer a global view of the app's UI, as you'll see [in the Features section](#features-diagram).
89
+
`navigation` is the Jetpack component to implement navigation. It has drawbacks, mostly in the dependency relations it requires, but it was a simple way to design the app's navigation quickly. It also provides editing tools that offer a global view of the app's UI, as you'll see [in the Features section](#features-diagram).
89
90
90
91
### Features
91
92
@@ -95,18 +96,18 @@ Thanks to Jetpack Navigation, here is a diagram showing all of the app's screens
95
96
96
97
### Experiments
97
98
98
-
This app was a way for me to try a few things I could not try on my day job as and Android developer. In this section you'll find some of the experiments I tried.
99
+
This app was a way for me to try a few things I could not try on my day job as an Android developer. In this section you'll find some of the experiments I tried.
99
100
100
101
#### Transmodel data model
101
102
102
-
Transmodel is the name of a reference data model to represent public transport data. I tried to use it as the internal data model of the application, but decided not to use it.
103
+
Transmodel is the name of a european reference data model to represent public transport data. I tried to use it as the internal data model of the application, but decided not to.
103
104
104
105
Transmodel is a complex model, its complexity comes from features which were not useful for the purpose of TNPR, notably:
105
106
106
-
- Separate concepts for the spatial and temporal aspects of transport data
107
-
- A representation for passengers, drivers and other types of "users" of public tranport modes
107
+
- Separate representations for the spatial and temporal aspects of transport data
108
+
- A representation for passengers, drivers and other types of users of public tranport modes
108
109
109
-
I choosed to stay with a projection of the Navitia data model. By "projection" I mean that I took the model as is, only keeping the resources and attributes I wanted TNPR to manage. Navitia's model is simpler and better suited for an application that is only targeted at passengers.
110
+
I choosed to use a simpler data model, which is a projection of the Navitia data model. By "projection" I mean that I took the Navitia model as is, only keeping the resources and attributes I wanted TNPR to manage. Navitia's model is better suited for an application that is only targeted at passengers.
110
111
111
112
#### AFK custom framework
112
113
@@ -119,7 +120,7 @@ It contains:
119
120
-`Component`: this is an interface that can be implemented by the app's `ViewModel`s:
120
121
- It has a `dispatch(Action)` method which executes an `Action`. An `Action` could be e.g. `LoadData(id: Int)` to trigger a request to a web service and load data, or `SearchJourneys(origin: Place, destiation: Place)` to find a journey from a point A to a point B.
121
122
- It has a `stateLive` property representing the "state" or "model" of a view, expressed in a way that should be independent of the UI framework.
122
-
- It has an `eventLive` property that allows one-shot "events" or "effects" to come back to the UI without forcing the `Component` to retain a reference to the view.
123
+
- It has an `eventLive` property that allows one-shot "events" or "effects" to come back to the UI without forcing the `Component` to retain a reference to the View.
123
124
124
125
- Some utility classes or functions:
125
126
-`ViewModelFactory`: a generic `ViewModelProvider.Factory` that is used to instantiate a `ViewModel` from an `Activity` or a `Fragment` like this:
@@ -315,7 +316,7 @@ override fun onActivityCreated(savedInstanceState: Bundle?) {
315
316
}
316
317
```
317
318
318
-
And here is `RoadmapViewModel.load()`. It sends an `Input.Start`:
319
+
Here is `RoadmapViewModel.load()`. It sends an `Input.Start`:
319
320
320
321
```kotlin
321
322
funload(tripId:String) {
@@ -345,7 +346,7 @@ fun load(tripId: String) {
345
346
}
346
347
```
347
348
348
-
😅
349
+
Easy 😅
349
350
350
351
This experiment should be conducted in a more complex use case, but I have the intuition that it would not be worth it. Perhaps when the app has to interact with many third party SDKs or frameworks? I don't know.
0 commit comments