2014-05-23 68 views
1

我正在創建一個新的域對象模式。在這個模型中,有User s和Post s。未來將會有更多的模型(例如Comment s)。我正試圖學習如何使用Scala來完成它。這裏有一個天真的實現:斯卡拉域對象建模

class User(val id: String, val creationDate: DateTime, val name: String, val email: String) 
class Post(val id: String, val creationDate: DateTime, val user: User, val title: String, val body: String) 

而這裏的另一種方法試圖擺脫重複idcreationDate的。

class Model(val id: String, val creationDate: DateTime) 
class User(id: String, creationDate: DateTime, val name: String, val email: String) extends Model(id, creationDate) 
class Post(id: String, creationDate: DateTime, val user: User, val title: String, val body: String) extends Model(id, creationDate) 

我想緩和一些我的域對象。爲此,我想添加一個isApproved: Boolean字段。

class Model(val id: String, val creationDate: DateTime) 
class User(id: String, creationDate: DateTime, val name: String, val email: String) extends Model(id, creationDate) 
class Post(id: String, creationDate: DateTime, val user: User, val title: String, val body: String) extends Model(id, creationDate) 

trait Moderated { 
    val isApproved: Boolean 
} 

class ModeratedPost(id: String, creationDate: DateTime, val user: User, val title: String, val body: String, val isApproved: Boolean) extends Post(id, creationDate, user, title, body) with Moderated 

我還想通過鍵入aliasing user和post id來防止我的代碼中的錯誤。

type Id = String 
type UserId = Id 
type PostId = Id 

class Model(val id: Id, val creationDate: DateTime) 
class User(id: UserId, creationDate: DateTime, val name: String, val email: String) extends Model(id, creationDate) 
class Post(id: PostId, creationDate: DateTime, val user: User, val title: String, val body: String) extends Model(id, creationDate) 

trait Moderated { 
    val isApproved: Boolean 
} 

class ModeratedPost(id: String, creationDate: DateTime, val user: User, val title: String, val body: String, val isApproved: Boolean) extends Post(id, creationDate, user, title, body) with Moderated 

在這一點上,我有幾個問題。

我應該在哪裏定義我的類型別名?我認爲他們必須在類,特質或對象內部進行定義。

我爲我的ID使用類型別名的目標是在編譯時捕獲錯誤。我想UserIdPostId是Id的「子類」。即如果方法採用Id,我可以通過PostId。我應該怎麼做?

我的Moderated性狀不覺得很有用。我仍然需要在所有混合它的類上聲明isApproved。這裏有什麼提示?

+5

類型別名加零類型安全。爲系統中的每個概念不同的實體創建適當的抽象。除了在絕對任何輸入值(字符串或數字等)有效的罕見情況下,通過對這些值施加約束的工廠強制所有創建。不要從構造函數中拋出異常。使用'Try' /'Success' /'Failure'(或ScalaZ'Validation'),而不是在檢測到無效參數時拋出異常。 –

回答

1

慣用的Scala會去是這樣的:

sealed trait Id { def strVal: String } 
case class UserId(strVal: String) extends Id 
case class PostId(strVal: String) extends Id 

trait Model { def id: Id, def creationDate: DateTime) 

case class User(
    id: UserId, 
    creationDate: DateTime, 
    name: String, 
    email: String 
) extends Model 

trait Post extends model { 
    def id: PostId 
    def user: User, 
    def title: String, 
    def body: String 
) 

trait Moderated { def isApproved: Boolean } 

case class UnmoderatedPost(
    id: PostId 
    creationDate: DateTime, 
    user: User, 
    title: String, 
    body: String, 
) extends Post 

case class ModeratedPost(
    id: PostId, 
    creationDate: DateTime, 
    user: User, 
    title: String, 
    body: String, 
    isApproved: Boolean 
) extends Post with Moderated 
1

您可以在package.scala中定義可以爲每個包創建的類型別名。

可以說你有一個簡單的包org.your.project。 創建目錄組織文件/叫你的/項目:package.scala

package org.your.project 

package object Types { 

    type Id = String 
    type UserId = Id 
    type PostId = Id 

} 

然後在您希望使用的類型別名添加類:

import org.your.project.Types._ 

我可能不會使用類型for你正在考慮的原因。 一種類型的Id也可以是一個Int,但是你把它作爲一個字符串。 任何閱讀代碼的人都必須點擊代碼庫來找出Id的真正含義。