ラベル DBMS の投稿を表示しています。 すべての投稿を表示
ラベル DBMS の投稿を表示しています。 すべての投稿を表示

2012年10月21日日曜日

プログラミングのタネ

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
椅子から立ち上がっただけで、激しいぎっくり腰に見舞われた、たなけんです。
本エントリでは、私なりのプログラミングのネタの探し方について記載します。

どう書く?org

はじめに頭に浮かんだのはどう書く?orgです。(久しぶりにのぞいてみるとサーバエラーになっていましたが)
問題の範囲が小さく、様々な言語で解答されているので、とっかかりやすく、他言語の特徴なども知ることができ、新しく覚えた言語を手に馴染ませる際に良く利用していました。

プログラミング本の写経

プログラミングの本、例えばPaul Grahamのon Lispであれば、Common Lispでどう書くか、ということが示されています。僕の場合は、Common LispではなくClojureでon Lispの写経を行いました。(SICPも早く完了したいのですが。。。)
その言語についての知識が全くない状態であれば、ただ写経するだけでも、習慣的な記法が身に付いて良いかと思いますが、私は少し退屈だと感じたのと、Clojureが好きであるという点から、少し言語を変えて写経を行いました。
Ruby on Railsを初めて学んだ際には”RailsによるアジャイルWebアプリケーション開発”という本を黙々と写経(というかコマンドとかもそのまま打ってました)しました。そのころは、Javaで書かれた自社製の独自フレームワークを使って開発することしかしておらず、Railsでは本当に少しのコードで、こんなことができるんだと衝撃を受けました。
写経をしながらだと、開発環境が整えられているためか、フレームワークのソースなどもその場で気になった瞬間に読むことができ、そういった点からも、手を動かさずに読むよりも理解が深まる気がします。
そういった訳で、プログラミング本はプログラミングのネタ供給元としてなかなか優れていると思います。

競技プログラミング

プログラミングコンテストチャレンジブックなど競技プログラミングのお題が紹介されている本やWebサイトも良質なネタの供給元だと考えられます。
しかし、僕自身がそれ程高度なアルゴリズムや実行時のパフォーマンスに関心がないため、競技プログラミングのお題でプログラムを書くことはあまりありません。(Excelの自動操作なんとかして的な、泥臭いけど知識が無いとてこずる系が興味の中心です)

ランサーズ

ランサーズというフリーランスへ仕事を依頼することができるサイトがあるのですが、ここでシステム開発系の依頼もいくつかあるようです。
内容としては、Webサイト構築、データの変換やデータベース構築などです。
その中で下記の2つの依頼が僕の目を引きつけました。

  • Webから商品情報をスクレイピングしてデータベースに登録する
  • 独自性ルールの麻雀ゲームを実装する

これを見た時、『これは職業プログラマ向け、どう書く?orgだ』と感じました。
それほど難しくなく、かつ現実的なスキルセットが必要なプログラムのネタが、ランサーズには転がっています。さらにそのプログラムの市場価値(依頼金額)も見られるので、『自分だったらx時間でできそう』とか、『この分野の依頼が多いから、やったことないけど手を出してみるか』といった自分のスキルの需要と供給についても考えられるので、『プログラム書きたいけど手頃なネタがないなぁ』という方には、ランサーズに出されているお題に取り組んでみることを、是非おすすめします。(個人的には、こういったスキルマッチングの市場がより一般的になるのかどうかなど、プログラムのネタ探し以外の点でもランサーズおよび類似サービスに注目しています)

必要に迫られ系

最後になりますが、やはり最も楽しいのは、自分のプログラムで現実の問題を解決することでしょう。ざっと思い出しただけで、今年は下記のプログラムを留学生活の合間に書いていました。

  • 計算問題自動生成(姪っ子向け、問題数、難易度を選んで計算問題生成)
  • 数独を途中までソルバ(単純に数を当てはめるだけの部分はプログラムに解かせ、推理が必要な部分は自分が楽しみながら解くためのツール)
  • 超簡易ERP(発注、在庫、営業、受注、販売、顧客、採用、給与、財務を管理するRailsアプリ、友人が文房具販売のスモールビジネスを始めるため、夏休み中に作成)
  • レポーティング (ビジネスゲームで得られる膨大なデータをDBに落とし込み、グラフを作成、マーケットシェアなど加工が必要な情報の計算)
  • ビジネスゲームロジック類推(蓄積したデータを変数に、統計モデルを検証し、どのパラメータが何に、どれくらい影響を与えるかを類推。)
  • 簡易OCR(画像データを変換、分割し、必要な箇所の文字を読みDBへ補完)
  • 英単語検索、記録(はじめは自分向けのコンソールツール、同じ単語を何回調べるかとか、類義語が簡単に取得出来るようにするなどをWordNetを使って実装。その後Webアプリとしてリニューアル)
  • オークションの売買履歴自動記録(アマゾンマーケットプレイスの上位1200冊の出品情報を継続的に取得(スクレイピング)記録し、売れるまでの期間、価格とランキングの変遷、売れる本のジャンルなどを求める)
  • 2chまとめの自動取得(スクレイピング)
  • Wordpress.comのブログに自動投稿(Seleniumでブラウザを自動操作)
  • POIを使ってExcelファイル作成(アドホックに良くある)


