Skip to content

Commit f219c9c

Browse files
kamiazyaclaude
andcommitted
refactor: remove redundant jMolecules comments and improve ID extraction
This commit addresses code review feedback by cleaning up jMolecules-related comments and improving type safety for ID handling. Changes: - Added type-safe AggregateId.extractId() extension function - Replaced all substringAfterLast("/") usages with extractId() - Fixed URI scheme documentation (gid://scopes/Scope/{ULID}) - Added with() helper method to reduce boilerplate in applyEvent - Enhanced Association pattern documentation in Scope entity - Removed redundant "Implements jMolecules..." comments across codebase - Simplified architectural comments to focus on design decisions Technical improvements: - Type-safe ID extraction for both Simple and Uri formats - Better documentation of within-aggregate vs cross-aggregate references - Clearer separation of architectural explanations from implementation details All tests passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent ffe5feb commit f219c9c

File tree

16 files changed

+421
-103
lines changed

16 files changed

+421
-103
lines changed

contexts/device-synchronization/domain/src/main/kotlin/io/github/kamiazya/scopes/devicesync/domain/entity/SyncConflict.kt

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
package io.github.kamiazya.scopes.devicesync.domain.entity
22

3+
import io.github.kamiazya.scopes.devicesync.domain.valueobject.ConflictId
34
import io.github.kamiazya.scopes.devicesync.domain.valueobject.ConflictType
45
import io.github.kamiazya.scopes.devicesync.domain.valueobject.ResolutionAction
56
import io.github.kamiazya.scopes.devicesync.domain.valueobject.VectorClock
67
import kotlinx.datetime.Instant
8+
import org.jmolecules.ddd.types.Entity
79

810
/**
911
* Represents a synchronization conflict with rich domain logic for resolution.
1012
*
1113
* This entity encapsulates the business rules for conflict detection, analysis,
1214
* and resolution strategies.
15+
*
1316
*/
1417
data class SyncConflict(
18+
private val _id: ConflictId,
1519
val localEventId: String,
1620
val remoteEventId: String,
1721
val aggregateId: String,
@@ -23,7 +27,13 @@ data class SyncConflict(
2327
val detectedAt: Instant,
2428
val resolvedAt: Instant? = null,
2529
val resolution: ResolutionAction? = null,
26-
) {
30+
) : Entity<SyncState, ConflictId> {
31+
32+
/**
33+
* Use getId() to access the conflict ID.
34+
*/
35+
override fun getId(): ConflictId = _id
36+
2737
init {
2838
require(localEventId.isNotBlank()) { "Local event ID cannot be blank" }
2939
require(remoteEventId.isNotBlank()) { "Remote event ID cannot be blank" }
@@ -180,6 +190,7 @@ data class SyncConflict(
180190
require(remoteVersion >= 0) { "Remote version must be non-negative" }
181191

182192
return SyncConflict(
193+
_id = ConflictId.generate(),
183194
localEventId = localEventId,
184195
remoteEventId = remoteEventId,
185196
aggregateId = aggregateId,
@@ -191,6 +202,37 @@ data class SyncConflict(
191202
detectedAt = detectedAt,
192203
)
193204
}
205+
206+
/**
207+
* Create a new SyncConflict for testing purposes.
208+
* Auto-generates an ID.
209+
*/
210+
fun create(
211+
localEventId: String,
212+
remoteEventId: String,
213+
aggregateId: String,
214+
localVersion: Long,
215+
remoteVersion: Long,
216+
localVectorClock: VectorClock,
217+
remoteVectorClock: VectorClock,
218+
conflictType: ConflictType,
219+
detectedAt: Instant,
220+
resolvedAt: Instant? = null,
221+
resolution: ResolutionAction? = null,
222+
): SyncConflict = SyncConflict(
223+
_id = ConflictId.generate(),
224+
localEventId = localEventId,
225+
remoteEventId = remoteEventId,
226+
aggregateId = aggregateId,
227+
localVersion = localVersion,
228+
remoteVersion = remoteVersion,
229+
localVectorClock = localVectorClock,
230+
remoteVectorClock = remoteVectorClock,
231+
conflictType = conflictType,
232+
detectedAt = detectedAt,
233+
resolvedAt = resolvedAt,
234+
resolution = resolution,
235+
)
194236
}
195237
}
196238

contexts/device-synchronization/domain/src/main/kotlin/io/github/kamiazya/scopes/devicesync/domain/entity/SyncState.kt

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,36 @@ package io.github.kamiazya.scopes.devicesync.domain.entity
33
import io.github.kamiazya.scopes.devicesync.domain.valueobject.DeviceId
44
import io.github.kamiazya.scopes.devicesync.domain.valueobject.VectorClock
55
import kotlinx.datetime.Instant
6+
import org.jmolecules.ddd.types.AggregateRoot
67
import kotlin.time.Duration
78

89
/**
910
* Represents the synchronization state between this device and another device.
1011
*
1112
* This entity encapsulates the business logic for managing synchronization state,
1213
* including state transitions, sync readiness checks, and error handling.
14+
*
15+
* Each SyncState is uniquely identified by the remote DeviceId it syncs with.
1316
*/
1417
data class SyncState(
15-
val deviceId: DeviceId,
18+
private val _deviceId: DeviceId,
1619
val lastSyncAt: Instant?,
1720
val remoteVectorClock: VectorClock,
1821
val lastSuccessfulPush: Instant?,
1922
val lastSuccessfulPull: Instant?,
2023
val syncStatus: SyncStatus,
2124
val pendingChanges: Int = 0,
22-
) {
25+
) : AggregateRoot<SyncState, DeviceId> {
26+
27+
/**
28+
*/
29+
override fun getId(): DeviceId = _deviceId
30+
31+
/**
32+
* Public accessor for deviceId.
33+
*/
34+
val deviceId: DeviceId
35+
get() = _deviceId
2336
init {
2437
require(pendingChanges >= 0) { "Pending changes cannot be negative" }
2538
lastSuccessfulPush?.let { push ->

contexts/device-synchronization/domain/src/main/kotlin/io/github/kamiazya/scopes/devicesync/domain/valueobject/DeviceId.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
package io.github.kamiazya.scopes.devicesync.domain.valueobject
22

33
import io.github.kamiazya.scopes.platform.commons.id.ULID
4+
import org.jmolecules.ddd.types.Identifier
45

56
/**
67
* Represents a unique identifier for a device in the multi-device synchronization system.
78
*
89
* Each device participating in synchronization has a unique ID that is used to track
910
* which events originated from which device and to maintain vector clocks.
11+
*
1012
*/
1113
@JvmInline
12-
value class DeviceId(val value: String) {
14+
value class DeviceId(val value: String) : Identifier {
1315
init {
1416
require(value.isNotBlank()) { "Device ID cannot be blank" }
1517
require(value.length <= 64) { "Device ID cannot exceed 64 characters" }

0 commit comments

Comments
 (0)