Edmund is a complex software. It is the first Apple targeting app I have ever written, and as a result, is rough around the edges. This document will overview what changes are planned/in-progress to help the software evolve.
While most features are overviews, this page will go into the technical details.
SwiftData and Core Data are persistent ORM libraries provided by Apple. They both allow for developers to store classes into SQLite databases, fetch them, and perform complex queries.
However, Core Data is much older than SwiftData. While Apple has made considerable efforts to bring rich functionality to SwiftData, its convenience stuns true work. However, Edmund was built on top of SwiftData. Due to its limitations, specifically with iCloud sync and lack of documentation, the complexity of Edmund grew tremendously.
For example. Consider the internal class representing a transaction, LedgerEntry. Since SwiftData does not allow for validation-on-save, validation was performed on a separate class. Secondly, since each LedgerEntry was bound to the user interface, one could not modify the LedgerEntry without causing UI glitches. As such, a "snapshot" type was created. This type mirrored LedgerEntry, but had support for validation.
Unfortunately, this lead to duplicated code. We would have one class for the SwiftData storage, and another for editing/validation. Since Edmund has 15 SwiftData models, it can be clearly seen how this was not sustainable. To make matters worse, iCloud sync complicated things further. One goal for Edmund is to support iCloud sync, so that users have their data on each device. However, due to CloudKit's restrictions uniqueness validation (very common in Edmund), must be completed manually.
Overall, this led to a deep rabbit hole. A new actor was created, ValidationEngine. It was in charge of ensuring uniqueness. But, since it was an actor (requirement since it was shared between the UI and the background), no action was synchronous. But, the UI does not support async work, so some weird workarounds were crafted.
Long story short, SwiftData added a huge amount of complexity and redundant code to the project. However, SwiftData is built on top of Core Data. Core Data, which is much older, more stable, and well documented, allows for low-level control. For example, it allows for validation within the model class. This removed the need for the ValidationEngine, "snapshot" types, etc. These validation functions run synchronously, so no weird workarounds.
Edmund is currently undergoing this refactor from SwiftData to Core Data. So far, about 4,000 lines of code have been removed. Huge win there. Additionally, the Element system was standardized, so that code was separated out into ExDisj-Swift. This refactor is massive, and will require at least 2 more months of work. This is to make the UI and user experience stable.
As hinted previously, much of the standard backbone of Edmund was moved to ExDisj-Swift. Such a move was intentional, as it allows for us to focus on building and improving Edmund.
This will bring some new, consistent features to Edmund, and help unify it with Ghosted and have more trust in the system.
ExDisj-Swift also contains may tools that reduce repeated sequences in the UI. For instance, instead of binding a sheet to handle editing and inspection, ExDisj-Swift provides the '.withElementIE' view modifier. This will help reduce a lot of redundant UI code.
A major goal for Edmund is iCloud sync. This will allow users to share their data across devices, and opens doors to allow for collaboration on budgets. More research and planning is needed for Edmund to support it. While the data contained does support it, with some extra validation, a "game plan" is needed. CloudKit, the supporting technology, is very strict about data migrations, or changes to the classes. As such, we do not want to incorporate features/data that will become a problem later.
Edmund used to support a feature called sub-accounts. This allowed an account balance to be distributed amongst smaller units. This follows the envelope accounting style. However, after collecting feedback during beta testing, it was determined that the feature was too complex for most users, and requires either simplification or education. As such, the feature was removed.
However, with the proper education and understanding of its use, envelope accounting can help users tremendously. To help with understanding, we renamed it from "sub-accounts" to "envelopes", to give a better mental image. To allow both simple and advanced budgeting, we are working to make this feature opt-in. By default, Edmund will appear to not use envelopes. Users will select accounts, and Edmund will do the heavy lifting in the background. If the user is not using envelopes, Edmund will pick a "default" envelope to use. However, if users switch to enabling envelopes, the UI will allow them to create, edit, and select them. Regardless, the internal workings will always use envelopes.
Edmund currently features "widgets" as customizable units on the homescreen. While this is not changing, we would like to include widgets outside the app. Edmund will have widgets for:
To help users with data integrity, organization, and overall peace of mind, we will add import and export functionality. If a file is exported, you will be able to view its contents, but you cannot edit them. After exporting, Edmund will ask if you want to "purge" the ledger, which will reset all transactions, and then add the initial balances. This can help you separate different periods of your budget.