必要に迫られ系の変種としては、ライブラリの検証が挙げられます。このブログで紹介したDatomicQuartziteWeb-driverなど、新しいライブラリを使う際には、いきなり既存のプロジェクトに組み込むのではなく、検証用プロジェクトを作成し、機能を一通り試しています。厳密には『何を書くか?』というプログラムのネタを供給してはいませんが、『何か書く、できることの幅を広げる』という観点からは、ライブラリの検証もひとつのプログラムのネタと言っても良いかと思います。
ローカルに保存されているプロジェクトの残骸を数えてみると、上記プログラム以外にも30ほどプロジェクトがあり、2週間に1つ以上のベースでは新規ライブラリを試していた様です。(ふと思い出しましたが、今年の頭はcoffeescriptやクライアントサイドMVCにこってりはまっており、spine.jsなどソースをガリガリ読んでいました。こちらも機会を見つけて紹介したいと思います)

まとめ

今年書いたプログラムの総括のようになってしまいましたが、プログラムを書きたいけど何を書けば良いか分からない、という方のヒントになればと思い、本記事をしたためました。
ランサーズを見て、どう書く?orgを思い出したのが事の発端ですが、ブログを書いているうちに、必要に迫られて書いたプログラムの思い出が頭に浮かび、長くなってしまいました。
Clojureを使い続けて3年目です。はじめはファイルの入出力でさえもわざわざ調べて書いていたのですが、今ではDBやWebのプログラミングも手短にできるなど、手に馴染んできました。現実的な問題を解き続ける事で、できることの幅が広がり、達成するまでの労力と時間が短縮されました。
この冬に、学生からソフトウェアエンジニアへと職業が戻りますが、業務内/外にこだわらず、Clojureを使って問題を解決していきたいと思います。
また、ゲームを使った学習についても関心があるので、Javascriptのゲームライブラリであるenchant.jsもClojurescriptのラッパを書くなどして使ってみたいと思っています。

今日の作業は以上、最後までお読み頂き、ありがとうございました。
たなけん(作業時間30分)

2012年10月13日土曜日

Clojureアプリのデプロイ: Heroku

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
オーストラリアでの留学生活も終わりが見えて来た、たなけんです。
本エントリではClojureアプリケーションのHerokuへのデプロイについて記載します。

Webアプリケーションの作成

これまでいくつかClojureのWebアプリケーションを作成してきたのですが、Herokuで運用するために何か特別なライブラリが必要なのか等、不明な点が多かったので、Leiningenのプラグインであるheroku/lein-templateのテンプレート機能を利用して、Webアプリケーションの雛形を作成しました。
プラグインは~/.lein/profiles.cljに[heroku/lein-template "0.2.0"]と追記するだけで、インストールが完了します。(次回leinコマンド実行時に、必要なjarなどが自動的にダウンロードされます)
下記コマンドを実行し、Heroku上で動作するWebアプリケーションを生成します。
lein new heroku プロジェクト名

Webアプリケーションの構成

上記コマンドにより、下記の8ファイルが生成されます。

  • .gitignore
  • Procfile
  • README.md
  • web.clj
  • 500.html
  • 404.html
  • web_test.clj
  • project.clj

project.clj

ソースはlein-heroku/lein-templateで公開されているので、要約のみを記載します。
Webのライブラリとしてはオーソドックスにcompojureとringを利用しています。
しかしenvironとdrawbridgeという見慣れないライブラリも利用されていました。
そこで少し調べた所、environは設定情報を管理するライブラリでした(Javaでいう所のpropertyのような物でしょうか)。また、drawbridgeはリモートデバッグのためのライブラリでした。

web.clj

こちらもソースはGit上で公開されていますので、直接の引用は控えたいと思います。
environはHeroku上で設定された環境変数を読み込む為に使われているようです。
(REPLを使う際のユーザ認証。確かに、悪意あるユーザからプロセスを守らないといけないですね)その他、起動ポートや、セッションキーなどHerokuから割り当てられる変数を取得している様です。

Herokuアカウントの取得

さて、デプロイするアプリケーションを用意したところで、次はアカウントを取得します。
アカウントを取得する為には、Herokuのサイトからユーザ登録を選択肢、メールアドレスを入力するだけです。メールアドレスの入力後、確認のメールが送られてくるので、そのメール内のリンクから確認画面へ移動し、パスワードを設定します。
以上で、アカウントを取得する事ができます。

開発ツールのダウンロード、ログイン、アプリケーションの登録

Heroku ToolbeltというHerokuのCLIクライアントをダウンロードし、インストールします。インストール後、heroku loginでHerokuにログインし、アプリケーションルートに移動後、Heroku createでアプリケーションをHerokuに登録します。
あとはGitコマンドをパチパチ打ってソースをコミットし、コミットしたソースをheroku側と同期します。(コンソールでの操作は下記を参考下さい。)


Heroku Toolbeltの操作

プロセスの起動と終了

heroku psコマンドでプロセスの状態を確認する事ができます。
プロセスを起動する際は、下記のようにプロセス名とスケール数を指定します。
heroku ps:scale web=1
また、プロセスを終了する場合は、プロセス名.プロセス番号で終了するプロセスを指定します。
heroku ps:stop web.1

ログの確認

