2012年7月11日水曜日

クライアント向けインターフェースの実装(1)

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
好きな料理は?と聞かれたら、カレーと即答する、たなけんです。
本エントリでは、プレゼンテーション層とアプリケーション層とをつなぐ、クライアント向けインターフェースの実装について記載します。


クライアント向けインターフェースの実装(1)

プロジェクトファイル


Compojure ver 1.1.0の利用を追記しました
またleiningenからringアプリケーションを起動出来るよう:ringオプションを追記しました。

nsマクロ


compojure.coreとcompojure.routeの利用を追記しました。

仮実装


httpクライアントからアクセスを可能にするためurlと関数を結びつけました。

テストコード


正常系、以上系の処理の2パターンを追加しました。

対応するAPIを増やす(準備)

これまでDictionary.comのdefine/dictionaryのみを対象に、url構築からjson-文字列抽出を実装しましたが、Dictionary.comではdefinition/dictionary以外にも様々なAPIを提供されています。
そこで、折角ですのでdefine/dictionary以外のAPIにも対応できるよう、これまで実装した関数に変更を加えようと思います。(修正に伴い、関数ごとの機能の切り分けなど、プログラムの見通しも良くしたいと思います。)
表1: Dictionary.comのAPI一覧

サービス名typesite

Dictionary (英英辞書)definedictionary(任意)

Thesaurus (分類語彙辞書)definethesaurus(任意)

Slang (俗語辞書)defineslang(任意)

Etymology (語源)無しetymology

Example (例文)example無し

Questions and Answers (Q&A)無しquestionanswer

Synonyms (同義語)synonyms無し

Random (ランダム)randomdictionary(任意)

randomthesaurus(任意)

Spelling (綴り字)spelling無し

まずはhttpリクエストのパラメータについて整理します。
英英辞典、分類語彙辞書、俗語辞書、ランダムについては、同じ引数でurlを組み立てることができます。(ただしsiteは省略可能、省略時にはdictionaryが指定されます)
しかし例文、同義語、綴り時については上記とは異なり引数にsiteを取りません。また、語源とQ&Aについては、引数にsiteを取らない代わりにtypeを取ります。
つまり、urlのパターンは以下のようになります。
  • typeにdefineが指定される
  • typeにdefineが指定され、siteにdictionaryが指定される
  • typeにdefineが指定され、siteにthesaurusが指定される
  • typeにdefineが指定され、siteにslangが指定される
  • siteにetymologyが指定る
  • typeにsynonymsが指定される
  • typeにrandomが指定される
  • typeにrandomが指定され、siteにdictionaryが指定される
  • typeにrandomが指定され、siteにthesaurusが指定される
  • typeにspellingが指定される
現時点では、引数が固定のため、語源、例文、Q&A、同義語、綴り時のサービスに対応していません。また、レスポンスとして返されるxmlのフォーマットも異なるため、各サービスごとにxpathを変更する必要があります。
つまり、対応APIを増やす為に必要な修正点は以下となります。
  • interface-for-clientで呼び出しサービスを識別
  • 利用するAPIに対応したurlを構築
  • 利用するAPIに対応したxmlからのJSON文字列の生成


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

2012年7月8日日曜日

アプリケーションのテスト(2)とCIツールの導入

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
『名は体を表わす』の通り、健康でふくよかボディのたなけんです。
本エントリでは、アプリケーションのテストおよびCIツールの導入について記載いたします。


アプリケーションのテスト(2)

本日は以下のテストコードを紹介します。
  • xml抽出関数のテスト
  • JSON生成関数のテスト
  • url構築からJSON文字列生成までを結合した関数のテスト

xml抽出関数のテスト


  • 正常系: 正常urlを引数に、想定されるxmlが抽出されるかをテスト
  • 異常系: 異常urlを引数に、想定される例外が発生するかをテスト

JSON生成関数のテスト


  • 正常系: 正常フォーマットのxml文字列を引数に、想定されるJSON文字列が生成されるかをテスト
  • 異常系: 異常フォーマットのxml文字列を引数に、想定される例外が発生するかをテスト

