Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如果制作很多函数别名并在任何地方组合它们,这是一个好的设计吗?_Scala_Design Patterns_Functional Programming - Fatal编程技术网

Scala 如果制作很多函数别名并在任何地方组合它们,这是一个好的设计吗?

Scala 如果制作很多函数别名并在任何地方组合它们,这是一个好的设计吗?,scala,design-patterns,functional-programming,Scala,Design Patterns,Functional Programming,我正在从事一个scala项目,它有非常实用的代码。它定义一个包对象,并使用type定义许多函数类型别名,如: package object updater { type FetchUser = UserSource => FetchFailed \/ FetchResult[BasicUser] type PublishUser = BasicUser => PublishFailed \/ OK type UpdateLastChangedUser = Ch

我正在从事一个scala项目,它有非常实用的代码。它定义一个包对象,并使用
type
定义许多函数类型别名,如:

package object updater {
    type FetchUser = UserSource => FetchFailed \/ FetchResult[BasicUser]
    type PublishUser = BasicUser => PublishFailed \/ OK
    type UpdateLastChangedUser = ChangedUser => DatabaseUpdateFailed[Change] \/ OK
    type GetMostRecentlyUpdatedUser = () => DatabaseGetFailed \/ Option[ChangedUser]
    type Continue = ChangedUser => Boolean
    type FetchUserChanges = Option[ChangedUser] => Continue => Stream[Failed \/ ChangedUser]
    type ChangeJobRunner = Job => Stream[Failed \/ ChangedUser] => BatchResult
}
然后,它定义了许多扩展这些类型的类,例如

case class MyFetchUser(httpClient:HttpClient) extends FetchUser {
    override def apply(userSource: UserSource): FetchFailed \/ FetchResult[BasicUser] = {
        // business code
    }
}

case class MyPublishUser(fetchUser: FetchUser) extends PublishUser { ... }
最后,它将在某个入口将它们结合在一起

我对这些代码感到非常奇怪,因为我从未见过这种组织代码的方式。在Java背景中,我曾使用一些域类组织代码,并相互依赖:

case class UserFetcher(httpClient:HttpClient) {
    def fetch(...) = ???
}

case class PublishUser(userFetcher: UserFetcher) {
    def publish(...) = ???
}
你如何看待前一种方法?这样组织代码是一种好的设计吗

  • 您不需要像这里那样扩展这些函数类型:

    case class MyFetchUser(httpClient:HttpClient) extends FetchUser {
        override def apply(userSource: UserSource): FetchFailed \/ FetchResult[BasicUser] = {
            // business code
        }
    }
    
    这是因为在您给出的代码中,您只定义了
    apply
    。你也可以在需要的地方写:

    val myFetchUser: FetchUser = userSource => { /*business code */ }
    
    或者,您可以根据需要编写一个方法来创建正确的
    FetchUser

    def getFetchUser(name: String): FetchUser =
      userSource => { /*business code to return users matching String */ }
    
    只有当您为那些属于接口一部分的类提供了其他方法时,这种情况才会停止

  • 上面显示,如果只需要在本地使用
    myFetchUser
    ,则不需要为其创建全局类。如果
    myFetchUser
    需要其他函数,您可以类似地在本地定义它们

  • 这段代码使用的事实是,比如说,
    FetchUser
    本质上只是一个函数类型,返回一个
    \/
    。但是,如果这使人们能够使用可用于函数的一般概念,那么这是有意义的,否则就不清楚这有什么好的意义。在包对象中收集这些函数类型似乎没有什么意义


  • 你知道有没有开源的scala项目使用同样的方式来组织代码?什么是
    \/
    ???异常还是结果?这是scalaz中的
    类型。我不确定是否理解“但对于第一个解决方案,我确定有许多函数只能在某个类中使用。”我将其解析为“有许多函数只能在某个类中使用”,我猜你的意思是,许多函数只在某些类中需要,但在这个设计中并不隐藏。然而,我不明白怎么回事。@Blaisorblade,你的理解完全正确。我的意思是,如果我使用第二种解决方案,我只需要将一些依赖对象(不是函数)传递给一些类,如果可能的话,我可以在一个类中定义方法,而不暴露于“包”级别