heroku logsコマンドでログを見る事ができます。初回起動時にLeiningenが依存関係の解消の為に必要なライブラリを取得しようとした形跡が見られます。(一度あるリポジトリへアクセスしたものの、そのリポジトリからは目的のライブラリを取得出来なかった際に出されるメッセージがログに残されていました。)
ログレベルの変更や、アプリケーションからのログ出力などは、アプリケーションの運用に必須な項目なので、変更方法等は知っておきたいところです。(調べてブログに書きます。。。)

環境変数の設定

heroku configコマンドで環境変数を設定します。ここで設定した環境変数のキーで、アプリケーション内から環境変数の値にアクセスする事が出来ます。

以上簡単に、Heroku Toolbeltを使ってみました。コマンド体系が直感的で理解しやすいといった感想を持ちました。作成した英単語学習アプリを公開したり、日々PCから実行しているルーチンのタスクをHeroku上のアプリからやらせるなど、いろいろとクラウド上でやってみたいことがあります。
HerokuはClojureを稼働させるのが簡単そうだったので、まず試してみましたが。今後データ量が大きくなりそうなアプリなどもありますので、他のホスティングサービスも試しつつ、ローカルのPCで走らせている日々のルーチンプログラムをクラウド上に移していこうと思います。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間1時間)



2012年10月10日水曜日

マーケットモニタリングアプリの開発(5): スクレイピングTips

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
可能な限り「どのような操作をするか」ではなく「(操作に依存せず)どんな結果を得たいか」をプログラミングしていたい、宣言型プログラミング大好き、たなけんです。
本エントリでは、スクレイピング(Webリソース(e.g. htmlページ)から必要な情報を抽出すること)のTipsを記載します。

FireBug

プログラマであれば、真っ先に思い浮かべるのはFirebugだと思います。御多分に漏れず、私もまずはFirebugでhtmlの構造を(タグを掘り下げながら)解析して行きます。
Firebugの便利な点としては、htmlエディタ(画面下部)上にマウスカーソルを移動させると、対応するhtmlイメージ(画面上部)がハイライトされる点が挙げられます。
スクレイピングしたい部分を画面上部に表示しておき、該当するタグを探って行くことでおおよそ必要な要素を特定することができます。

YQL Console

私がスクレイピングする際に重宝しているもうひとつのツールがYQL Consoleです。
YQLとはYahoo!が開発した『Webリソースに適用出来るSQL』のようなものです。
Firebugで取得したい要素を特定し、enliveのselectorを記述したものの、意図していない結果が返される事が多々あります。なぜならenliveのselectorは該当する要素を全て含んだ結果を返しますが、私が欲しいのはその中の一部だからです。
このような場合、selectorで返される要素を俯瞰し、必要な要素と必要でない要素の違いを見分けるために、私はYQL Consoleを利用します。
具体的には結果をtreeで表示し、必要な要素と必要でない要素を比較します。
理論的にはEmacs上でも結果の比較は可能なのですが、YQL Consoleは階層を可視化して
くれるので、直感的に要素の違いを見分けることができます。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間15分)


マーケットモニタリングアプリの開発(4): ランキングの更新

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
バイト先のレストランからビールを一箱もらってご機嫌の、たなけんです。
本エントリでは、モニタリング対象のランキングの更新について記載します。

ランキング更新の必要性と処理の流れ

取引が成立した理由を探る為には、出品時のランキングだけではなく、実際に売買が成立した時点のランキングも必要だと考えています。(出品後に人気が出て売れたのかどうかを検証するため)
そこで、モニタリング対象の本については、たとえそれが1200位(一括で取得できる上限)以下であっても、日々のランキングを取得する必要があります。
そこで、下記の流れで、ランキング情報を管理します。

  1. 本日のランキング上位1200を取得
  2. 前日までの累積されたISBN(ISBNマスタに登録済み)と比較
  3. 本日のランキング上位1200とISBNマスタとの差分を取得
  4. ISBNマスタに存在せず、本日のランキング上位1200に入ったものは、ISBNマスタに追加
  5. 本日のランキング上位1200に存在しないが、ISBNマスタに存在するものは、個別にランクを取得する


ソースコードと解説

ソースコードは下記の通りです。

ランキングは商品詳細ページに含まれるため、まずは商品詳細ページにアクセスします。(詳細ページのurlはhttp://www.amazon.co.jp/dp/商品コード(ISBN))順位を含むタグから値を取得、また順位が含まれない場合はnilを設定します。ただし、18禁のコンテンツは直接商品詳細ページにアクセス出来ないため、仮置として-1を設定しています。
技術的には特に新規要素は無く、ただenliveを用いて必要な情報を取得しているだけです。
取得した情報はRDBMSのランキングテーブルに追加されます。

今日の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間1時間)

マーケットモニタリングアプリの開発(3): 取引情報取得

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
日本に帰国したら、携帯キャリアは何にしようか決めかねている、たなけんです。
本エントリでは、アマゾンマーケットプレイスの出品情報の取得について記載します。

ブラウザからアクセス

アマゾンの商品詳細ページから、中古の出品リンクをクリックすると、出品情報の一覧が表示されます。その時のurlは下記のようなものでした。
http://www.amazon.co.jp/gp/offer-listing/4121020618/ref=dp_olp_used?ie=UTF8&condition=used
このurlからhttp://www.amazon.co.jp/gp/offer-listing/にISBNを付けると、取引情報の先頭ページにアクセスできることが予想されます。
実際に別のISBNで試した所、予想通り取引情報の先頭ページにアクセスすることができました。
また、先頭ページのhtmlを解析したところ、次ページへのリンクはa要素のidがolp_page_nextであるタグのhrefの値であることが分かりました。

