なんでこがいに並外れた Typesafe ができたんか言うたら...
「よくシリコンバレーのスタートアップが作ってるようなうさんくさいビデオ」を Typesafe も作っていました。
Typesafe activator ダウンロードするか、めんどくさい...とサイトに行ったらいきなりビデオ見せられました。なかなかのユーザー体験をしました。
何か Typesafe Activator がすごい革新的っぽいことが伝わってきます。
他にもいろいろあります。
去年 Scala Conference に来てくれた Jamie さん
すごそう。
知らない人
すごそう。
Heiko さん
すごそう。
小田好先生
すごい(確信)
まとめ
- Typesafe すごそう
- 広島弁バージョンの登場が待たれる
composer で依存関係から特定のライブラリを除外する
Maven でのこれ
<dependencies> <dependency> <groupId>sample.ProjectA</groupId> <artifactId>Project-A</artifactId> <version>1.0</version> <scope>compile</scope> <exclusions> <exclusion> <!-- declare the exclusion here --> <groupId>sample.ProjectB</groupId> <artifactId>Project-B</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
composer にはこの依存関係から特定のライブラリを除外する機能はない。まだ実装していないのではなく方針として入れるつもりはなさそう。composer 開発者はこの機能を不要と思っているっぽい。
Exclude packages · Issue #1549 · composer/composer
理想をいうと微妙なところだけど、実際こういう問題はよく起きるからカバーするべきじゃないかな。composer 開発者はそういう経験ないのだろうか。PHP はフルスタックでそれのみで完結するようなフレームワークが多く、依存関係のツリーが深くならないから dependency hell が起きづらいと勝手に理解しておく。
一応、問題自体は除外したいモジュールを provide に指定すれば解決する。すでに提供されているのだから composer で持ってくる必要はないよね、ということ。
{ "require": { "foo": "1.0.0" }, "provide": { "bar": "*" } }
ただし、これだと問題は解決するものの意味としては全く違うから気持ち悪い。設定が json だからコメントも書けない。
まとめ
- composer で exclude したいときは provide を使う
- json で設定ファイルはきびしい
Python で Github Flavored Markdown をレンダリングする
前回の補足的な内容
python の Markdown ライブラリ自体は Github Flavored Markdown(GFM) をサポートしていない。
>>> import markdown >>> markdown.markdown("```python\ndef hello():\n print('hello')\n```") u"<p><code>python\ndef hello():\n print('hello')</code></p>"
python の Markdown ライブラリは拡張可能になっている。Markdown ライブラリの拡張ライブラリとして py-gfm を使うと gfm も扱えるようになる。
>>> import markdown >>> markdown.markdown("```python\ndef hello():\n print('hello')\n```", extensions=['gfm']) u'<pre class="highlight"><code class="language-python">def hello():\n print(\'hello\')</code></pre>'
さて、これで python であることを認識してくれたわけではあるけれど、シンタックスハイライトが効いていない。しかし、前回のエントリで MoinMoin に Markdown + py-gfm を組み込んだときはシンタックスハイライトがついていた。なんで?
これが気になっていろいろソース読んだりしたのだけど、答えは MoinMoin が pygments に依存しているから。pygments をインストールする前後で Markdown ライブラリは動きが変わる。
$ pip install pygments
>>> import markdown >>> markdown.markdown("```python\ndef hello():\n print('hello')\n```", extensions=['gfm']) u'<div class="highlight"><pre><span class="k">def</span> <span class="nf">hello</span><span class="p">():</span>\n <span class="k">print</span><span class="p">(</span><span class="s">'hello'</span><span class="p">)</span>\n</pre></div>' >
pygments をインストールしたらシンタックスハイライトがついた。
実は Markdown のほうにこんなコードがあった。
try: from pygments import highlight from pygments.lexers import get_lexer_by_name, guess_lexer, TextLexer from pygments.formatters import HtmlFormatter pygments = True except ImportError: pygments = False
https://github.com/waylan/Python-Markdown/blob/2.4-final/markdown/extensions/codehilite.py#L26-L32
わかりにくい挙動だと思う。markdown 関数の第二引数で extensions=['pygment']
みたいに渡すようにすればいいのに。せっかく拡張を作れるにしたのになぜこういう結合をさせるのか理解に苦しむ。
まあともあれ、Markdown + py-gfm + pygments で良い感じに GFM がレンダリングできるので使うと良いと思います。
MoinMoin で Markdown (Github Flavored Markdown) を使う
Markdown のメモ帳として kobito を使っていたんだけど Qiita に新規投稿ができないし、過去の投稿は編集できるけど取得はできない(つまり書いた記事がいつのまにか巻き戻されている)という状態に頻繁になるので使うのをやめました。なんなんだ、嫌がらせか。
いい加減あきれたので Qiita で書いていたもののうち、非公開にしているものを自分で管理している MoinMoin Wiki に記事を移行することにしました。公開しているものはこのブログに持ってくることにします。
さて、Qiita は Markdown で、MoinMoin は独自記法なので単純に考えると変換を書ける必要がある、と思いきや実はそんな必要はない。MoinMoin の parser はプラガブルになっていて自分で追加ができるので自分で Markdown パーサーを書いてやれば OK。 MoinMoin の公式の Wiki には Python の Markdown ライブラリを用いた方法が紹介されています。
しかし使ってみたら Qiita は Github Flavored Markdown (の亜種?)なのでコードブロックなどが Markdown ライブラリだとうまくレンダリングできませんでした。Github Flavored Markdown を扱えるライブラリを探していたら dart-lang の人たちがなぜか python で実装している py-gfm というのを教えてもらいました。
というわけでまず py-gfm をインストールします。
$ git clone https://github.com/dart-lang/py-gfm.git $ cd py-gfm $ python setup.py install
これで Markdown ライブラリで GFM 拡張が使えるようになるので、これを使って GFM プラグインを書きます。
# coding: utf-8 from markdown import markdown import json Dependencies = ['user'] class Parser: def __init__(self, raw, request, **kw): self.raw = raw self.request = request def format(self, formatter): output_html = markdown(self.raw, extensions=['gfm']) try: self.request.write(formatter.rawHTML(output_html)) except: self.request.write(formatter.escapedText(output_html))
すごくテキトーですが、これで GFM プラグインの完成です。簡単ですね。 text_markdown.py という名前で MoinMoin の plugin/parser ディレクトリに入れてあげましょう。
2015/02/10 追記
原因は追ってないけど最近 py-gfm が動作しなくなったので Markdown の extension を組み合わせてほぼ GFM っぽい感じにしてます。これだけで十分かも。なにか互換性壊れたのかなー。
# coding: utf-8 from markdown import markdown import json Dependencies = ['user'] class Parser: def __init__(self, raw, request, **kw): self.raw = raw self.request = request def format(self, formatter): output_html = markdown( self.raw, extensions=[ 'markdown.extensions.fenced_code', 'markdown.extensions.toc', 'markdown.extensions.codehilite', 'markdown.extensions.wikilinks', 'markdown.extensions.tables', 'markdown.extensions.def_list', 'markdown.extensions.nl2br', 'markdown.extensions.headerid', ]) try: self.request.write(formatter.rawHTML(output_html)) except: self.request.write(formatter.escapedText(output_html))
Markdown で Wiki エントリを追加する
markdown で Wiki にエントリを追加したいときは、書き出しを
#format text_markdown (空行)
にすれば Markdown として解釈してくれるようになります。
これでレンダリングが崩れることはなくなりましたが、CSS が当たっていません。 CSS はどこに追加するのが流儀なんでしょうか。よくわからないので本体の common.css に https://github.com/johnmdonahue/git_marked から拝借したのを突っ込んでしまいました。
.c{color:#998;font-style:italic;} .err{color:#a61717;background-color:#e3d2d2;} .k{font-weight:bold;} .o{font-weight:bold;} .cm{color:#998;font-style:italic;} .cp{color:#999;font-weight:bold;} .c1{color:#998;font-style:italic;} .cs{color:#999;font-weight:bold;font-style:italic;} .gd{color:#000;background-color:#fdd;} .gd .x{color:#000;background-color:#faa;} .ge{font-style:italic;} .gr{color:#a00;} .gh{color:#999;} .gi{color:#000;background-color:#dfd;} .gi .x{color:#000;background-color:#afa;} .go{color:#888;} .gp{color:#555;} .gs{font-weight:bold;} .gu{color:#800080;font-weight:bold;} .gt{color:#a00;} .kc{font-weight:bold;} .kd{font-weight:bold;} .kn{font-weight:bold;} .kp{font-weight:bold;} .kr{font-weight:bold;} .kt{color:#458;font-weight:bold;} .m{color:#099;} .s{color:#d14;} .na{color:#008080;} .nb{color:#0086B3;} .nc{color:#458;font-weight:bold;} .no{color:#008080;} .ni{color:#800080;} .ne{color:#900;font-weight:bold;} .nf{color:#900;font-weight:bold;} .nn{color:#555;} .nt{color:#000080;} .nv{color:#008080;} .ow{font-weight:bold;} .w{color:#bbb;} .mf{color:#099;} .mh{color:#099;} .mi{color:#099;} .mo{color:#099;} .sb{color:#d14;} .sc{color:#d14;} .sd{color:#d14;} .s2{color:#d14;} .se{color:#d14;} .sh{color:#d14;} .si{color:#d14;} .sx{color:#d14;} .sr{color:#009926;} .s1{color:#d14;} .ss{color:#990073;} .bp{color:#999;} .vc{color:#008080;} .vg{color:#008080;} .vi{color:#008080;} .il{color:#099;}
やっつけ感すごいですが、とりあえずこれで MoinMoin で Github Flavored Markdown が使えるようになりました。めでたし。
Scala.js について
Sendagaya.js(仮) で Scala.js について LT しました。
資料はこちら
http://tototoshi.github.io/slides/sendagaya-js-scala-js/
スライドは Scala.js を使って作ってみました。 ソースコードはこちら。
Scala.js は以前から知っていましたが、今回初めてさわりました。意外にサクサク書けました。ふむふむ、なんだちゃんと動くじゃないか、という感じ。
特にハマりどころはなかったし、Scala が JavaScript に変換されるということだけで十分面白いです。Scala 好きな方は一度試して見ると良いと思います。Scala の学習コストを考えたら Scala.js の学習コストはかなり低いです。そして何より心をざわつかせる何かがあります。
仕事で使うのはファイルサイズの都合上まだ無理ですが、バージョンが上がるごとに劇的な改善があるので、もしかしたら...という感じです。まあしばらくは良いおもちゃという感じで情報を追っておこうと思います。
チーム開発とクソコード
今までパッケージソフトとかWebサービスの開発をしてきた中で、ビジネス上の納期や要求を満たすためにひどいコードを書くっていうのは自分の経験ではあまりなかった気がします。なにかひどいバグがあって、とりあえずのパッチを当てて間に合わす、ということはたまにあるけれど。SIの世界は知りませんよ。
そもそもコードを汚くかけば納期に間に合うということもないし、ビジネス上の近道になるということもない。コードをきれいに書こうが汚く書こうが無理なものは無理。第一汚いコードを意図的に書くというのも意外に難しいということは、普段まあまあきれいなコードを書いている人ならわかってくれるんじゃないかと思います。
仕様変更に設計がついていけてなくておかしいとかならともかく、関数が1000行あるとか、newした瞬間全てが終わるとか、変数のスコープがびっくりするくらい広い、みたいなコードについてははビジネス上の要求ではなく、単にそのコードを書いた人が良いコードの書き方を知らなかったと思うしかありません。
ただそういったコードを書くのが下手くそな人たちが単にくそなのかというとそうでもなく、コードを書くのは下手だけどドメイン知識がすごいとか、DBやSQLなら異常に詳しいとか、その人が製品触るとなぜかバグが見つかるとか、あとはもう技術どうこう関係ないけどいちいち面白いとか、いろいろあります。
コードについて語ろうとすると当然コードを書くのが得意な人が強いので、クソコードを書く人はクソ、良いコードを書ける人間だけ雇え、となりがちだけど、コードを書くのが得意、コードにしか興味がない、みたいな人だけ集まるのも多様性に欠けて危険な感じがします。エンジニアとして、チームの一員としての価値の発揮の仕方は別にコードを書くことに限らないと思うので、コード書く力だけ偏重するのはやめたいです。
というわけでクソコードを解決するためには、ビジネス上の都合とか技術的負債がどうとか議論するのも良いですが、良いチーム作ってコードレビューで元気に殴り合いつつ、コード書くのが得意な人がリードしてコードの品質を底上げしていこうと考えるのがテンションあがって良いと思います。
さて git blame するか。
Scala 版 factory_girl みたいなのを作りました。
https://github.com/tototoshi/seedbed
Scala で factory_girl っぽいものを作りました。*1かなりお手軽な感じになっています。
依存ライブラリは特にありませんのでどのデータベースライブラリを使っていても大丈夫です。
動作は postgresql と h2 でのみ確認してますが、他のデータベースでも動くと思います。
とりあえず snapshot 版を sonatype にあげときました。
resolvers += "Sonatype snapshots" at "http://oss.sonatype.org/content/repositories/snapshots/" libraryDependencies += Seq( "com.github.tototoshi" %% "seedbed" % "0.1.0-SNAPSHOT" // and database driver )
使い方
以下のサンプルコードでなんとなくわかってもらえると思います。
define でテーブルごとのデフォルト値を定義、 create でデータを1件挿入、get/list はデータベースからレコードを取得するのに使用します。
データの取り扱いは割り切って Map[String, Any] でやってしまいます。基本的に型安全とかよりは手軽さを重視しています。動的言語な気分で使ってください。API は factory_girl より phactory (PHP の factory_girl 的なやつ) に近いです。
あくまでテスト用ライブラリなので、メインのプロダクトコードに入れるのはやめてください。
/* CREATE table beatles ( id serial primary key, first_name varchar(10) not null, middle_name varchar(10), last_name varchar(10) not null, birth_date date not null ); */ import seedbed._ // データベースの設定 trait TestDBConfiguration extends Configuration { val driver: String = "org.postgresql.Driver" val url: String = "jdbc:postgresql://localhost/seedbed_test" val user: String = "user" val password: String = "password" } // Seedbed クラスのインスタンスを生成 val s = new Seedbed with TestDBConfiguration // デフォルト値の設定 // めんどくさければ s.define("beatles") だけでも OK。DB のメタデータを見てよしなにしてくれます。 s.define("beatles", Map( "first_name" -> "John", "middle_name" -> "Winston", "last_name" -> "Lennon", "birth_date" -> new SimpleDateFormat("yyyy-MM-dd").parse("1940-10-09") )) // データベースへレコードを1件挿入 s.create("beatles") // デフォルト値を一部書き換えて挿入 s.create("beatles", Map("first_name" -> "Paul")) // データベースから first_name=Paul なデータを取得 s.get("beatles", Map("first_name" -> "Paul")) //=>Some(Map(first_name -> Paul, ...)) s.get("beatles", Map("first_name" -> "John")) //=>Some(Map(first_name -> John, ...)) // データベースからデータをまとめて取得する s.list("beatles")
予定、めも
- association とか sequence の機能はそのうち欲しくなったら実装します。
- joda-time くらいには依存してもいい気がしている。
*1:skinny には FactoryGirl http://skinny-framework.org/documentation/factory-girl.html があるけれど、skinny-orm 依存なので自分の用途には合わない。