Galapagos Tech Blog

株式会社ガラパゴスのメンバーによる技術ブログです。

PhoenixでElmしてみる

ご機嫌よう、奢侈文弱なガラパゴスのおとめです。

ガラパゴスでは社内勉強会というものが毎週開催されているのですが、その席で、Elm推しのナイスミドルで格好いい本柳さんが「PhoenixとElm連携できます(`・ω・´)キリッ」と発表されていましたので、今回はそれを試してみます。

この記事はPhoenix Framework 1.3-rc.1を対象にしています。1.2以前はディレクトリ構造などが異なります。また、PhoenixやElmのインストールなどは済んでいるものとします。

$ iex -v
Erlang/OTP 19 [erts-8.3] [source-d5c06c6] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

IEx 1.4.1
$ mix phx.new -v
Phoenix v1.3.0-rc.1
$ node -v
v6.10.3
$ elm -v
0.18.0

おさらい:Phoenix FrameworkとElm

もちろんこのblogをご覧の皆様には説明の必要などないと思われますが、Phoenix Frameworkは、RailsErlangのいいとこ取りをしようといったWebフレームワークで(1.3でRails Wayとは一線を画す素敵な方向に進んだことはこのblogでも触れました)、一方のElmは乱立するAltJSの戦いで瀕死のフロントエンドエンジニアにもたらされた希望です。

因みにですが、PhoenixのデフォルトではフロントエンドにはES6が使われます。

まとめ

いきなりですがまとめますと、Phoenix Frameworkで使用しているbrunchにElm対応の拡張を入れると、それだけでフロントエンドはElmで書くことができます。ほら、簡単でしょう?

アセット管理のおはなし

簡単でしょう? ……??

何を言っているのかちょっと意味がわかりませんね。Elm対応の拡張を入れる? なに言うてはりますのん?

その前にbrunchについてお話ししましょう。brunchはフロントエンドのビルドツールで、Phoenixではデフォルトのアセット管理ツールとして採用されています。アセットというのはJavascriptCSSなど、Viewのナカミのように動的に生成されるわけではないリソースのことですが、例えばLESSやSCSSで書いたものはCSSコンパイルしたり、Javascriptはサイズを圧縮したりしますね? そういったことを行うためのツールです。行うと言っても実際には意識することはほとんどなくて、アプリケーションの実行時にフレームワークがよしなにそういうことをしてくれるのですが。

さて、ここまでのおはなしで、諸兄諸姉にはもう、アセットというものは静的で、変更後一回だけ生成すればよく、しかしその一回は確実に実行されなければならない、ということがお分かりかと思います。

ところで、例えばES6ならイマドキのモダンなブラウザなら普通に使うことができます−−できるはずですね?−−が、Elmの場合はJavascriptに変換する必要も出てきます。トランスパイルですね。もちろん、Elmで書いて手動でトランスパイルして、出てきたJavascriptをbrunch(などのビルドツール)で使う、ということもできますが、面倒じゃなくてですか? もしも万が一手順書のようなものに従って何かするとしたら、トランスパイルしたり、そうして出力されたファイルを決まった場所にコピーしたり、といった「手順」はいかにも省略されそうじゃなくてですか? 人が行うなら、確実に実行される、という要求を満たせそうにありません。

そんなわけですので、ソースツリー上では普通にElmを書いて、トランスパイル以下略などは自動的によろしくして頂きたいですね。

elm-brunchを使ってみる

もちろんシェルスクリプトなどを書いてCIに組み込んでも良いのですが(それはそれでローカルデバッグの時面倒そうですが)、もっと朗報があります。Elmに対応したツールを使えば良いのです。はじめの方でお話ししたように、brunchにElm対応の拡張を入れましょう。

ここにelm-brunchがありんす。早速インストールしましょう。

$ npm install --save-dev elm-brunch

Phoenixプロジェクト上にElmのためのフォルダを作って関連するパッケージをインストールします。

$ mkdir assets/elm
$ cd assets/elm
$ elm package install elm-lang/html

せっかくelmディレクトリにいることですし、早速Elmを書いていきましょう(テキストに「ご機嫌よう世界」と出力するだけの簡単なものです)。この時、App.elmというファイル名にすると、トランスパイルして出力されたファイルが既存のapp.jsを上書きしてしまうので注意しましょう。今回はElmApp.elmという名前にしてみました。

module ElmApp exposing (..)

import Html exposing (Html, text)

main : Html msg
main =
  text "ご機嫌よう世界"

さて、もちろん現時点ではまだbrunchの設定などは行なっていませんので、このままではトランスパイルなどは自動では行われません。そこで、brunchの設定をします。

まず、assets/brunch-config.jsに、elm-brunchに関する設定を書きます。brunchが監視しているフォルダに"elm"を追加するのもお忘れなく。

elmBrunchの設定でelmFolderを指定する設定方法をよく見るのですが、それでは動かなかったので、ここではmainModulesでパスも指定しています。

...
  paths: {
    // Dependencies and current project directories to watch
    watched: ["static", "css", "js", "vendor", "elm"],
    // Where to compile files to
    public: "../priv/static"
  },

  // Configure your plugins
  plugins: {
    elmBrunch: {
      mainModules: ["elm/ElmApp.elm"],
      outputFolder: "../assets/js",
      makeParameters: ["--debug"]
    },
    babel: {
      // Do not use ES6 compiler in vendor code
      ignore: [/vendor/]
    }
  },
...

依存関係にもElm関連を指定する必要がありますので、assets/package.jsonに追加します。

...
  "devDependencies": {
    "babel-brunch": "6.0.6",
    "brunch": "2.10.7",
    "elm": "^0.18.0",
    "elm-brunch": "~0.8.0",
    "clean-css-brunch": "2.10.0",
    "css-brunch": "2.10.0",
    "uglify-js-brunch": "2.1.1"
  }
...

この段階で、一旦アセットパイプラインを動かして、Elmがトランスパイルされることを確認してみましょう。Phoenixでbrunchなアセットパイプラインを手動で実行するには以下のようにします。問題がなければ、このように完了メッセージが表示されるはずです。

$ node node_modules/brunch/bin/brunch build
14:56:35 - info: compiled 66 files into 2 files, copied 3 in 2.8 sec
Elm compile: elm/ElmApp.elm, to ../assets/js/elmapp.js

ところで先ほど書いたElmApp.elmはどこでどう動くのでしょう?

assets/brunch-config.jsに、outputFolder: "../assets/js"と書きました。これは、トランスパイルしたファイルの出力先の指定になります。アセットパイプラインを実行した際のコンソールログからもこのことはお分かりいただけますね? でも、このままではアプリケーションにロードされませんので、どこかに書く必要があります。

どこかに……?

ElmApp.elmは、単に「ご機嫌よう世界」と出力するだけなのを思い出してください。とりあえず適当な要素にでも出してみましょう。

というわけで、elmというIDの要素に出力してみます。assets/js/app.jsにElmAppを使います的な感じで、要素を書き換えるJavascriptを記述します。

...
import "phoenix_html"
import Elm from "./elmapp.js"
...
const elmElement = document.querySelector("#elm")
const elmApp = Elm.ElmApp.embed(elmElement)

次に、出力先の要素を適当に用意します。プロジェクトを作ったばかりの場合はインデックスページ(lib/YOUR_APP_NAME/web/templates/page/index.html.eex)しかありませんが、ここに追加してしまいましょう。

...
  <div id="elm"></div>
...

ではサーバを起動してみます。

$ mix phx.server

するとこのように、無事にご機嫌よう世界できました。

f:id:glpgsinc:20170517153955p:plain

elmapp.jsがありません、というようなエラーになる場合は、app.jsの該当の行を一旦コメントアウトしてアセットパイプラインを実行してください。これは、elmのトランスパイルがjsのコンパイルよりも後に行われることで発生します。一度トランスパイルしてしまえば大丈夫です。トランスパイルを必ず先に行うこともできると思うのですが、この記事ではそこまで突っ込みません

さいごに

突然ですがガラパゴスではサーバーサイドエンジニアを募集していますガラパゴスで実際にPhoenix Frameworkを採用したプロジェクトはまだ一つしかありませんが、推しを共有できる仲間が欲しいですのん、というわけで興味がおありの方は是非に。皆さまの応募お待ちしています。

では、ご機嫌よう。

この記事は業務の一環として業務時間中に書きました

SwiftでもElmのようなパーサーコンビネータを利用できるようにしてみました。

こんにちは、iOS開発チームの本柳です。

コードのモジュール化について色々考えながら開発していたのですが、 あれこれ考えているうちに勢い余ってgalapagos/HighOrderHelperというライブラリを作ってしまいました。

galapagos/HighOrderHelper ?

このライブラリはElmがコア機能として提供しているHigh-Order Helpersという機能をSwiftに移植したものです*1

galapagos/HighOrderHelperはパイプラインオペレーターや関数合成オペレーター、他に関数を変形するための関数などを含む関数プログラミングを行うための手助けとなるような機能を含んでいます。

このライブラリの機能の一部を紹介しましょう。

パイプラインオペレーター

F#から生まれ、OCamlOSS界に降臨し*2、Elixirに採用されたことでWEB界隈に認知され、その後WEBの力で急速に開発者に浸透していったオペレーター|>です。

Elmでは。Forward apply(|>)、Backward apply(<|)という二種類のパイプラインオペレータがありますが、galapagos/HighOrderHelperを利用すると、これらをSwiftで利用出来るようになります。

このパイプラインオペレーターを利用すると、下記のようにコードを書くことが出来るようになります。

// パイプラインオペレータを使う雰囲気だけご覧頂くためのコード(実際にこのコードが動作するわけではない)
let entity = JSONString
                 |> JSON.parse
                 |> Entity.map

このオペレーターを利用するためには参照透過な関数を用意する必要がありますので、積極的に利用していく結果的に副作用のある処理が少なくなっていくのが嬉しいですよね。

ヘルパ関数

galapagos/HighOrderHelperは提供するオペレーターを利用しやすくするために幾つかのヘルパ関数を用意しています。

ここではflip関数をご紹介します。

以下のような関数があるとします。

func A() -> String {
    return "a"
}

func B(_ a: Int, _ b: String) -> String {
    return "\(a)-\(b)"
}

この時、A() |> (B, 1)のようなコードを書きたいのですが、型が合わないために書くことが出来ません。

flip関数は関数の第一引数と第二引数を入れ替えた関数を返す関数です。

この関数を利用するとA() |> (flip(B), 1)というように書くことが出来るようになります。

このような感じで、ヘルパ関数を利用すると様々なケースにgalapagos/HighOrderHelperは提供するオペレーターを利用出来るようになります*3


galapagos/HighOrderHelperの機能をちょろっとご紹介しました。

詳細はGithubに記載してあるので、興味のある方は是非御覧ください。

さて、ガラパゴスでは勢い余ってライブラリを書いてしまうようなアクティブなエンジニアを募集しております。

ご興味お持ちの方は是非、弊社の採用ページを御覧ください。

www.glpgs.com

たくさんのご応募お待ちしております。


*1:この手のライブラリは何番煎じなんだ?という気もするのですが、Elm Likeという点においてはこいつが初版のはず

*2:実のところOCamlOSS界隈に降臨したかどうかは知りませんので、詳しい方は教えてください

*3:これが、パズルを解いているような感じで楽しいのです!

Cookpad Tech Kitchen #7 参加レポート〜ごちそうさまでした〜

こんにちは!テストチームとのの(@tono2587)です。
今回はクックパッドでおいしいごはんをごちそうになった話を書きます!!!

f:id:glpgsinc:20170424173845p:plain 嘘ですごちそうになりながらテスト現場のお話聞いた参加レポートです(おいしかったのは本当です)(めっちゃおいしかったです)

Cookpad Tech Kitchen #7 〜 理想の開発現場の「ふつう」のお話 〜

日時:2017/04/21 Fri. 19:30〜
場所:クックパッド株式会社 東京都渋谷区恵比寿4-20-3 恵比寿ガーデンプレイスタワー12F 登壇者:秋山 浩一さん、関 将俊さん、深谷 美和さん、松尾 和昭さん

cookpad.connpass.com

公開された資料

どんなお話が聞けたか

  • 「理想の開発現場」について
  • 理想の開発現場の「ふつう」について
      「うまくいったらどうなるの?」
      「なんでやるんだっけ?」
      「やりたくないの?」
      「えー」
  • そのチームで喜ばれるふるまいについて
  • 明日からできそう??

「理想の開発現場」について

タイトルの「理想の開発現場」とはどういうこと? という説明を秋山さんより

  • いままでは、テストと開発それぞれが独立しているほうが理想の形だと思っていた。
     ・技術、お金、管理それぞれが独立(IV&V)
  • しかし、2015年のみわさんの発表を聞いてもう一つの理想の形に気がついた
     ・「人はミスをする」ことが受け入れられていて、テストエンジニアと開発者が一緒に品質をよくしている形
     ・ダイバーシティインクルージョン…多様に集まって、お互いに認め合うこと
  • ソフトウェアの世界では、このようにひとつの世界で情報交換したほうがよいのではないか
     ◯よいところ
     ・何を言っても大丈夫なこと…認めあっている
     ・「人」ではなく「こと」に焦点が当たっていること…品質をよくするために人が動く
     ・見方が違うことが大事
     ・共同作業と当事者意識…一緒にひとつになってやっている

解説にはカンペがあったそうです笑

今回はそんな理想の形=みわさんのチームについてのお話でした。

これから話す内容について関さんより

  • これまでは、できあがったチームの事例を報告していた
     →それを聞いたからといってできるとは限らない!
  • 今回は、チームになっていく過程を報告します
     →問題解決の最中に起こる話からよいチームができていっているのではないか?
     フレーズ→ふるまい→価値観 のようにチームの価値観ができていくのでは。
  • こんな名言があります
    『生きている花をつくろうとすれば、ピンセットで細胞を一つ一つ物理的に組み立てるのではなく、種から育てるであろう。』
         ーーークリストファー・アレクサンダー『時を越えた建設の道』

(種の撒きかたを教えてくれるんですね?!)

理想の開発現場の「ふつう」について

よくつかわれているフレーズがあります。

「うまくいったらどうなるの?」

  • このフレーズのよいところ
     ゴールがわかる、確かめる方法がわかる、ゴールまでのステップがわかる、うまく迷える
    →これをきっかけにしてぼんやりしていることをはっきりさせられる

  • 例:◯◯の調査をします と言われたとき
    ほんとうにやりたいことのための調査なので、そのやることがみんなにわかるようになったらやめようか、とか決めることができる
    Q:調査の区切りは先行投資だと難しいのでは?
    →時間で切る ことが多い

「なんでやるんだっけ?」

  • このフレーズのよいところ
     ・ゴールの意味がわかる、やりすぎを抑えられる
    →その作業自体の意味を考えたり、その作業でつくろうとしてるものがわかってくる。「不足」は不具合とかで見つけやすいが、やりすぎはわかりづらいのでこのフレーズが役に立つ
    →不安に思っていることはバラすほうがよい。
    →1人よりn人で考えたほうがみつけやすい

  • 例:だれかが迷っているとき、話し合いが急に静かになったとき、結論が出ないとき、困っているように見えるとき、熱中し(すぎ)ているとき

Q:Cookpadではどうですか?
人に干渉するのはけっこうやります。進捗の確認とか
Slackとか直接でちょくちょくコミュニケーションとる
できるならやったほうがいい

「やりたくないの?」

  • このフレーズのよいところ
     ・1人だけがやりたくない、状態にならなくできる(ヤダ共有)
     ・やる気がないからやらない、とはならなくできる
     ・上手い人がかわりにやってくれたりする
    →「嫌なこと」をなくしていくことができる。モチベートするのではなく、嫌なことを認めてなくしたり、みんなのものにすることができる

  • 例:問題を前に言葉が出ないとき、言い訳をする人が出てきたとき

Q:微妙なところに気づいてあげる工夫は?その人が「やりたくなさそう」という判断基準は?
→顔をみるから気づく。その人の話を聞いていてゴールが明確じゃないときや、明らかに目をそらすとかのとき

「えー」

  • このフレーズのよいところ
     ・瞬時に違和感を伝えることができる
    →「えー」って言うと課題かも、って気付ける
     ・それが何かをみんなが一斉に考えて話し始める
    →たいていの場合課題(問題)がみつかる

  • 例:「あれ?」とかも同じ使い方。ちょっと待って、というかわりだったりする
    →理不尽なこと言われたときには有効

◆スビードを大切にしているチームだからつかいます
 ・「早く」みんなに伝えたい
 ・自分で納得できるまで確かめてから伝えたい

Q:途中から入ったひとにも「えー」が悪く伝わらないコツは?(「えー」って普通否定的なイメージ)
→次の言葉までセットにしてる 「えー◯◯?」
Q:新しい人が「えー」の意味をわかるきっかけは?
→みんなのいる場で言われる/使われることが多いから慣れていく
→自分のことと同じようにその場にいる人が考え始める

そのチームで喜ばれるふるまいについて

  • 変だな?と思ったときにすぐ誰かにいう
  • バグかな?と思ったときにすぐ誰かに言う
     →スピード重視だから。バグじゃなくても怒られたりしない(いままではバグかな?くらいでは報告しなかったし、違うかもしれないことに開発者の工数をとることはよくないことだと思っていたけどいまはそうではない)
  • 仕様がわからないときだれかにきく
     →誰かが知ってるのに、わからない人が調べている時間のほうがもったいない
  • テストのやり方がわからないときだれかにきく
  • テストを思いついたとき、やる前にだれかにいう
     →ここバグ出そうだな〜って思ったときにすぐ言っちゃう
     →実装する前でも言う。考慮できてなかったところに気づいたりする
     →知っているなら先に言いなさいよ、というスタンス。いいものをつくりたいはずなのに、自分のやりたいことが優先されるべきではない。バグでそう→実装で確認は自分がやりたいことじゃないだろうか。
     「わざわざできあがってから言うのは、きみは意地悪だ」
  • こうしたフレーズを繰り返し言っていき、だんだんチームの価値観をつくっていく

明日からできそう?

15年も一緒にやっている長いチームだから、チームとしてできあがっているからこそ成り立つものなのでは?
と思われるかもしれないが、このチームに限った例ではないよ
→ラムダノートという会社と1ヶ月くらい一緒に仕事したらそっくりなチームができたから

まとめ

・テストエンジニアと開発者が一緒につくっていくのもチームの理想の形
・理想の開発現場ではなにが普通なのか
 ・よくつかわれているフレーズがあり、価値観をつくっていってると思う
 ・みんなが当事者
 ・新しく入ったメンバーにも繰り返し言っていき、慣れてもらう

Twitter公式タグも盛り上がってました!

感想

話を聞いて、わたしがすぐできそうなことについて考えました。

  • モヤモヤはすぐに伝える
     なんでも全部すぐ言うのがよいとはまだ思いませんが、悩みすぎたり、考えすぎて止まらないようにしようと思いました。まずは時間で区切ってみます。
  • 朝会をちょっと変えてみる
     いままで:進捗をざっくり確認→今日はAさんここ、Bさんこっちからお願いします。→他は何か(共有事項)ありますか?(終)
     これから:最後の(共有事項)の聞き方を具体的にしてみる。不具合でたかとか、仕様不明点ないかとか…
     →心当たりを見つけやすいし、細かいことも共有しやすくなりそう。
     →逆に無駄話みたいになっちゃうこともあるので、ほどほどでよいとアドバイスもらいました。
  • 「よいものをつくるため」を忘れない
     喜ぶのが自分ひとりだけ、にならないこと。
     →ちょっと面倒だな…ということも、「これを使う何万もの人がこっちのほうがうれしい」と言われたらがんばれる

ほか
ごはん全部おいしかったです。豚肉の角煮みたいなやつとか、生姜焼きとか、炊き込みご飯とか…でも食べながら聞くのは上手くできなかったです…もっと食べたかった…笑
ごちそうさまでした…
…というわけで、おいしいごはんとおいしいお話をいただいた1日でした。今よりもっとよくなるためにすぐできそうなことも見つかったので、早速やってみようと思います。

くいしんぼうとののが明日からもがんばる会社はこちら〜(エンジニア募集中)

www.glpgs.com