James Carl Sitsit

A repository interface is not cloud sync

FloatWatch keeps SQLite behind repository interfaces. That gives a cloud implementation one boundary, but it does not make synchronization a one-file job.

By James Carl Sitsit

I gave FloatWatch a clean storage boundary, but that boundary does less than I first claimed. The repository interfaces are real. Cloud sync is not.

The app currently runs on one phone. SQLite stores the data, ML Kit handles OCR on-device, and the daily flow does not call a server. That fits the unreliable connections the app was built around, but it also means a lost phone is a lost ledger.

The boundary that exists

Screens and providers talk to repository interfaces. main.dart chooses the local implementations:

final ownerRepo = LocalOwnerRepository(dbHelper);
final staffRepo = LocalStaffRepository(dbHelper);
final transactionRepo = LocalTransactionRepository(dbHelper);

Those lines are useful because the UI does not construct SQLite classes directly. A future implementation has a defined place to enter the app, and the existing providers can keep calling the same repository methods if that contract still fits.

The boundary has already helped keep the OCR work separate from storage work. That is the payoff I can claim today.

The cloud claim goes too far

It is tempting to call the future Firebase swap a one-file change. I have not earned that sentence.

Changing the constructors in main.dart would select different repository classes. It would not prove that synchronization works, that local behavior survives without a connection, or that the existing interface covers everything a cloud-backed version needs. I have not built the cloud implementation, so the number of files involved is unknown.

The interface is not stubbed either. The local interface and its implementations are doing real work. What is missing is the cloud side and the behavior that would connect it to the local app.

What the pattern actually buys

The repository layer buys a place to make the next change. That is smaller than buying the change itself, but it is still useful.

If the future cloud repositories fit the same contract, less code above the boundary should move. If they do not, the interface will change and the app will show me where my assumptions leaked. I will only know after building it.

Today, main.dart wires three local repositories and the daily flow works without a server. That is what shipped. Cloud sync stays a TODO until it exists.


This is from FloatWatch, a Flutter app that reconciles a GCash outlet's cash and e-float on-device. The full build is in the FloatWatch deep dive.