プログラムからスクレイピング

上記の観察に基づき、ISBNから出品情報を取得するため、下記の様な関数を作成しました。


  • condマクロ: JavaなどのCase文のようなもの
  • その他工夫した点: Lispらしく、再帰を利用。次ページがあれば、結果をリストに追加して、再帰。次ペーがなければ結果を返す。

その他は、前回と同様enliveを用いて、販売者ID、販売価格、商品状態を抜き出しています。
抜き出した値は、RDBMSの取引情報テーブルに日付とともに収納しています。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間1時間)

マーケットモニタリングアプリの開発(2): 中古ランキング取得

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
最近少しずつ体重が減少してきた、たなけんです。
本エントリでは、アマゾンマーケットプレイスに出品されている本の、ランキングの取得について記載します。

ブラウザからアスセス

プログラムからアクセスする前に、まずはブラウザからアクセスしてurlを見てみました。
アマゾンのトップ画面から”カテゴリー > 本”を選択し、メニューの詳細をクリック後、条件を入れずに検索すると、左下に状態を選択するリンクが出るので、それをクリックします。さらに右上の並べ替えで『人気度』を選択すると、アマゾンマーケットプレイスに出品されている本のランキングが取得出来ます。さらに下部のリンクから次のページへと移動すると、urlは以下のようなものでした。
http://www.amazon.co.jp/s/ref=sr_pg_2?rh=n%3A465392%2Cp_47%3A2020%2Cp_45%3A0%2Cp_46%3Abefore%2Cp_n_condition-type%3A680579011&page=2&bbn=465392&sort=salesrank&unfiltered=1&ie=UTF8&qid=1349846898
このurlをデコードすると、下記のようになります。
http://www.amazon.co.jp/s/ref=sr_pg_2?rh=n:465392,p_47:2020,p_45:0,p_46:before,p_n_condition-type:680579011&page=2&bbn=465392&sort=salesrank&unfiltered=1&ie=UTF8&qid=1349846898
このurlからrh=以降のパラメータは検索条件、pageはページ番号、sortは並べ替え順であることが推測できます。
pageパラメータの値を3にしたところ、推測通り3ページ目を読み込むことができました。

プログラムからスクレイピング

上記urlのページを変えてアクセスすることで、1ページから100ページまでプログラムからアクセスすることができることが分かりました。各ページ12冊の本が表示されるため、最大で1200位までの本の取引をモニタすることになります。
それでは、ランキングのページからISBNを抽出してみましょう。
ランキングのページのhtmlの構造を解析したところ、div要素の、id=順位 - 1のタグに含まれる事が分かりました。
そこで、スクリプト用ライブラリのenliveを用いて、各ページから順位とISBNを取得する関数を下記のように定義しました。


  • net.cgrand.enlive-html/html-resource関数: 引数のurlをhtmlとして読み込む
  • clj-http.client/get関数: 引数のurlを読み込む。オプション引数は文字コード
  • clj-time.coerce/to-sql-date関数: java.sql.Date型に変換
  • clj-time.core/now関数: 現在時刻を取得
  • net.cgrand.enlive-html/select関数: 指定したタグの値を取得

上記関数で取得したISBNをRDBMSのUSED_RANKテーブル(日付、ISBN、ランキング)に保存し、まずはモニタリング対象となる本を登録することができました。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間1時間)

マーケットモニタリングアプリの開発(1): 概要

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
しばらくマーケットモニタリングアプリの開発に没頭していました、たなけんです。
本エントリでは、マーケットモニタリングアプリの概要について記載します。

事の発端

クラスメイトとの雑談で、古本の流通について話題となりました。そこで私は、日本では個人がアマゾンに本を出品できることを紹介しました。すると友人は、『どんな本が、どれくらいの値段で売れるのか、自動的にデータを取れないかな? データが取れるとどんな本をいくらで出品するのが良いか分かるね。』とアイデアを提案してくれました。
そこで、Clojureでプログラムを作成し、アマゾンマーケットプレイスでどのような本が売れているのかのデータを取る事にしました。

処理の流れ

売れ筋の本の方が、中古本であっても回転が早いだろうと仮定し、まずはベストセラーランキングから本のISBNを取得し、その後、そのISBNをキーに取引情報(sellerIdとisbnで一意に識別)を取得します。
取引情報を継続して取得し、公開されている取引情報が消えた時点で、その取引が成立したと見なし、成立取引一覧に取引情報を移します。
成立取引一覧のISBNから本の属性(ジャンル、出版日)や値引率などを分析し、どんな本がどれくらい売れるのかを求めます。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間15分)

2012年9月13日木曜日

第3イテレーションの振り返り

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
肩甲骨のストレッチの効果か、姿勢が良くなったと最近言われた、たなけんです。
本エントリでは、第3イテレーションを振り返ります。

Datomicおよび各種ライブラリを利用した所感

長所

Clojureで書かれている製品である為、クエリにそのままClojureの式(自作の関数も含む)を使う事が出来る

Clojureで書かれている製品である為、Clojureのデータをそのまま収納する事が出来る