url構築からJSON文字列生成までを結合した関数のテスト

正常系: 単語を引数に、想定されるJSON文字列が生成されるかをテスト

CIツールの導入

参考にさせて頂いたサイトのリンクをご紹介いたします。

  • Jenkinsのインストール Link
  • JenkinsとLeiningenの連携 Link


今回の作業は以上。最後までお読み頂きありがとうございました。
たなけん (作業時間30分(各種インストールは除く))

アプリケーションのテスト(1)


はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
『やってみせ、言って聞かせて、させてみて、褒めてやらねば人は動かじ』は、少し過保護なのではないかとふと思う、たなけんです。
本エントリでは、アプリケーションのテストを記載いたします。


アプリケーションのテスト(1)

本日は以下のテストコードを紹介します。
  • nsマクロ及び定数
  • 設定ファイル読み込み関数のテスト
  • url構築関数のテスト

nsマクロ及び定数


名前空間および依存ライブラリの宣言をします。
また、テストの検証に用いる定数も宣言します。

設定ファイル読み込み関数のテスト


設定ファイル読み込み関数をテストします。エラーの場合は想定されるExceptionかどうか判定します。

  • 正常系: 正しいフォーマットのファイル読み込み (記載内容 {:test "test"})
  • 異常系 1: 設定ファイルが存在しない場合のエラーハンドリング
  • 異常系 2: 設定ファイルの記載内容が異常の場合のエラーハンドリング (記載内容 {:test "test")

url構築関数のテスト


引数をつなげた文字列が生成されるかを確認します。

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


アプリケーションの実装(3)とバージョン管理ツールの導入


はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
お腹が空くと『欲しがりません勝つまでは』と言っている、たなけんです。
本エントリでは、アプリケーションの実装とバージョン管理ツールの導入について記載いたします。


アプリケーションの実装(3)

本日は、url構築からJSON文字列生成までを結合した関数のコードを紹介します。

url構築からJSON文字列生成までを結合した関数


引数に単語を取り、戻り値に意味を抽出したJSON文字列を返します。
  • ->マクロ: 左からS式を評価し、その返り値を次のS式の引数として、順次S式を評価する

    バージョン管理ツールの導入

    参考にさせて頂いたサイトのリンクをご紹介いたします。
    • gitのインストール Link
    • GitHubアカウント作成 Link
    • リポジトリへの追加 Link
    • 変更のコミット Link
    上記手順でGitHubにコードを登録&公開しております。
    ご関心のある方は、是非ご一読下さい。 Link


    今回の作業は以上。最後までお読み頂きありがとうございました。
    たなけん (作業時間30分(各種インストールは除く))

    アプリケーションの実装(2)

    はじめに

    おはようございます。当ブログにアクセス頂き、ありがとうございます。
    『臥薪嘗胆』が高校時代の座右の銘だった、たなけんです。
    本エントリでは、アプリケーションの実装について記載いたします。

    アプリケーションの実装(2)

    本日は以下のコードを紹介します。
    • url構築関数
    • xml取得関数
    • JSON文字列出力関数
    • 意味検索メイン関数

    url構築関数


    引数に与えられた文字列をurlテンプレートに埋め込みます。
    Dictionary.comは意味取得以外にもAPIを提供しているため、
    柔軟にurlを構築出来るよう引数を設定しています。 
    • str関数: 引数を文字列として結合する

    xml取得関数


    引数のurlへhttpリクエストを送信し、レスポンスを受信します。
    レスポンスのbody要素をxml文字列として取得します。

    • clj-http.client/get関数: 引数のurlにGETメソッドのhttpリクエストを送信

    JSON文字列出力関数


    xml文字列から、単語、品詞、意味を含むJSON文字列を生成します。

    • letfn特殊形式: スコープ内でのみ利用する関数を束縛
    • clj-xpath.core/$x: 第1引数のxpath問い合わせを、第2引数のxmlに対して実行する
    • let特殊形式: スコープ内でのみ利用する変数を束縛
    • for特殊形式: リスト内包表記
    • clj-json.core/generate-string: ClojureオブジェクトからJSON文字列を生成する

    例えば下記のようなxmlから

    下記のようなJSONを作成します。(改行、エスケープシーケンスは若干異なります)


    追記: リスト内包表記について

    例えば、(for [i '(1 2 3)] (+ 10 i))を評価すると、(11 12 13)が結果として返されます。
    動作のイメージとしては、forの後の角括弧内のiにリストの各要素が束縛され、角括弧の後のS式を評価した結果のリストを返すといったものです。
    1変数の場合は、map関数を用いても同様の結果を得ることが出来ます。
    (map #(+ 10 %) '(1 2 3))

    forの場合は複数の変数や、階層を持たせる(入れ子のfor文のイメージ)ことができます。
    複数の変数を利用すると、Pythonのタプルのような、2要素のhashmapを簡単に作ることができます。

    複数変数の例 (for [i '(:a :b :c) j '(1 2 3)] {i j})
    結果 ({:a 1} {:a 2} {:a 3} {:b 1} {:b 2} {:b 3} {:c 1} {:c 2} {:c 3}) 

    入れ子の例
    (for [i '(:a :b :c)]
      (for [j '(1 2 3)] {i j})
    )
    結果

    (
      ({:a 1} {:a 2} {:a 3})
      ({:b 1} {:b 2} {:b 3})
      ({:c 1} {:c 2} {:c 3})
    )


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

    開発環境整備とアプリケーションの実装(1)

    はじめに

    おはようございます。当ブログにアクセス頂き、ありがとうございます。
    『千里の道も一歩から』とつぶやきながら、人生を迷走しているたなけんです。
    本エントリではClojureを用いたWebアプリケーション開発の第一歩として、仕様策定(全体, 第1イテレーション)と開発環境の整備、そして実装について記載いたします。

    アプリケーションの全体像

    クライアントからhttp GETメソッドによって、サーバに問い合わせ、
    外部APIから取得した情報をhttpレスポンスとして返す、
    非常にシンプルなWebアプリケーションとなります。
    • 入力: クライアントにより入力された単語を受信する
    • 処理: 外部APIを利用し、英単語の意味を取得する
    • 出力: クライアントへ取得した意味を送信する

    各イテレーションのゴール

    1. プログラムから辞書にアクセスし、意味を取得する。(アプリケーション層)
    2. ブラウザからの操作を可能にする。(プレゼンテーション層)
    3. ユーザごとの履歴を残す。(パーシステント層)
    4. Herokuへのデプロイ及び性能テスト(運用)

    第1イテレーション実装方針

    • 辞書はDictionary.com のWeb APIを利用する
    • clj-httpを用いDictionary.comにアクセスし、意味を含むXMLを取得する
    • clj-xpathを用いXMLから意味を取得する
    • clj-jsonを用いClojureオブジェクトをjson文字列に変換する

    異常系の処理(全体方針)

    • 例外発生時には、Exceptionを補足して、アプリケーション例外を投げる
    • tools.loggingを用い、適切にログを残す(例外内容のトレース等)
    その他、機能毎に以下のような異常の発生が考えられます。
    • 設定ファイルの不備
    • 外部APIのダウン
    • 外部APIの仕様変更

    開発環境の整備

    以下のサイトを参考にさせて頂きました。
    • Emacsインストール Link
    • swank-clojureインストール via ELPA Link
    • Leiningenインストール Link

    ビジネスロジックの実装(1)

    本日は以下のコードを紹介します。
    • プロジェクトファイル
    • アプリケーション例外クラス
    • nsマクロ
    • 例外処理関数
    • 設定ファイル読み込み関数

    プロジェクトファイル


    Leiningenでプロジェクトを作成した際、自動生成されるproject.cljに
    利用する各種ライブラリを追記します。
    Leiningenは、JavaでいうところのMavenのようなもので、ライブラリの依存関係を解消します。
    プロジェクトファイルはMavenのPOMファイルにあたり、
    lein deps
    を実行することで、依存ライブラリのダウンロード、クラスパスへの追加をすることができます。

    アプリケーション例外クラス


    例外発生時にはJavaのクラス情報を利用するため、java.lang.RuntimeExceptionを継承した、
    アプリケーション例外クラスを作成します。
    compile関数でこのファイルをコンパイルした後は、他のJavaクラスと同様、
    Clojureプログラム内で利用することができます。

    nsマクロ


    nsマクロはJavaのpackageとimportを合わせたようなもので、
    名前空間と、その名前空間内で使用するClojure/Javaクラスを宣言します。
    :reload-allオプションは、逐次関連するファイルを再読み込みすることの指定です。
    :requireで宣言されたClojureファイルについては、
    asで付けられたエイリアス/メンバ
    で、指定されたファイルのメンバにアクセスすることができます。

    例外処理関数


    例外の内容をログに記録し、アプリケーション例外を発生させます。
    • do特殊形式: 副作用のある処理を行う
    • clojure.tools.logging/error関数: エラーをログ出力する
    • throw特殊形式: 例外を発生させる

    設定ファイル読み込み関数


    設定ファイルを読み込み、読み込まれた文字列をClojureのオブジェクトに変換します。
    • slurp関数: ファイルの記述内容を文字列として読み込む
    • read-string関数: 文字列をClojureのオブジェクトに変換する
    • try特殊形式: 例外が発生される可能性のある処理を包む。例外発生時に対応する例外を含むcatch節を評価する
    逐次ファイルI/Oが発生することを避けるために、一度だけget-properties関数をよび、
    その値をpropertiesとしてモジュール内に保持しておきます。

    今回の作業は以上。最後までお読み頂きありがとうございました。
    たなけん (作業時間60分(各種インストールは除く))

    2012年7月4日水曜日

    ブログはじめました


    はじめに

    おはようございます。当ブログにアクセス頂き、ありがとうございます。
    最近『今やる、すぐやる、出来るまでやる』がモットーの、たなけんです。
    本ブログは、私の関心のある技術を実際に利用した際の備忘を兼ねた記録となります。
    本エントリでは、Clojureを用いたWebアプリケーション開発の動機と、構想を記載いたします。開発の詳細は本日以降書き綴っていきたいと思います。


    動機

    留学生活も残り半年となり、職場復帰もいよいよとなってきました。そこで、復職後直ちに第一線で働けるよう、リハビリも兼ねていくつかソフトウェアを開発し、その過程をブログに記録していこうと思います。
    これまで蓄積してきたスキルの棚卸しと、新しいテクノロジーのキャッチアップを目的に一歩一歩進めて行きたいと思います。
    第一弾として、英単語学習ウェブアプリケーションを作ってみたいと思います。


    構想

    さて、実際に開発に入る前に、開発プロセスおよび採用技術を整理しておきましょう。
    開発プロセスとしては、以下のようなイテレーション型開発を採用しようと思います。
    1週間で1サイクル回しながら4週間で一応の完成を目指したいと思います。

    1. 構想
    2. 仕様策定
    3. 設計
    4. 実装
    5. テスト
    → 2. に戻って機能追加

    採用技術としては、以下を想定しています。ただし、使いながら適宜変更するかもしれません。

    実行系

    • プレゼンテーション(ユーザインタフェース)層: Clojurescript / Google Closure Tools
    • アプリケーション(ビジネスロジック)層: Compojure & 外部ライブラリ(Loggingなど)
    • パーシステント(トランザクション)層: CongoMongo
    • Web & AP コンテナ: Jetty
    • DB: Mongodb
    • OS: Linux
    • 稼働インフラ(ハードウェア&ファシリティ): Heroku

    開発系
    • 設計: 紙とペン
    • エディタ: clojure-mode / Emacs
    • REPL: swank-clojure / Leiningen
    • バージョン管理: git / Github
    • テスト: clojure.test / xunit / Jasmine / PhantomJS / Selenium
    • タスク(ビルド)自動化: Jenkins

    今回の作業は以上。最後までお読み頂きありがとうございました。
    次回は開発環境の構築と第1イテレーションの仕様策定、実装を予定しています。

    たなけん (作業時間30分)