―屋外貯蔵タンク付属設備の紹介― 屋外タンク貯蔵 …...―屋外貯蔵タンク付属設備の紹介― 屋外タンク貯蔵所の泡消火設備 深田工業株式会社
SI屋のためのF# ~DSL編~
-
Upload
bleis-tift -
Category
Technology
-
view
3.138 -
download
1
description
Transcript of SI屋のためのF# ~DSL編~
SI屋のためのF#
~DSL編~
bleis-tift
October 25, 2014
自己紹介
id:bleis-tift / @bleis
なごやではたらくゆるふわ F#er
仕事で F#使ってます!
今日話すこと
ざっくり:SI屋がF#をどのように業務に使っているかの一例
もうちょい詳しく:内部DSLとか外部DSLを F#で作って 1ソースである特定のコードと仕様書を出力してハッピー!
背景
弊社について・・・
従業員数 20人以下の小さい会社
とがった技術者が多いかも
ちょっと特殊なWebサービスを構築したりしている
.
.
クライアント
↑特殊HTTP(S)主に XML
サーバ
SI屋で働くプログラマの敵
SI屋で働くプログラマの敵
今日のテーマは「Excel方眼紙をいかにして倒すか」です!
Excel方眼紙の何が駄目か
印字切れとの闘い
ヘッダ、フッタ、目次を手動更新
自動化しにくい
そういうフォーマットを決めるのは結構だが、俺に使わせるな!
Excel方眼紙を触らないためには
えらい人になって、Excel方眼紙を禁止する
Excel方眼紙のない世界に移住する
Excel方眼紙は最終出力として割り切り、自動生成
Excel方眼紙を触らないためには
生成結果は完全でなければならない微調整があっては駄目。人手が必要な部分があると、生成物のみを編集されるようになって死ぬ。
他者をコントロールできなければならない生成物を編集することは固く禁止しないと死ぬ。
他社もコントロールできなければならない生成物を以下略。まずは自分たちで完結するドキュメントから始めるのが吉。
Excel方眼紙を触らないためには(2)
Excel方眼紙だけではなく、プログラムに必要なものも生成する
ツールロックインさせてしまう
可能であれば開発プロセスに組み込んでしまう
内部DSLの例:ログ一覧
システムが出力するログをまとめたドキュメントが必要ログには.NET標準の仕組み (トレース)を拡張したものを使用
ログ定義 XMLから、カスタムツールでログ出力用のコードを出力
ドキュメントとログ定義XMLを 1ソースから生成できると便利!.
.
DSLドキュメント
ログ定義 XML
DSLの作り方
あくまで一例
1. 必要な情報の洗い出し
2. 型を作る
3. 値を作る方法を考える
4. 値を作る方法を提供する
5. 出力部分を提供する
余談:JSONの上に独自のルールを課してDSLだぜ!は、よほど単純なものでないとつらいのでは?
DSLの作り方:必要な情報の洗い出し
まずは、DSLがどんな情報を含まなければならないかを洗い出す
ドキュメントが必要としている情報IDログレベルログ本文 (概要と詳細)パラメータ (名前、説明)ログの説明 (自明なログには書かない)
ログ定義XMLが必要としている情報IDログ出力用メソッド名ログレベルログ本文 (概要と詳細)パラメータ (名前、型)
DSLの作り方:型を作る
F#なのでレコードとか判別共用体とか使う.ログ定義用DSLの型の例..
.
type Level =
Critical | Error | Warning | Information | Verbose
type Parameter = string * Type * string option
type Log = {
Id: int
Level: Level
Name: string
Summary: string
Format: string
Parameters: Parameter list
Description: string option
}
DSLの作り方:値を作る方法を考える
内部DSLでいいか外部DSLにするかの分水嶺
関数等を組み合わせた良い感じの書き方で値が作れる→内部DSL値をDSLに戻したい→外部DSL
内部DSLは F#の力がそのまま使えてしまう→完全に元に戻すことは不可能 (条件分岐、ループ、関数・・・)
今回は内部DSLを採用
DSLの作り方:値を作る方法を提供する
こんな感じで書けるように関数等を定義.ログ定義用内部DSLの例 (実際はこれのリスト)..
.
define 1 Error InvalidHeader
|> parameters
[ "header" =>
typeof<string> |> withComment "不正なヘッダ"
"value" => typeof<string> |> withComment "値" ]
|> summary "ヘッダ不正"
|> format "ヘッダ{header}(値:{value})が不正です。"
|> withComment "ヘッダが不正な場合に出力されます。"
ちなみに、この書き方を実現するために FsControlを使ってます
DSLの作り方:出力部分を提供する
出力先に必要な情報はすべて値に含んでいるので、あとはこれを元にごにょればOK
Excelの出力にはEPPlusを使用COMと違って Excel不要NPOIと違って生成したファイルが壊れにくいライセンス (LGPL)と xlsには対応していない点に注意
XMLは無難にXDocumentXMLの構築が C#よりはるかに楽なの、もっと言っていくべきかも?
ここに完成図を貼る
外部DSLの例:テーブル仕様書
テーブルに対するドキュメントが必要
CREATE TABLE文では情報が足りないドキュメントからCREATE TABLEを生成?
どうせプログラマが書くのなら、Excelを入力にする意味はない
DSLで書いた定義からドキュメントとCREATETABLE文を吐けばいい!
外部DSLを選んだ理由
今後、テーブル変更DSLを作りたい
今回のDSL+テーブル変更DSLで、今回のDSLを生成し直したい
内部DSLとして、いい表現が思い浮かばなかったというのもある
内部DSLとの違い
再掲:DSLの作り方の一例
1. 必要な情報の洗い出し
2. 型を作る
3. 値を作る方法を考える
4. 値を作る方法を提供する
5. 出力部分を提供する
3で外部DSLの文法を考え、4でそれを実装する気に入らなければ 3に戻ってやり直す
文法・機能
文法は好きなようにあまり機能を詰め込まない
汎用的にしすぎると、ドメイン特化とはいったい何だったのか、となる
パーサジェネレータとパーサコンビネータ
パーサコンビネータは単なるライブラリなので、手軽に始めれる
パーサジェネレータはコードを生成するので、面倒
とりあえずはパーサコンビネータでいいのではないだろうか
F#のパーサコンビネータ
FParsec
XParsec(ない)
ParsecClone
FsAttoparsec
FParsecが機能的にも速度的にも無難
デモ
まとめ
Excel方眼紙はプログラマが触るべきものではない
Excel方眼紙の生成をプロセスに組み込んでしまう
DSLどんどん作って、Excel書く仕事なくしていこう!
おわり