原理的にはスケールアウトが可能
クエリおよびデータの追加、変更がほぼClojureのS式である(Clojureネイティブである)点が唯一にして最大の長所だと思います。RDBMSを利用していると、例えばSELECT文ではSQLの書式に従い、SQLの関数を利用して結果を得て、そこからClojureのデータに束縛し直す必要があります。しかし、Datomicではfindの条件にそのままClojureの関数が使えるため、SQLとClojureのデータを行き来するような処理は必要なく、手早く開発することができました。

短所


  • 無料版ではfreeおよびmemプロトコルのみであるため、スケールアウト性能を検証することができない
  • BIツールのように複数のテーブルを結合するなど、様々な角度からデータを解析する方法が確立されていない
  • 集約系の関数など、自力で実装しなくてはならない

RDBMSであればスタースキーマなど、分析対象のデータを多次元的に扱う手法が確立されています。Datomicの柔軟なクエリ構築力を考慮すると、恐らく良い実装方法があるのだろうと、ぼんやりとそのポテンシャルは感じたのですが、今の時点では具体的な方法までは見えていません。

短所としてBIツールの様な多次元表の利用を挙げましたが、「プログラマブルなクエリが書ける、マクロも書ける」というDatomicの潜在能力を引き出せば、SQLを使うよりもスマートにこれらのソフトウェアを実装することができると(根拠は薄弱ですが)直観しています。

Webアプリケーションを一通り書いてみて気付いたこと(およびClojure愛)

これまで、主なClojureの使い道はツール作成でした。しかし、今回はプレゼンテーション層からパーシステント層までClojureを用いて、小さいながらもWebアプリケーションを完成させることができました。そこで気付いたことを振り返りたいと思います。

自転車あるいは糊

Clojureは私にとって最も手に馴染んだプログラミング言語です。そのしっくり来る感じを例えると「自転車」です。気軽に、どこへでも、最短距離で移動できる乗り物です。
他のプログラミング言語を同様に例えるとすれば、Cは飛行機、Javaは鉄道、Pythonはバスでしょうか。それぞれに利点はありますが、家の裏の公園に行く為に、飛行場を作ったり、線路を引くのは、得たい結果に対して労力が釣り合わない気がします。その点Clojureは行きたい場所へ、そこが車さえも入り込めない路地であっても、最短経路でたどり着くことができます。
また、目的地が遠ければ、鉄道や飛行機を乗り継いで行けばいいのです。駅と飛行場の間は自転車で移動し、最後のバス停から終着地点までの間だけ自転車に乗る事もできます。これは必要に応じてCやJavaで書かれたアプリケーションやライブラリをClojureから使って、目的の機能を実現している時の、僕の頭の中にあるイメージです。
実際、ブログでも紹介したTesseractやImagemagickをClojureから操作し、H2 Database Engineへデータを格納後、帳票を出力するツールの実装は、この乗り継ぎの比喩の良い実例と言えるでしょう。そしてWebアプリケーションに関しても、一から書いたコードは少なく、殆どはライブラリが提供する機能をつなぎ合わせたものでした。
多くの人はこう言うでしょう。「それは自転車ではなくて糊だよ」と

マクロ

自転車の例えはまだ続きます。車のエンジンをバラしてまた組み挙げられる人はどれくらい居るでしょうか、またそれに掛かる時間は?工具は?
バラして組み直す事、これはすなわち言語そのもののハックのしやすさの比喩といえます。
Clojureはシンプルです。特殊形式とマクロと関数しかルールが無いと言っても良いでしょう。構造が簡潔であり、なおかつユーザが手を加える余地を十分に残しています。マクロは、簡単に言えば言語の構文を規定し直す機能です。私は多用はしませんが、「いざとなればマクロでなんとでもできる」という信頼感があります。メカニズムを把握していて、そこに手を入れることができる感覚、それは自転車いじりに似ています。自動車のエンジンや、電車のモーターは、固そうですし、私には複雑過ぎます。
マクロの存在がClojureをシンプルかつ柔軟にしており、マクロがあるため僕はClojureを信頼して使い込む事ができています。この感覚が、やはり私にとって自転車なのです。

万人の自転車へ

Clojureが私にとって自転車である事、それは多くの人にとってどうでも良い話だと思います。しかし、Clojureは他の人にとっても自転車となり得る言語だとしたら?
私はJavaのアプリケーションやライブラリを鉄道に例えました。同様にClojureのライブラリは地下鉄や高速道路網と例えても良いかもしれません。多くの人が利用する点から点への移動には、より効率よく移動するための道が敷かれるからです。そして、それら全ての乗り物に、だれでも自転車を携えて乗ることができます。
このブログを読まれた方が、「Clojure使ってみようかな」と思ってもらえるように、これからもClojureの魅力を伝えていきたいと思います。

私に足りないもの

自転車は簡単に乗れますが、奥が深い乗り物です。フォームの善し悪しで、疲労度が大きく変わります。
私はこれまで、全くの我流でコードを書散らしてきました。自転車で言えばがむしゃらに漕いでいる状態です。
Webアプリを設計、開発する中で何度も「どう書くのが関数型言語の特性を活かしているのか?」と自問しつつも、まず動く物を優先して、ここまで漕ぎ進めて来ました。
当初の目標であったプレゼンテーション層からパーシステント層まで実装を終えた今、次に何をすべきかと考えました、私には何が足りないのだろうか?と。
そこで考え至った結論が、フォームの改善です。プログラミングの基礎です。

