This repository has been archived by the owner on Feb 9, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 80
Quill v2
Vicky Chijwani edited this page Aug 23, 2017
·
40 revisions
This is a brain-dump of thoughts for the next major version of Quill.
Before doing a big rewrite, write acceptance tests. Read this summary of Michael Feathers' Working Effectively with Legacy Code.
Consider a white+accent minimal theme like Medium and Asana. Current theme doesn't fit well with an app focused on writing. Other inspirations: iA Writer.
What changes will need to be done frequently?
- Compatibility changes as Ghost evolves (hopefully there will be fewer breaking changes after 1.0)
- Adding new fields in domain objects and exposing them in the UI
- Editor refinements
- Offline operation improvements (do we need to persist state as described here and in other recent "Building for Billions" talks?)
- Post content check-pointing for undo/time travel
- UI refinements
- Testability
- Independence from 3rd-party libs (using adapters?), especially Realm because its model is counter-intuitive which causes a lot of crashes (best option: do a safe integration of Realm, rather than a deep integration)
- Independence of core business logic from Android-specific APIs (quite difficult to do)
- Ghost 1.0 changes (especially at the DB level)
- Complexity of network code (e.g.,
onSyncPostsEvent
code;forceNetworkCall
vsloadCachedData
; ...) - Complexity of post state machine
- Background sync
- Figuring out what has changed on the server since the last time we checked - this is not as easy as it seems
- Multiple blogs logged in simultaneously
- Fully-offline operation (including image upload?)
- Image upload decoupled from editor UI (e.g., when sharing photos from other apps)
- Edit draft on phone, lock screen, publish from Ghost, unlock screen => published post is overwritten! (issue link)
- Spurious conflicts detected, aggravated by naive sync timing (see Fabric for stats)
- Temporal dependency of network requests is unoptimized, e.g., user info must be loaded before loading posts (to enforce Ghost's role-based permissions), and post upload must happen before download - there should be a declarative way to specify these dependencies, instead of the naive "refresh events queue" that we have now
- When a post is changed in the background while it is being edited, the logic to handle it is very flaky (
PostReplacedEvent
etc). Relevant issues: #125 - Can't cancel ongoing requests (e.g., stuck image uploads). With large timeouts (5 mins for
WRITE_TIMEOUT
), the ability to cancel - exposed to the user - is even more critical. - See
FIXME
comments in code - Keep other known issues in mind, see the labelled issues
Validate this against Ghost 1.0 OAuth plans (iirc they're planning to have a single auth mechanism for all blogs related to a single person - "person" might mean a Ghost account, or something else entirely).
- Provide a
BlogDataStore
interface to query and update a blog/account's data, have 2 implementations (NetworkBlogDataStore
andCacheBlogDataStore
perhaps, since we use a write-back cache strategy mostly). - For the
CacheBlogDataStore
:- ✓ Store data for each blog in a separate Realm file
- ✓ Move all blog url, credentials, etc (everything in
UserPrefs
currently) to the default Realm- ✓ Additionally map blog url + username => Realm file for that blog (store this mapping in the default Realm itself)
- ✓ Retrofit 2.x
- ✓ Realm 2.x
- ✓ RxJava 2.x - https://realm.io/news/gotocph-jake-wharton-exploring-rxjava2-android/
- ...
- Architecture inspiration (use wisely!):
- Represent the post state machine in its own class, independent of Android/Realm stuff for testability
- Use a lightweight state machine library for structure
- Functional core, imperative shell (https://www.destroyallsoftware.com/talks/boundaries)
- Make domain objects like
Post
immutable - If mutability is necessary, try to draw on ideas from React and the concept of Monads
- Make domain objects like
- Make all network calls synchronous:
- To allow reusing in background sync
- To enhance code readability
- Inject dependencies as far as possible, avoid singletons except for logging/analytics
- Use Jake Wharton's "Robot pattern" for UI tests
- Maybe use RxJava to refactor the ugly refresh and post upload logic (get rid of the queues!)
- Must store several copies of each post, at least these:
- Current edited, unsynced copy
- Copy of the post as it was when last synced from the server (in order to support "discard unpublished edits" offline; to show diff before publishing edits; and for better conflict-detection and possibly resolution, i.e., show the diff relative to common ancestor and the last-uploaded time of the device copy, maybe try a 3-way merge like git does - this last is probably overkill)