Skip to content

Refactoring to use model classes instead of database entitites#1347

Open
Futsch1 wants to merge 33 commits intomainfrom
databaseEntityToModel
Open

Refactoring to use model classes instead of database entitites#1347
Futsch1 wants to merge 33 commits intomainfrom
databaseEntityToModel

Conversation

@Futsch1
Copy link
Copy Markdown
Owner

@Futsch1 Futsch1 commented Apr 6, 2026

No description provided.

Futsch1 added 24 commits April 2, 2026 17:31
# Conflicts:
#	app/src/main/java/com/futsch1/medtimer/reminders/ReminderNotificationProcessor.kt
#	app/src/test/java/com/futsch1/medtimer/processortests/NotificationProcessorTest.kt
#	app/src/test/java/com/futsch1/medtimer/processortests/RefillProcessorTest.kt
#	app/src/test/java/com/futsch1/medtimer/processortests/RepeatProcessorTest.kt
#	app/src/test/java/com/futsch1/medtimer/processortests/ScheduleNextReminderNotificationProcessorTest.kt
Resolved conflicts by keeping entity naming convention (*Entity suffix)
and adding mapper layer in ReminderEventRepository to bridge between
database entities and domain model ReminderEvent.
# Conflicts:
#	app/src/main/java/com/futsch1/medtimer/database/MedicineRepository.kt
#	app/src/main/java/com/futsch1/medtimer/reminders/NotificationProcessor.kt
#	app/src/main/java/com/futsch1/medtimer/statistics/CalendarEventsViewModel.kt
@Futsch1 Futsch1 marked this pull request as draft April 6, 2026 07:24
@qltysh
Copy link
Copy Markdown
Contributor

qltysh bot commented Apr 6, 2026

2 new issues

Tool Category Rule Count
qlty Structure Function with many parameters (count = 6): Factory 1
qlty Structure Complex binary expression 1

@Futsch1
Copy link
Copy Markdown
Owner Author

Futsch1 commented Apr 6, 2026

@ThomasKiljanczykDev
I have drafted the PR to use only model classes in the application code. It is also a big one, but the scope of changes is limited to this (and a few minor things left and right). Please have a look.

Android Tests still fail, so there's a few bugs left which I will fix.

Copy link
Copy Markdown
Contributor

@ThomasKiljanczykDev ThomasKiljanczykDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't reviewed everything, but some of these comment are disruptive enough that the code might change a lot.

I will continue the review once you address my current comments.

private val reminderRepository: ReminderRepository,
private val reminderEventRepository: ReminderEventRepository,
private val tagRepository: TagRepository,
private val medicineDao: MedicineDao,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have you replaced repositories with dao?
The repositories were meant to abstract ALL the code from the db implementation.

With this mixed approach you're breaking this layer of abstraction

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have moved this class into the database package for a reason: I consider the backup tightly coupled to the database implementation, so it is a database backup, not a model backup (also for the sake of compatibility). Since repositories interface is now based on the model classes, the backup requires a direct database access.

So I do not consider this breaking the abstraction.


private fun createAndSave(fileContent: String?) {
val file = File(context.cacheDir, backupFilename)
val file = File(context.cacheDir, PathHelper.backupFilename)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Helper (and Util) is a very vague name which often leads to dumping a lot of unrelated code into a single class.
It would probably be better to give it some more sensible name

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

val id: Int,
val color: Int,
val useColor: Boolean,
val notificationImportance: ReminderNotificationChannelManager.Importance,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should probably extract the importance into NotificationImportance to make it independent from the channel manager. Channels themself are more part of the application layer

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

) : JSONBackup<FullMedicineEntity>(FullMedicineEntity::class.java) {
override fun createBackup(databaseVersion: Int, list: List<FullMedicineEntity>): JsonElement {
// Correct the medicines where the reminder's instructions are null in this loop
for (fullMedicine in list) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use flatMap here instead of this for

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


private suspend fun processTags(fullMedicine: FullMedicineEntity, medicineId: Int) {
for (tag in fullMedicine.tags) {
val tagId = tagDao.create(tag).toInt()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should probably sort this ID casting nonsense.

It should be either int everywhere or long everywhere.
Long is the safer option since the performance impact should not be that noticeable and you get practically infinite possible values

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not see how: Room always returns long from @insert operations. I chose to use int as ID type some time ago and do not want to do a migration just to change this to long.

The repositories now always return int IDs, so towards the application it's int only. Internally, we have to do a cast, but I do not see how this hurts.

}
}

private suspend fun processReminders(fullMedicine: FullMedicineEntity, medicineId: Int) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should accept the domain model and copy the reminders (with id reset)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment above: I'd like to keep the backup logic close to the database structure.

@Entity
class Medicine() {
@Entity(tableName = "Medicine")
class MedicineEntity() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could move all the properties into the constructor so you create new entities more easily without for default values

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@Futsch1
Copy link
Copy Markdown
Owner Author

Futsch1 commented Apr 7, 2026

@ThomasKiljanczykDev
I have addressed all your review comments

@Futsch1 Futsch1 marked this pull request as ready for review April 8, 2026 17:11
@Futsch1
Copy link
Copy Markdown
Owner Author

Futsch1 commented Apr 11, 2026

@ThomasKiljanczykDev
Can you let me know when you'll be able to review? No hurries, but still would be good to know...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants