Your SlideShare is downloading. ×
WebサービスをScala+LiftでUI Firstに作る
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

WebサービスをScala+LiftでUI Firstに作る

9,681
views

Published on

Published in: Technology

0 Comments
10 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
9,681
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
0
Comments
0
Likes
10
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. WebサービスをScala+LiftでUI Firstに作る~ LiftのView-Firstを生かしたワークフローでアプリ開発 ~ Fungoing LLC / Satoshi Miyauchi Twitter : @nothijiri
  • 2. Overview Satoshi Miyauchi @nohijiri フリーのプランナ/Webディレクタ デザイン、マークアップ、プログラム、サーバ、ネットワークも一応やる 2010年10月にPHPからScalaに移行 自身でもWebサービスを企画開発しておりプラットフォームに Scala+Lift+PostgreSQL+MongoDBを選択 サービス開発の経験をもとに、LiftのView-Firstについて紹介 Page : 1
  • 3. Liftの開発StyleはView-First MVCも対応するっぽいけどLift wikiの Overview1つ目がView-Firstだしきっとメインhttp://oss.infoscience.co.jp/scala/www.assembla.com/wiki/show/liftweb/View_First.htmlなどを参考に Page : 2
  • 4. View-Firstの仕組み BootStrap Snippet Model View Snippet Model Snippet View Model Snippet BootStrapの指示に従い、まずViewが呼び出される。 Viewは0~nのSnippetを利用し画面を出力する。 Snippetは適宜Modelを利用しデータへアクセスする Page : 3
  • 5. どういう時にいいの? Page : 4
  • 6. ・エンドユーザー向けで、・UI、マークアップが先行して、・一画面に要素が多いサービス こういうものに効果を発揮しそう Page : 5
  • 7. 作ったサービス 物語エンターテイメント「Catary」 エンドユーザー向けコミュニケーション/CGMのサービス。 画面内の要素が非常に多く、ほぼ全ての機能は エンドユーザーが直接触れる部分になる。 Page : 6
  • 8. 課題・エンドユーザー向けサービスではView(UI)の仕様が 凍結することはほぼ無い。継続的に検証、改善、調整が必要・その際、当然Markupの修正や画面遷移の修正が入る。 そのためMarkup→Viewの反映コストが大きいと ボディブローのようにきいてくる・PC向けUIを提供しているととにかく画面内に部品が多く 細かいコストがさらに響いてくる Scala+LiftならMarkupとViewをかなりシームレスに 行き来できサービス開発を効率化できる Page : 7
  • 9. Wolkflow 1. サービスの企画 2. サービス機能の設計 View-First 3. 画面遷移の設計 4. 画面デザイン/HTML Markup 5. Boot.ScalaでSiteMapを適用 な 6. Lift:Surroundの適用 領 7. Lift:Embedの適用 域 8. ViewをSiteMapの定義にしたがって配置 9. Model、Documentの実装 10.Snippetの実装 11.完成!? Page : 8
  • 10. 1.サービス企画 まずは企画が必要ですね。 どんなサービスか、ユーザーにどんな価値を提供するか、 そういった部分をイメージ化してドキュメントにしましょう。 PowerPoint、Keynoteなどお好きなソフトウェアでどうぞ。 Page : 9
  • 11. 2.サービス機能の設計 続いて、サービスで提供する機能をまとめていきましょう。 これも図解レベルでわかればいいと思います。 こちらもPowerPoint、Keynoteなどお好きなソフトウェアでどうぞ。 このあたりまで来るとVisio、Cacooなんかもいいかと思います。 Page : 10
  • 12. 3.画面遷移の設計 企画と機能ができたら、ユーザーへ提供する画面を列挙して 繋がりを図に入れ込んでいきましょう。 Intro Image AddSign/Signup Welcome Other User Image Edit Image Search Image Delete Image List Home Theme Episode… Episode… Edit Icon Edit Icon Edit Bg Dictionary… Dictionary… Edit Bg Setting Character… Character… Edit Data Page : 11
  • 13. 4.画面デザイン/HTML Markup ここまでくれば必要なUIがわかるので、 デザインしてDreamWeaverなりマーク アップツールなりでHTMLを作ります。 ここで重要なのは「仮画面ではなく実 際にユーザーに見られてOKなところま で作り込む」という点です。 デザイナに依頼するためにワイヤーフ レームを作るというステップが入る可 能性もありますが、この工程の中で処 理します。 また、この時点で必要なフォームは全 て作り、項目名や入力規則も全てユー ザーが見てわかるレベルまで記載しま す。フォーム以外の挙動はヘルプや FAQのページに書いておきます。 Page : 12
  • 14. 4.画面デザイン/HTML Markup とても重要です UI Firstな開発では 「ユーザーが見ている記述=優先される仕様」 と考えUIに合わせて実装をしていきます ※改修時もロジックより先にUIを直します Page : 13
  • 15. まだ一行もScalaのコードを書いてないが大丈夫か? Page : 14
  • 16. 5.Boot.scalaでSiteMapを適用 def sitemap() = SiteMap( //Base functions Menu(Loc("Home", List("index"), "Home", CtUser.notLoggedIn)) :: Menu(Loc("Signup", List("signup"), "ユーザ登録", CtUser.notLoggedIn)) :: Menu(Loc("Register", List("register"), "ユーザ認証" )) :: Menu(Loc("Agreement", List("agreement"), "利用規約")) :: Menu(Loc("Privacy", List("privacy"), "プライバシーポリシー")) :: Menu(Loc("About us", List("aboutus"), "運営" )) :: Menu(Loc("Guide", List("guide"), "利用ガイド" )) :: Menu(Loc("Faq", List("faq"), "FAQ" )) :: Menu(Loc("Guideline", List("guideline"), "ガイドライン")) :: Menu(Loc("Inquiry", List("inquiry"), "お問い合わせ")) :: Menu(Loc("Inquiry Finish", List("inquiry_finish"), "お問い合わせ")) :: Menu(Loc("Message", List("message"), "メッセージ")) :: Menu(Loc("Reconfirm", List("reconfirm"), "認証メール再送",CtUser.reconfirm)) :: Menu(Loc("Signout", List("signout"), "サインアウト", CtUser.logoutWithRedirect )) :: Menu(Loc("Password reset", List("passreset"), "パスワード再設定", CtUser.notLoggedIn )) :: Menu(Loc("Password reset finish", List("passreset_finish"), "パスワード再設定", CtUser.notLoggedIn )) :: //Mypage functions Menu(Loc("Welcome", List("welcome"), "ようこそCataryへ", CtUser.loginFirst )) :: Menu(Loc("Mypage", List("h","index"), "マイページ", CtUser.loginFirst )) :: ~~省略~~ } 面白みも何もないコード。RewriteRuleが必要ならあわせてBoot.scalaへ Page : 15
  • 17. 6.Lift:Surrroundの適用 Surround ヘッダ、フッタ領域をSurround としてtemplates-hiddenに分離 webapp/xxxx.html <lift:surround with="default" at="content"> <div id="container"> <!-- Contents Body --> </div> </lift:surround> Contents webapp/templates-hidden/default.html <html> <head> <title><lift:Menu.title /></title> </head> <body> <lift:bind name="content" /> </body> </html> Page : 16
  • 18. 7.Lift:Embedの適用 Embed 何度も表示する部品をEmbed Embed としてtemplates-hiddenに分離 webapp/xxxx.html <lift:embed what=“left_mypage" /> webapp/templates-hidden/left_mypage.html Embed <div> Embed <div>Left Menu 1</div> <div>Left Menu 2</div> <div>Left Menu 3</div> <div>Left Menu 4</div> <div>Left Menu 5</div> </div> Page : 17
  • 19. 8.ViewをSiteMapの定義にしたがって配置 Surround Embed EmbedSiteMap View View View View View Embed View View View Embed 動きはしないが、ユーザーが触れる画面は 全て静的なモックアップとして実装。 アドレスを直に叩くとまずは表示される段階。 Page : 18
  • 20. ※Viewの更新は再コンパイル不要 LiftはViewからロジックが完全に切り離されて いるので、Viewの更新はサーバを起動したま ま行うことができます。 UIは文言やレイアウトなど細かい調整が入るこ とが多いのでこれは大きなメリットです。 Viewの配置作業もBoot.scalaが変わる時以外 は起動したまま作業ができます。 Page : 19
  • 21. ※この時点でまだほとんどScalaのコードに触っていません そろそろモデルでも作るか・・・ Page : 20
  • 22. 9.Model,Documentの実装 <net.liftweb.mapper> KeyedMapper KeyedMetaMapper User / Theme Contents 入力のフォームと提供するUIをもとに、 各種モデルを実装していく。 <net.liftweb.mongodb> モデルから画面を作るのではなく、 MongoDocument 画面通りに動くようモデルを作る。 MongoDocumentMeta これもある種のView-First? Page : 21
  • 23. 10.Snippetの実装 Snippetはとてもたくさん。 1つ1つクラスを作るわけには Snippet Snippet いかないのである程度の単位で まとめていきます。 Snippet Snippet 今のところ「同じModelを使うも Snippet Snippet Snippet Snippet のは1つに」で実装しています。 Snippet Snippet ※Snippetクラスのインスタンスは 1Requestに対して1つだけ生成 Snippet されるようです。なのでコンスト Snippet Snippet ラクタでfindしておけば使い回し ができます ここの粒度はまだ試行錯誤の最中 Page : 22
  • 24. Login Form Snippet 例として、「ログイン時には表示され ないログインフォーム」を実装。 Page : 23
  • 25. 注意点 LiftのViewは一切ロジックを含む事ができない。 なので条件分岐もできない・・・ Page : 24
  • 26. じゃあどうするのか? Page : 25
  • 27. Snippet自身が表示すべきか判断する Page : 26
  • 28. <lift:Signin:form > <div class="contentsBox"> View <div class="subject">ログイン</div> <div id="err_signin_global" class="error"/> フォーム領域を <table width="100%" border="0"> Lift:Signin:formという <tr> Snippetタグで囲む。 <td nowrap="nowrap">CataryID</td> Bindするべきアイテムは <td><f:login_cataryId /> <div id="err_signin_cataryId" class="error"/> <f:xxxxxx />のような形に。 </td> </tr> ここで囲った範囲を <tr> 「ログイン時だけ表示する」 <td nowrap="nowrap">パスワード</td> <td><f:login_password /> 領域にしたい <a href="/passreset"><br/>パスワードをお忘れの方</a> <div id="err_signin_password" class="error"/> </td> </tr> <tr> <td colspan="2" align="center"><f:login_save />一週間ログインを保持する</td> </tr> <tr> <td colspan="2" align="center"><f:login_submit /></td> </tr> </table> </div></lift:Signin:form> Page : 27
  • 29. // 1def form(xhtml: Group): NodeSeq = { Snippet // 2 CtUser.currentCataryUser match { // 3 case Full(user) => NodeSeq.Empty // ログイン済みなら表示しない // 4 case _ => SHtml.ajaxForm( bind( "f", xhtml, "login_cataryId" -> SHtml.text( cataryId , cataryId = _ , ("id","login_cataryId" ),("class","required" ) ) , "login_password" -> SHtml.password( "" , password = _ , ("class","required")) , "login_save" -> SHtml.checkbox( false , save = _ , ("class","required")) , "login_submit" -> (SHtml.hidden(doSignin _) ++ <input type="submit" value="ログイン"/>) ) ) } } 1) Lift:Signin:formで呼ばれる関数。View側で囲った内部がxhtml :Groupで渡される 2) ログイン状態のチェックをするための関数。戻り値にモデルが入っているとログインしている 3) Case Full(user)の場合ログインしているので、このフォームを表示したくない。 そこでNodeSeq.Emptyを返してしまう。これによって<lift:Signin:form>で囲った部分が 空になるので表示されなくなる。 4) ログインしていなければ値のバインドを行う Page : 28
  • 30. イメージ図 innerHTML lift:Signin:form Empty ログイン時 Bind済HTML 未ログイン Page : 29
  • 31. 11.完成!? あとはひたすらModelとSnippetを実装すれば サービスが完成するはずです。おめでとう! でも俺達の戦いはまだ始まったばかりだぜ・・・ Page : 30
  • 32. まとめLiftのView-Firstは実装において「Viewを先に呼び出す」「Viewを先に作る」といった意味もあるもののそれ以上に「ViewはMarkup工程とのInterface」という面を強く意識していると感じます。それによってUIの調整、改善とアプリケーションの実装がシームレスに近い状態で行えるようになります。 View-First =「UIが先に出来ている=UI First」なWorkflowに適した仕組み。なのでそうでないアプリケーションに とってはHeavyなだけのFrameworkになる可能性もあり Page : 31
  • 33. Wolkflowの再確認 サ サ 1. サービスの企画 ー ー ビ ビ 2. サービス機能の設計 ス ・ ス ・ UI UI 3. 画面遷移の設計 改 デ 善 ザ 4. 画面デザイン/HTML Markup 計 イ 画 ン 5. Boot.ScalaでSiteMapを適用 6. Lift:Surroundの適用 UI-First 7. Lift:Embedの適用 8. ViewをSiteMapの定義にしたがって配置 Application 9. Model、Documentの実装 10.Snippetの実装 11.完成!? Page : 32
  • 34. Lift=Service Design & Markupと シームレスなScala Web Framework ご利用は計画的に型安全で非同期処理ができてコード記述量も少ないScala+LiftはWebサービス開発にお勧め。 JVMで動くScalaはLLに比べパフォーマンス面でも有利。 Page : 33

×