年内の目標

コンピュータ書の古典"SICP(計算機プログラムの構造と解釈)"の原著が本家サイトから無料で読む事ができます。関数型プログラミングのエッセンスを掴むべく、このSICPの原著を年末までに読み切りたいと考えています。
学習記録をブログに綴る事で、読者の皆様にも関数型言語でのプログラミングの公理のようなものをお伝えできればと考えています。

運用フェーズに向けて

Webアプリの開発フェーズはほぼ終了しましたが、まだこのプロジェクトは終わっていません。そうです、Herokuにデプロイしてサービスを公開、運用ノウハウを蓄積するというタスクが残っています。また、運用しながらメンテナンス性を高める為にリファクタリングしたり、ログ解析ツールそして機能追加など、改修のアイデアはまだまだあります。
SICPリーディングと平行して、Webアプリプロジェクトも継続していきます。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間1時間)


Datomicの利用(3)

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
テストコードを書く時、気持ちの昂りを抑えきれない、たなけんです。
本エントリでは、Datomicを利用したClojureアプリケーションのテストについて記述します。

本体の改修

テストコードを実行した際、想定した通りにデータの改廃がされていなかったため、本体コードを改修しました。
元のソースでは、定数connの宣言部で一度だけt/connect関数を呼び、その接続を他の関数内で利用していました。しかし、この場合、データベースが削除されても接続(peer)のキャッシュにデータが乗っているため、検索が可能な状態でした。
テストコードでは、各テストの前にデータベースを削除し、全てのデータを初期化する必要があったため、find-all関数などに含まれている接続オブジェクトも更新(具体的にはt/connect関数の呼び直し)が必要となりました。
そこで、接続オブジェクトを各関数の引数とし、接続オブジェクトの更新が必要無い本体コードでは、一度だけ宣言したconnを、テストコードでは毎回呼び直したオブジェクトを利用する様変更しました。


単体テスト

事前条件として、peerのGC、データベースの削除、追加、スキーマの作成を行っています。その後データ挿入、検索のテスト。再度条件を初期化し、利用制限確認関数の境界値テストを実施するようにしました。


結合テスト

手動でテストを実施しました。
データベースを初期化、限界件数を1にした状態で、画面を操作し、1度目の検索は正常に実行され、2度目の検索でsorryメッセージが表示されることを確認しました。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間30分)

Datomicの利用(2)

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
西川きよし師匠の「小さなことからこつこつと」に、とても共感している、たなけんです。
本エントリでは、ClojureアプリケーションでのDatomicの利用について記載します。

仕様

今回のWebアプリケーションでは、利用制限のある外部APIを使用します。そのため、一日の間に、一定回数を超えるアクセスがあった場合、外部APIへの利用を止める処理が必要となります。
そこで、アプリケーションから外部APIへ問い合わせた内容を永続化しておき、次のアクセスの前に、その日のAPIコール回数を(データベース/Datomic)確認し、利用制限を超えている場合は、その旨をユーザに伝えることとします。
APIへの問い合わせ内容として、まずは検索した単語と検索した日時を記録します。
また、調べられている単語や、アクセスされている日時の傾向を把握する為に、入力された全ての履歴を表示する画面も追加します。

実装

実装の大部分は、thearthurさんのgithubのコードを参考にさせて頂きました。

プロジェクトファイル


Datomicのクライアント(Datomic用語でpeer)であるcom.datomic/datomic-freeおよび、時間計算に便利な(Joda Time LibraryのClojureラッパ)ライブラリであるclj-timeを追加しました。

ns マクロ


プロジェクトファイル同様Datomicおよびclj-timeライブラリの利用を宣言します。

  • use節: datomic.apiのうちdbとqは名前空間を付けずに呼び出せ、他の関数は名前空間のエイリアスにdを仕様
  • require節: clj-time.coreおよびclj.time.coerceの名前空間のエイリアスを設定


データベースおよびスキーマの作成(DDL)


データベース及びスキーマを定義します。無料版のDatomicではメモリにデータを保存するmemプロトコルと、H2 Database Engineを内部で利用し、ファイルにデータを保存するfreeプロトコルを利用することができます。
Datomicのスキーマ定義はRDBMSとはやや異なり、属性毎に個別に定義を宣言することでエンティティ全体を組み立てる形式となります。
具体的には、上記ソースでは、エンティティがworkで、wordとtimeがworkの属性として宣言されています。(それぞれ型はstringとinstant(日時))
RDBMSでの定義を(単純化して)考えると、テーブル名がworkとなり、wordとtimeはテーブルworkの中の列となります。
RDBMSのようにトップダウンでスキーマを定義する訳ではなく、逆にボトムアップでスキーマを定義して行きます。
実際、列の型を変えるなど、プログラミングしながら、属性を追加したり、削除したのですが、スキーマ変更に伴い、わざわざ既存のデータを変更(エクスポート&インポート)しなくても良かった点には驚きました。(RDBMSを利用している場合は、スキーマを変更した場合は、データのインポートが必須となるので)
データモデルを固める前に、いろいろと試すことができる、柔軟であるといった意味では、開発時に余計な作業でプログラマの時間を奪わない工夫がされていると感じました。
その一方、データ型が不揃いであることから、検索時の性能劣化、柔軟すぎて不整合が発生しないだろうかなど、運用時に考慮すべき課題も目につきました。

  • d/create-database関数: 引数のurlをアドレスとするデータベースを作成(データベースを作成していないと、コネクション作成時に例外が発生する点に注意が必要)
  • d/connection関数: 引数のurlで指定されたデータベースへの接続を確立する
  • d/transact関数: 引数の式をトランザクションとして実行する


