longevity

A Persistence Framework for Scala and NoSQL

View project on GitHub

building the user aggregate

The user has four parts: the User, the UserProfile, and two natural keys: the Username and the Email. Let’s focus on the User first:

package simbl.domain

case class User(
  username: Username,
  email: Email,
  fullname: String,
  profile: Option[UserProfile]) {

  def updateProfile(profile: UserProfile): User = copy(profile = Some(profile))

  def deleteProfile: User = copy(profile = None)

}

The User case class provides us with the four members we find in the UML in the section on modelling our domain, including the relationship between User and UserProfile. There are also a couple of business methods inside: updateProfile and deleteProfile.

In longevity terminology, Users are persistent objects - that is, objects we want to persist in their own table or collection. We tell longevity that we want to persist them by marking them with the @persistent annotation:

package simbl.domain

import longevity.model.annotations.persistent

@persistent[SimblDomainModel]
case class User(
  username: Username,
  email: Email,
  fullname: String,
  profile: Option[UserProfile]) {

  def updateProfile(profile: UserProfile): User = copy(profile = Some(profile))

  def deleteProfile: User = copy(profile = None)

}

When we annotate User as a persistent class, longevity augments the User companion object, making it extend longevity.model.PType[SimblDomainModel, User]. It also creates a set of properties for us that we can use to reflect on User fields. It puts these properties in an inner object props in the User companion object. Now we can talk about User fields username and email with properties User.props.username and User.props.email.

In our companion object, we define keys on the username and email fields, specifying that these two member are to be unique: no two users should have the same username or email.

object User {
  implicit val usernameKey = primaryKey(props.username)
  implicit val emailKey = key(props.email)
}

The props.username and props.email are two of the properties fields that were put in by the @persistent annotation. The methods primaryKey and key are provided by the PType class that the User companion object now extends.

You can have as many keys as you like, but only one of the keys - in our case, the username key - can be a primary key. Primary keys perform better than other keys when you are using a distributed database, since the database can determine the node that holds the data by examining the key.

prev: declaring the domain model
up: getting started guide
next: the user profile