chriswarbo-net: fecd606e17878229bbcae9f7c7424125318a7d49

     1: ---
     2: title: Optional Datatype Fields
     3: ---
     4: 
     5: I've been working on a bunch of Scala codebases recently, which represent data
     6: using classes with optional fields. For example (not actual code!):
     7: 
     8: ```scala
     9: case class User(
    10:   userID: String,
    11:   name: Option[String],
    12:   email: Option[String],
    13:   phone: Option[String],
    14:   dateOfBirth: Option[Date],
    15: )
    16: ```
    17: 
    18: There are a few problems with this sort of representation:
    19: 
    20:  - It's 'stringly typed': using uninformative types like 'String', rather than
    21:    something more specific like 'UserID', 'Email', etc.
    22:  - Using this sort of representation is awkward, e.g.
    23:    `val myUser = User(myID, None, None, None, Some(myDOB))`
    24:  - This representation does not scale well, as we add new fields.
    25: 
    26: ## Rich Types ##
    27: 
    28: The first problem is easy eough to fix. Values with some particular structure
    29: can use a representation which follows that structure. For example, not every
    30: `String` is a valid email address: there must be two parts separated by '@', and
    31: each part has further restrictions (e.g. the first part cannot be empty, cannot
    32: contain the '@' character, etc.; whilst the second part must be a valid domain
    33: name, like 'localhost', 'gmail.com', etc.). These constraints give rise to
    34: 'correct by construction' representations like the following:
    35: 
    36: ```scala
    37: final case class Email(
    38:   private user: Username,
    39:   private host: DomainName,
    40: ) {
    41:   override lazy val toString: String = user.toString + '@' + host.toString
    42: }
    43: ```
    44: 
    45: Types which don't have any known structure can use a 'newtype' (borrowing
    46: terminology from Haskell). In Scala we do that with `AnyVal`, like this:
    47: 
    48: ```scala
    49: final case class Name(override val toString: String) extends AnyVal
    50: ```
    51: 
    52: ## Smarter Constructors ##

Generated by git2html.