データの追加および検索(DML)


スキーマの定義が管理用領域への(メタ)データの書き込みであるのに対し、データの追加はユーザ領域へのデータの書き込みとなります。(どちらも "d/transact conn データ" と書かれているのはその為です。)
add-a-work関数では、引数に単語と日時を取り、workエンティティを追加します。
find-all関数では、登録されている全てのworkエンティティを取得します。q関数の引数となっているクォートされたベクタがSQLで言う所のSELECT文に相当します。
:findに続く?n ?tは、SQLのSELECTに続く列名の様なものです。しかし、SQLとは異なり属性定義(スキーマ)に紐付いている訳ではなく、任意の文字列が利用可能です(?nameなど)。
?nおよび?tが何を表わしているのかは、続くwhere節で定義されます。
”[?e :work/word ?n]”は「任意のエンティティ?eの属性:work/wordの値は?nである」ということを宣言しています。言い換えると、任意のエンティティ?eは、属性に:work/wordを持ってることになります。つまり「?nは属性に:work/wordをもっているとあるエンティティの:work/wordの値である」ということを表わしています。
"[?e :work/time ?t]"も同様に、「?tは属性に:work/timeをもっているとあるエンティティの:work/timeの値である」となります。
では複数ある:work/wordの値と:work/timeの値が、それぞれ同一エンティティに紐付いていることはどのように示されているのでしょうか?(SQLでテーブルを結合する際に、結合する基準となる列を指定するようなイメージ)
実はDatomicでは特にキーを指定する必要がありません。なぜなら前の式”[?e :work/word ?n]”の?eと、後の式"[?e :work/time ?t]"の?eは、任意ではあるが同一のエンティティと見なすからです。Datomicのクエリで使用される名前(?nなど)は、同じ名前であれば同じオブジェクトを指していると見なされます。この結果、find-all関数の結果として、属性に:work/wordと:work/timeを持っているエンティティの、それぞれの値の集合が返されます。この仕組みをDatomicでは論理プログラミング(Logic programming)と呼んでいます。

  • time/now関数: 現在日時を取得
  • time/within?: 引数のintervalの中に引数の日時が含まれて入ればtrueを返す
  • time-coerce/to-date: Jodaのdatetime型からjava.util.Date型へ変換
  • time-coerce/from-date: java.utils.Date型からJodaのdatetime型へ変換


クライアントからのアクセスのコントロール


外部APIにアクセスする前に、その日のアクセス総数を取得し、制限を超える場合は、検索をせずにsorryメッセージを返すよう、limit?関数を追加、call-api関数を変更しました。

全履歴を取得する管理画面


httpクライアントからfind-allを呼ぶインターフェースを追加しました。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間2時間)

Datomicの利用(1)

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
日本語であるにも関わらず、ロシアからのアクセスが最も多いブログを書いている、たなけんです。
本エントリではClojureアプリケーションでのDatomic利用方法(インストールまで)を記載します。

Datomicとは

Datomicとは、私が愛用しているClojureの作者である、Rich Hickey氏が開発している、新しいタイプのDBMSです。
現在では、これまで主に利用されてきたRDBMSだけではなく、KVSなどもごく普通に利用されるようになってきましたが、それらのデータベースと異なる点は何か、少し見てみましょう。

リードに重点を置いたデータ分散システム

データが更新されたタイミングで、クライアント側に持たせているキャッシュが同期されます。そのため、ノードは分散されていますが、検索前に必要なデータに関連するキャッシュを更新し検索するため、高速にデータの読み込みが可能です。その反面、データの一貫性を保証しながら書き込むため、ライトには多少のオーバーヘッドがかかります。

クライアント側でクエリを解析

通常のRDBMSではクライアントから投げられたSQL文をサーバで解釈してから、実行するのですが、Datomicはクエリの解釈をクライアントで行います。その結果、サーバ側の負荷が通常のRDBMSよりも軽くなり、少数のサーバで多数のクライアントからのアクセスを、軽快に捌くことができます。

柔軟なクエリ

ClojureひいてはLispの根本思想である『全てのプログラムはデータであり、全てのデータはプログラムである』をDatomicは体現しています。
先述の通り、クライアント側でクエリを解釈するということもあり、クエリそのものがプログラムであることを許容しています。
プログラム可能なクエリという発想は、識者をして「Datonicは10年先のテクノロジーを先取りしている」と言わしめている理由のひとつかもしれません。

インストールとトランザクタープロセスの起動

Datomicのダウンロードページより無料版をダウンロードし、任意のディレクトリに解凍します。解凍先のディレクトリに移動し、シェルに下記を入力しトランザクタープロセスを起動します。

bin/transactor config/samples/free-transactor-template.properties

デフォルトではポート4334が接続待ち受けポートとなります。
ポートやその他設定を変更するには、config/samples/free-transactor-template.propertiesファイルを編集します。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間30分)

2012年8月19日日曜日

