{"id":18708193,"url":"https://github.com/czajnikowski/babylon","last_synced_at":"2025-04-12T10:33:54.607Z","repository":{"id":75306509,"uuid":"195787325","full_name":"Czajnikowski/Babylon","owner":"Czajnikowski","description":"My demo submission to Babylon Health","archived":false,"fork":false,"pushed_at":"2020-07-05T11:18:32.000Z","size":2015,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-08-03T09:03:06.146Z","etag":null,"topics":["combine","combine-framework","ios","ios13","mvvm","reactive","reactive-programming","swift","swift5","swiftplaygrounds","swiftui"],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Czajnikowski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-07-08T10:11:14.000Z","updated_at":"2024-06-13T08:47:13.000Z","dependencies_parsed_at":"2023-06-06T02:15:27.669Z","dependency_job_id":null,"html_url":"https://github.com/Czajnikowski/Babylon","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Czajnikowski%2FBabylon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Czajnikowski%2FBabylon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Czajnikowski%2FBabylon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Czajnikowski%2FBabylon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Czajnikowski","download_url":"https://codeload.github.com/Czajnikowski/Babylon/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223511420,"owners_count":17157518,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["combine","combine-framework","ios","ios13","mvvm","reactive","reactive-programming","swift","swift5","swiftplaygrounds","swiftui"],"created_at":"2024-11-07T12:22:14.745Z","updated_at":"2024-11-07T12:22:15.538Z","avatar_url":"https://github.com/Czajnikowski.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/Czajnikowski/Babylon/raw/master/logo.png\"\u003e\n\u003c/p\u003e\n\nHello ~~Babylon~~\n==================================\n\n~~Thank you for taking the time to consider my demo during the recruitment process for the Remote Senior iOS Developer position at your company. I'd be more than happy to join your impressing team.~~\n\nInitially I prepared the demo as an assignment in the [interview process](https://github.com/Babylonpartners/ios-playbook/blob/master/Interview/README.md) for Babylon Health. I actually passed the demo stage and scored \"very well\", but the company decided to pause on hiring new remote engineers just a day before my Skype interview. Well 🤷🏼‍♂️\n\nIt's a pretty generic demo though. You may find some interesting bits there if you're interested in `SwiftUI`, `Combine`, Playground Driven Development or architecture. I appreciate constructive critique as well 🙂\n\n# Demo\n\nAs a demo, I've chosen [*The babylon demo project*](https://github.com/Babylonpartners/ios-playbook/blob/master/Interview/demo.md#1-the-babylon-demo-project).\n\n### Requirements\n\nXcode 11 Beta 5, no Catalina needed.\n\n### Dependencies\n\nI decided to stick to the native frameworks, so there are no 3rd party dependencies by now. The main frameworks of my choice are:\n\n- `Combine` for reactive programming\n- `SwiftUI` for the View layer\n- `Foundation` for networking and caching\n\n### Architecture\n\nThe responsibilities of the app are split across three separate frameworks and the app target itself:\n\n1. `View` - leaf framework concerned just about the presentation layer.\n2. `Networking` - leaf framework concerned about networking.\n3. `ViewModel` - framework depending on both `Networking` and `View` concerned about the bidirectional mapping of data between the `View` and underlying logic and services.\n4. `Babylon` app target - main target where dependency injection takes place via the `Coordinator`\n\nThere is a subtle difference between *classic* MVVM and my approach. In *classic* MVVM the View layer depends on ViewModel and in my approach, the ViewModel depends on the View.  \nSuch dependency graph makes `View` a decoupled, leaf framework making it easy to compile, develop and test independently. Thanks to it I've been able to leverage the Playground Driven Development technique to implement and troubleshoot both view's implementations (see `*.playground` in the project).  \nThe frameworks are additionally extracted into separate projects. This makes presumable cross-team development less prone to merge conflicts.\n\n### Tests\n\nI've written two, taking `PostListViewModel` under test (see `PostListViewModelTests` or Cmd + U on the `Babylon` scheme).  \nI've been trying to incorporate snapshot testing as well (see `snapshot_testing` branch) using `FBSnapshotTestCase` by Uber, but [it doesn't seem to work well with SwiftUI at the moment](https://github.com/uber/ios-snapshot-test-case/issues/97).\n\n### Known issues\n\n- [Eagerly evaluated destinations](https://twitter.com/chriseidhof/status/1144242544680849410)\n- [Problem with Alert binding](https://stackoverflow.com/questions/56762294/how-to-bind-presentation-of-swiftui-alert-when-triggered-outside-of-the-view)\n- [Unable to bind to animation](https://forums.developer.apple.com/thread/117824)\n- [Unable to embed multiline Text in vertically scrollable ScrollView](https://stackoverflow.com/questions/56593120/how-do-you-create-a-multi-line-text-inside-a-scrollview-in-swiftui)\n- [\"Reparenting nested renderer host -- preferences may be missing\"](https://www.reddit.com/r/swift/comments/c1spxh/reparenting_nested_renderer_host_preferences_may/\") while navigating to Details view\n\n### Requirements checklist\n\n✅ Swift 5.1.  \n✅ The information is available offline by leveraging the `URLCache`. The quickest-to-implement solution I can imagine.  \n✅ Reloading available as a navigation bar item in `PostListView`.  \n✅ Have a point of synchronization in `PostDetailsViewModel.loadData()`, I used a `Zip` for that.  \n✅ I find the code to be production grade. Not production ready though (uses iOS SDK beta 3).  \n✅ It compiles and runs.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fczajnikowski%2Fbabylon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fczajnikowski%2Fbabylon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fczajnikowski%2Fbabylon/lists"}