Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Backlogが一体いつから Scalaを遣っていないと 錯覚していた? / Scala Fukuoka 2017 Backlog is using Scala

Backlogが一体いつから Scalaを遣っていないと 錯覚していた? / Scala Fukuoka 2017 Backlog is using Scala

Scala福岡2017 にて、ヌーラボの谷本、松本がお話しした資料です。プロジェクト管理ツールBacklogにおけるScala + Play Frameworkへの移行プロジェクト(通称Play化)について。

More Decks by 株式会社ヌーラボ

Other Decks in Technology

Transcript

  1. Ҡߦํ๏ ϘπҊ +BWB͔Βݺͼग़͞ΕΔϝιουΛগͣͭ͠4DBMBʹҠ২ ˎˎˎαʔϏε +BWB *TTVFαʔϏε +BWB ˎˎˎΞΫγϣϯ +BWB ՝୊ฤूΞΫγϣϯ

    +BWB ˎˎˎΞΫγϣϯ +BWB *TTVFαʔϏε 4DBMB ˎˎˎαʔϏε +BWB ˎˎˎαʔϏε +BWB 3%#Πϯϑϥ૚
  2. ࠾༻ͨ͠Ҡߦํ๏ ػೳ୯ҐΛ࡞Γ੾ͬͯɺ/HJOYͰΞΫηεΛ 1MBZ൛ʹৼΓ෼͚Δ *TTVFαʔϏε +BWB ՝୊ฤूΞΫγϣϯ +BWB ˎˎˎαʔϏε +BWB 3%#Πϯϑϥ૚

    /HJOY *TTVFαʔϏε 4DBMB ՝୊ฤूΞΫγϣϯ 4DBMB ˎˎˎαʔϏε 4DBMB ˎˎˎΞΫγϣϯ +BWB 5PNDBU൛ 1MBZ൛
  3. ࠾༻ͨ͠Ҡߦํ๏ *TTVFαʔϏε +BWB ՝୊ฤूΞΫγϣϯ +BWB ˎˎˎαʔϏε +BWB 3%#Πϯϑϥ૚ /HJOY *TTVFαʔϏε

    4DBMB ՝୊ฤूΞΫγϣϯ 4DBMB ˎˎˎαʔϏε 4DBMB ˎˎˎΞΫγϣϯ +BWB ͨͩ͠ɺ4FTTJPOΛڞ༗͢Δ࢓૊Έ͕ඞཁ ˠ3FEJTΛ࢖࣮ͬͯ૷ 5PNDBU൛ 1MBZ൛
  4. ࣮ࡍͷ͸·ΓͲ͜Ζ ଞͷݴޠͱͷࡉ͔͍จ๏ͷҧ͍ [T] ⟷ <T> => ⟷ -> Option ⟷

    Optional val & var ⟷ let & var JNQMJDJUDMBTT forจ
  5. JNQMJDJUDMBTT implicit class Foo(val a: String) { def foo: Int

    = 3 * a.toInt } ”9”.foo extension String { var foo: Int { return 3 * Int(self)! } } ”9”.foo struct Foo { Foo(const char* a) : a(a) {} int foo() { return 3 * atoi(a); } private: const char* a; }; Foo a = ”33"; a.foo(); $
  6. GPSจϜζΧγΠωʜ forDPNQSFIFOTJPO forMPPQ for { i <- 1 until n

    j <- 1 until i if isPrime(i + j) } yield (i, j)
  7. GPSDPNQSFIFOTJPO IUUQTTQFBLFSEFDLDPNEBJLTZTDBMBGVLVPLB TMJEF ˠ0QUJPOܕΛ࢖͍͜ͳͯ͠ॳ৺ऀ͔Βதڃऀ΁ 4DBMB෱Ԭ for(p <- e) yield e′

    e.map{case p => e′ } — The Scala Language Specification Version 2.9 / 6.19 For Comprehensions and For Loops for(p <- e; p′ <- e′;…) yield e′′ e.flatMap{ case p => for(p′ <- e′;…) yield e′′ } p <- e if g p <- e.withFilter((x1 ,…,xn ) => g)
  8. GPSDPNQSFIFOTJPO&YBNQMF for { i <- 1 until n j <-

    1 until i if isPrime(i + j) } yield (i, j) (1 until n) .flatMap { case i => for (j <- 1 until i if isPrime(i + j)) yield (i, j) } for(p <- e; p′ <- e′;…) yield e′′ e.flatMap{ case p => for(p′ <- e′;…) yield e′′ }
  9. (1 until n) .flatMap { case i => for (j

    <- 1 until i if isPrime(i + j)) yield (i, j) } p <- e if g p <- e.withFilter((x1 ,…,xn ) => g) (1 until n) .flatMap { case i => for (j <- (1 until i) .withFilter { j => isPrime(i + j) } ) yield (i, j) }
  10. (1 until n) .flatMap { case i => for (j

    <- (1 until i) .withFilter { j => isPrime(i + j) } ) yield (i, j) } for(p <- e) yield e′ e.map{case p => e′ } (1 until n) .flatMap { case i => (1 until i) .withFilter { j => isPrime(i + j) } .map { case j => (i, j) } }
  11. GPSDPNQSFIFOTJPO for { i <- 1 until n j <-

    1 until i if isPrime(i + j) } yield (i, j) (1 until n) .flatMap { case i => (1 until i) .withFilter { j => isPrime(i + j) } .map { case j => (i, j) } }
  12. GPSDPNQSFIFOTJPO ࠶ܝ IUUQTTQFBLFSEFDLDPNEBJLTZTDBMBGVLVPLB TMJEF for(p <- e) yield e′ e.map{case

    p => e′ } for(p <- e; p′ <- e′;…) yield e′′ e.flatMap{ case p => for(p′ <- e′;…) yield e′′ } p <- e if g p <- e.withFilter((x1 ,…,xn ) => g) ˠ0QUJPOܕΛ࢖͍͜ͳͯ͠ॳ৺ऀ͔Βதڃऀ΁ 4DBMB෱Ԭ — The Scala Language Specification Version 2.9 / 6.19 For Comprehensions and For Loops
  13. GPSDPNQSFIFOTJPOΛ࢖͏ -JTU 0QUJPO 'VUVSFͳͲ͸ flatMap map withFilterΛ࣮૷͍ͯ͠Δ for { :

    allProjects <- projectRepository.allRelatedProjectsOrderRecent(ctx.user.id) userCount <- userRepository.countUsersOfSpace(ctx.space.id) allProjectIds = allProjects.map(_.id) myPullRequests <- pullRequestRepository.allMyRequest(user.id, allProjectIds) activities <- projectActivityRepository.allGroupedActivitiesOfSpace (allProjectIds, activityTypes, pagination) : } yield DashboardContents( : allProjects = allProjects, userCount = userCount, myPullRequests = myPullRequests,
 activities = activities, : ) }
  14. ࢖͍ͬͯΔݴޠ΍ϥΠϒϥϦ ৽ ݱࡏ ݴޠ 4DBMB +BWB ΢Σϒ ϑϨʔϜϫʔΫ 1MBZ 8FCXPSL

    ςϯϓϨʔτ Τϯδϯ 5XJSM 7FMPDJUZ εΫϦϓτ )BYF )BYF
  15. ϧʔςΟϯάͷઃఆ xwork-Dashboard.xml <!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN" "http://www.opensymphony.com/xwork/xwork-1.0.dtd"> <xwork>

    <package name="dashboard" extends="default"> <default-interceptor-ref name=“defaultAuthComponentStack"/> <action name="Dashboard" class="jp.co.nulab.backlog.webwork.dashboard.Dashboard"> <result name="success" type="velocity"> <param name="location">/pages/dashboard/Dashboard.vm</param> </result> </action> </package> </xwork> GET /dashboard controllers.dashboard.DashboardController.viewDashboard() routes
  16. ΞΫγϣϯͷॻ͖͔͑ +BWBͷιʔεΛݟΔ for ifͳ΋ͷΛmap filterͱ͔ʹॻ ͖͔͑Δ def viewDashboard() = addToken

    { actions.userAction.async { implicit request => dashboardApplicationService.viewDashboard().map { contents => Ok(views.html.dashboard.dashboard(contents)) } } }
  17. $POUFOUT'BDUPSZ 3FQPTJUPSZܦ༝ͰσʔλΛऔΓग़͢ def create()(implicit ctx: UserContext, io: IOContext, ec: ExecutionContext):

    Future[DashboardContents] = { val user = ctx.user val activityTypes = ActivityType.availableActivities(user.role) val pagination = PaginationQuery(count = 10) for { : allProjects <- projectRepository.allRelatedProjectsOrderRecent(ctx.user.id) userCount <- userRepository.countUsersOfSpace(ctx.space.id) : } yield DashboardContents( : allProjects = allProjects, userCount = userCount, : ) }