第3イテレーションの計画

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
『今やる、すぐやる、出来るまでやる』がモットーの、たなけんです。
本エントリでは、第3イテレーションの計画として、仕様および実装方針を記載します。

第3イテレーション(パーシステント(トランザクション)層)の仕様

外部APIを規定の回数以上使用しないよう、検索語と検索日時をデータベースに記録し、規定回数以上のアクセスがあった場合は、外部APIへアクセスせず、画面にメッセージを表示します。
RDBMSでの実装するのであれば、1テーブルのみ、列は単語と日時といったシンプルな構成となるような仕様です。

実装方針

最終的にHerokuにデプロイしてサービスインする予定ですので、無料で利用可能なDBの選択肢として以下の3つが考えられます。

  • PostgreSQL
  • MongoDB
  • その他組み込み系DB

通常のRDBMSについては帳票処理の際に利用し、特に問題なく利用出来たため、
今回のアプリケーションでは、新たなチャレンジとして

  • MongoDB
  • Datomic(組み込みモード)

を用いて、パーシステント層を実装したいと思います。

テスト方針

下記の4ステップを1サイクルとし、継続的にテストが可能な状態を目指します。

  • テストデータの作成
  • 取り込み
  • テスト
  • テストデータの消去


今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間15分)

2012年8月12日日曜日

Clojureで帳票処理(csv読み書き、RDBMS利用、グラフ描画、PDF出力)

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
授業が始まってからグログ更新が滞っていた、たなけんです。
本エントリでは、Clojureを利用した帳票処理について記載します。

事の発端

現在、大学院で会計を専攻しているのですが、任意科目でいくつかのMBA専攻のクラスを受けています。(前期までに、ほぼ会計は履修したため、今期は75%がMBAのクラス)
その履修しているMBAクラスのひとつに、企業戦略を立案するクラスを履修しています。
面白いことに、このクラスの成績は、シュミレーションゲーム上のスコアにより決定されます。(クラスのメンバーを8チームに分け、チーム間で競争することとなります。)
決定すべき項目として、製品開発(高機能戦略や低価格戦略)、マーケティング(世界を4地域に分け競合の出方を伺いながらどのエリアを攻めるか)、生産(工場の人員配置や設備投資など)、財務(株式発行、社債発行など)などがあり、毎週50項目ほどのパラメータを検討して、事業戦略を実装し、他チームと結果を競い合っています。
各チームが決定する50項目のうち、27項目は年度末(実際は毎週日曜日)に結果とともに全チームに公開され、翌年のパラメータ検討の際の参考資料とすることができます。
他チームが見る事のできるパラメータは27項目なのですが、それがチーム毎(8)、地区毎(4)、四半期毎(4)で公開されるため、結果として毎年3,456(=27*8*4*4)項目に目を通すこととなります。また、年間の比較を考えると、1年(1週間)毎にデータが3,456項目ずつ増えることになりますので、数値だけを見て比較するのは困難であると考えられました。
そこで、数値の変化を、各社、各地域で比較出来るようグラフを作成することとなりました。

仕様

入力: 会社、地域ごとに1csvファイル。行は項目、列は四半期ごとの数値が記載されている。
出力:1項目1ページ、1ページに各地域のグラフを縦に配置、1グラフに8社と平均値を表示、横軸は時間、縦軸は値。

出力例
製品販売価格



数値をグラフにすることにより、各チームの意思決定が比較しやすくなっているのが分かると思います。例えば、EA市場ではほとんどのチームが価格を他の地域より高めに設定していること、また、year7に突然ピンクチームがAP、LA、NA市場で価格を高く設定したことなどがこのグラフから読み取れます。

実装

全ソースはtana-kenのGithubにて公開しています。
興味を持たれた方は是非ご覧になって下さい。
以下、ポイントを絞って、実装内容を紹介します。

nsマクロ

https://gist.github.com/3331553
ライブラリとしてclojure.java.io、clojure.data.csv、clojure.java.jdbc、incanter.core、incanter.chartsを利用します。

csvファイル読み書き


ファイルサイズが十分に小さいため、遅延シーケンスとして処理をせず、doallにより全データをメモリ上に読み込んでいます。

行列入れ替え


元ファイルは、列方向にデータが追加される仕様であったため、行方向にデータが追加されるよう、行と列を入れ替える処理を実装しました。

RDBMS利用


組み込みRDBMSとしてH2 Database Engineを採用しました。
csvファイル読み込み同様、想定される取得データが十分小さいため、doallにより全データをメモリ上に読み込んでいます。
また、今回はテーブルを結合する必要がないため、H2 Database Engineのcsvファイル読み込み機能を利用しました。(csvファイル読み込み -> 整形 -> 1ファイルに結合 -> H2 Database Engineにてテーブルとして利用)

グラフ描画


incanterを通じてjfreechartオブジェクトを作成しています。
RDBMSからグラフ描画に必要なデータセットを取り出し、グラフを描画します。

nsマクロ


incanterで利用しているjarと依存関係で不整合があったため、プロジェクトを分けました。ライブラリにはclj-pdfを利用しています。

内容作成


タグ付けされたベクタにて要素を構成しています。
sort-by関数により、ページを制御しています。

PDF描画


pdfマクロにて、与えられた内容をpdfファイルとして出力します。

今回の作業は以上、最後までお読み頂きありがとうございました。
たなけん(作業時間4時間)