Day 4 - Task Entity and Designing the Brand

Olaoluwa Oke| 28 February 2024

This afternoon, I sat at my desk wondering why my TaskRequest DTO wasn’t being recognized. Turned out I had actually named it TaskCreateRequest in the code. Minor mistake, but it killed my flow and even made me pause my music.



Most of today went into building the Task entity. Sticking to the Interface Metaphor idea, I almost named it Chores — more homely — but ironically, I type “chores” slower than “task.” So “task” it is.

ERD image
I gave each task a name, a description, a due date, and some logic around recurrence and completion. More importantly, it can be assigned to someone — though I had to remind myself that not every task starts off with an owner. So assignedTo needed to be nullable. Took me a second to realize that.

ERD image


I built the usual DTOs:
  • TaskCreateRequest — incoming payload for new tasks.
  • TaskUpdateRequest — for edits or status changes.
  • TaskResponse — what goes back to the client.


  • I also wrote a repository method to find tasks by name, then immediately questioned it. Task names aren’t unique. Every shared house on the planet has “Take out trash” and “Clean bathroom.” It makes more sense to query by roomId, or maybe by (roomId, name, assignedTo) together.


    Technical Log


    1. Entity Definition
    @Document(collection = "tasks")
    data class Task(
        @Id val id: String? = null,
        val name: String,
        val description: String?,
        val dueDate: Instant?,
        val assignedTo: String?, // userId, nullable
        val roomId: String,
        val status: TaskStatus = TaskStatus.PENDING,
        val recurrence: Recurrence? = null,
        val createdAt: Instant = Instant.now()
    )
    
                                            


    2. Enums

    enum class TaskStatus { PENDING, IN_PROGRESS, COMPLETED }
    enum class Recurrence { DAILY, WEEKLY, MONTHLY, NONE }
    

    3. DTOs

  • TaskCreateRequest — name, description, dueDate, assignedTo, recurrence.
  • TaskUpdateRequest — editable fields like status, assignedTo, dueDate
  • TaskResponse — includes id, createdAt, and computed status.

  • 4. Repository Layer
    interface TaskRepository : MongoRepository<.Task, String> {
        fun findByRoomId(roomId: String): List<.Task>
        fun findByRoomIdAndName(roomId: String, name: String): List<.Task>
    }
    

    Note: Dropped the idea of a global findByName due to non-uniqueness across rooms.

    5. Service Layer Operations
  • createTask(request: TaskCreateRequest): TaskResponse
  • updateTask(taskId: String, request: TaskUpdateRequest): TaskResponse
  • deleteTask(taskId: String)
  • getTasksInRoom(roomId: String): List<.TaskResponse>
  • assignTask(taskId: String, userId: String)