afonso
04/01/2022, 1:41 PMMigratorService
in iosMain
, including all the necessary platform-specific models. I had to implement these models because I wanted to take this opportunity to revisit all the existing models and improve their structure which makes the native models not match 1-1 with the new ones.
But now I’m at a crossroads since I have no way to call the MigratorService
from commonMain
. So I either:
• Move all the code I’ve done in iosMain
to commonMain
. This has the potential risk of exposing old iOS related code to Android and the potential scenario where an Android app might try to run the migration. It also makes code ergonomics a bit more complicated, since I have a User
common model and an old User
iOS model.
• Create an expect MigratorService
in commonMain, with the actual implementation being on iosMain
. But this approach implies also adding a complete no-op
version of MigratorService
in androidMain
. Which is exposing an API that doesn’t really do what is expected.
Which one would be considered the best practice in KMM and why? Or is there another alternative to tackle these situations?kpgalligan
04/01/2022, 5:03 PMMigratorService
from commonMain
if it has no equivalent in Android? There’s no “best practice” here as far as I understand your situation. You need to code common models and both platforms can use them, or you have some iOS specific code in iosMain
. You can have a common interface that is implemented by iOS and be a no-op on Android. While that may not seem ideal, I don’t understand your code or problem in the abstract, so it’s not feasible to say if that is or isn’t a good idea (I would for sure not do expect/actual for that kind of thing, however).afonso
04/01/2022, 5:43 PMNativeUser
.
Since I will want to share the user model with android and iOS and take this opportunity to do a bit of refactoring, I created in commonMain
a User
model.
In order to bring the the information from the current version of the app, in iOSMain
I replicated a class for the user, the NativeUser
model and created a MigrationService
that loads the file from the bundle, decodes it into a NativeUser
and then I migrate the data to fit a User
object and save it in the new location, marking the migration complete.
This MigrationService
should a property of a ModuleManager
(for dependency injection purposes) defined in commonMain
. When ModuleManager
receives the call to performMigration
, it ideally calls the method performMigration
of the MigrationService
.
But since all this is happening in commonMain
and my implementation of the MigrationService
is in iOSMain
I’m not sure how I can make this happen without defining an expect/actual MigrationService
or simply moving everything to commonMain
(which isn’t ideal because I’d lose access to Foundation specific things like NSBundle
and NSDate
, but can be worked around).kpgalligan
04/01/2022, 7:38 PMMigrationService
needs to be a properly of ModuleManager
. Were I building this, generally speaking, you always have an entry point for each platform that gets called when the app starts to init the shared Kotlin. In there I’d probably check if the migration needed to happen, and it would be MigrationService
calling into something from commonMain to do the initial migration. However…kpgalligan
04/01/2022, 7:41 PMMigrationServiceIntf
(for lack of a better name), with one method (performMigration). Android and iOS implement their own version, and you DI those. Android’s indeed does nothing, but if you need to have everything injected in commonMain, that’s the simplest plan. Again, expect/actual for something like this is inflexible and I’d not use that. That is for sure my best practice advice here.afonso
04/01/2022, 7:53 PMPersistenceService
as part of the ModuleManager
, that way once I get the NativeUser
object transformed into a User
one, I can simply fire it to the persistence service, to do its thing. The persistence service is not something that is visible from outside the ModuleManager
, as it’s merely an implementation detail.
your approach is quite interesting, I guess I’d just have to create a
class MigrationService: MigrationServiceIntf {}
both on androidMain
and iOSMain
and everything should work.
One last thing, why do you say expect/actual is inflexible and not the right approach to handle this? I fear I might be using it wrong now 😬kpgalligan
04/01/2022, 7:58 PMkpgalligan
04/01/2022, 7:58 PMkpgalligan
04/01/2022, 7:59 PMkpgalligan
04/01/2022, 8:00 PMafonso
04/01/2022, 8:10 PM