GradleでExcelを読み込んでなにかを作る

Gradle の社内勉強会をやることになったので、ネタ集めをしています。

「Gradle、実はこういうこともできるよ」ネタを考えてたら
私がよくやるのを紹介したらいいかもと思いつきました。

Gradle はスクリプトベースのビルドツールなので、
極端な話、ガリガリとスクリプトを書けば何でもできます。

ちょっとした Excel 読み込みからの→ファイル生成を個人的によくやります。
自分用の作業テンプレートを作っておく意味もあって、まとめておきたいと思います。

Gradleタスクを作る

build.gradle は以下のような感じです。

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.apache.poi:poi:3.13'
        classpath 'org.apache.poi:poi-ooxml:3.13'
    }
}

import org.apache.poi.ss.usermodel.*

task generateMessageIdJava << {

    Workbook workbook = WorkbookFactory.create(
                                  new File("メッセージマスタ.xls"))
    Sheet sheet = workbook.getSheetAt(0)

    new File("MessageId.java").withWriter("UTF-8") { writer ->

        writer << "package sample.constants;\n\n"
        writer << "public class MessageId {\n\n"

        (3 .. sheet.getLastRowNum()).each { rownum ->
            Row row = sheet.getRow(rownum)

            String messageId = row.getCell(0).getStringCellValue()

            // メッセージIDが記載されていない行は書き出さない
            if (messageId?.length() == 0) return

            String message = row.getCell(1).getStringCellValue()

            writer << "    /** $message */\n"
            writer << "    public static final String $messageId"
            writer <<                             " = \"$messageId\";\n"
            writer << "\n"
        }

        writer << "}"
    }
}

やっていること
・buildscript ブロックで Apache POI を使えるように依存関係を設定します。
・同様に、Apache POI が使えるように import 文を追加します。
Excel を1行ずつ読み込みながら、出力ファイルに1行ずつ書き出します。

build.gradle と読み込む Excel ファイルは同じフォルダにある想定です。
出力ファイルも同じフォルダに生成します。

Excel ファイルの中身はこんな感じです。
よくあるマスタ定義ファイルです。

f:id:hideoku:20151111010422p:plain

build.gradle と同じディレクトリに Excel ファイルを配置しておきます。

[とあるフォルダ]
├build.gradle
├メッセージマスタ.xls
└(MessageId.java

タスクを実行してファイルを生成する

gradle generateMessageIdJava

タスクを実行すると、以下のようなファイルが出力されます。
よくみる定数定義ファイルです*1

package sample.constants;

public class MessageId {

    /** 検索しました。検索結果は{0}件です。 */
    public static final String MSG001 = "MSG001";

    /** 登録しました。 */
    public static final String MSG002 = "MSG002";

    /** ユーザIDとパスワードを入力してログインしてください。 */
    public static final String MSG003 = "MSG003";

    /** {0}は入力必須です。 */
    public static final String MSG004 = "MSG004";

    /** {0}は{1}以下の数値で入力してください。 */
    public static final String MSG005 = "MSG005";

}

応用例

このような Gradle タスクを Jenkins などの CI に組み込めば、
設計書が SCM(Subversion, Git etc)にコミットされたのを検知して
自動的に設計書に対応したソースコードを生成して、コミットする
…なんてこともできます。
面倒なルーチンタスクからの解放です。

Gradle Wrapper を使えば、Gradle インストールしていない人にも
使ってもらうことができますね。

*1:こういう定数定義ファイルに意味があるのかどうかは横に置いておきます。そういうものが必要とされる職場があるのだということで。

CheckStyleでテストクラスだけ日本語メソッド名OKにする方法

CheckStyle の設定で苦労したので、作業メモを残しておきます。

やりたいこと

テストクラスはメソッドを日本語で宣言したいので、
テストクラスのメソッドだけを CheckStyle のチェックから外したい。

MethodName モジュールの仕様

メソッドの命名チェックを行っているのは “MethodName" というモジュールです。

<module name="MethodName"/>

CheckStyle の設定ファイルではこんな感じで設定されています。
デフォルト値は省略されていますので、明示的に属性値を書いてみると以下のような感じに。

<module name="MethodName"
               format=“^[a-z][a-zA-Z0-9]*$"
               allowClassName=“false"/>

format 属性で「小文字英字で始まって」「英数字のみ」という命名ルールが規定されています。
記号も日本語もダメ。
allowClassName 属性はクラス名と同じ名前のメソッドを宣言してもよいかどうか(当然 false)。

excludesClassName みたいな属性があれば、「ファイル名が “Test.java” で終わるもの」と
指定できたりしますが、このモジュールは残念ながらそういう属性はありません。

なんとかがんばるしかありません。

SuppressionFilter を使う

SuppressionFilter を使うことで、各モジュールが行うチェックの対象外を指定することができます。
http://checkstyle.sourceforge.net/config_filters.html#SuppressionFilter

便利そうです。

だけれど、ちょっとやっかいです。
いつもの CheckStyle 設定ファイルとは別で、ファイルを作らないといけないです。

いつもの CheckStyle 設定ファイルには
以下のように「SuppressionFilter の設定は別ファイルを見てね」と設定追加します。

<module name="SuppressionFilter">
  <property name="file" value="docs/suppressions.xml"/>
</module>

その参照先となる、別ファイル suppressions.xml を作ります。

<?xml version="1.0"?>

<!DOCTYPE suppressions PUBLIC
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">

<suppressions>
  <suppress checks=MethodNamefiles=“.*Test.java$” />
</suppressions>

<suppress> の checks 属性に対象のモジュール名を指定します。
files 属性に正規表現で対象外としたいファイルを指定します。ここではテストクラスの想定。

通常の CheckStyle でファイル指定する感じで “*Test.java” とか指定すると
実行エラーになるので注意です。

suppressions.xml のパス指定がやっかい

いつもの CheckStyle 設定ファイルに suppressions.xml(ファイル名は任意です)のパスを
指定するのですがこれが厄介者です。
いつもの CheckStyle 設定ファイルかの相対パスで見てくれたらいいものの…

CheckStyle を実行する際の作業ディレクトリかどこかからの相対パスっぽいです。
(きちんと調べてませんが、システムプロパティの ”user.dir” とかだと思います)

なので、ひと工夫が必要です。

<ケース1> Eclipse Check Style Plugin の場合

<property name="file" value=“${config_loc}/suppressions.xml"/>

もしくは

<property name="file" value=“${samedir}/suppressions.xml"/>

という感じで変数を使うことで、いつもの設定ファイルがあるディレクトリパスを指定できます*1
Eclipse Check Style Plugin が ${config_loc}, ${samedir} といった組み込み変数を
用意しているみたいです。

${samedir} よりも ${config_loc} を使っている人が多そうなので、
以降は ${config_loc} を使っていきます。

<ケース2> Maven の場合

Eclipse でチェックできるようになったから、次は Maven でチェックだ*2
という流れで、「mvn checkstyle:checkstyle」するとエラーになります。

${config_loc} は Eclipse Plugin の組み込み変数なので、Maven が知らない変数になります。
Maven として config_loc の変数をセットしてあげる必要があります。

pom.xmlCheckStyle plugin がこんな感じで設定されているとして…

<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-checkstyle-plugin</artifactId>
   <version>2.8</version>
   <configuration>
     <configLocation>${basedir}/config/checkstyle.xml</configLocation>
   </configuration>
   <executions>
     <execution>
       <phase>verify</phase>
       <goals>
         <goal>check</goal>
       </goals>
     </execution>
   </executions>
 </plugin>

タグにひと工夫を加えます。
タグを追加して config_loc という変数をセットします。

   <configuration>
     <propertyExpansion>config_loc=${basedir}/config</propertyExpansion>
     <configLocation>${config_loc}/checkstyle.xml</configLocation>
   </configuration>

これで Eclipse でも Maven でも、
いつもの設定ファイルからの相対パスで suppressions.xml を指定することできます。

「mvn checkstyle:checkstyle」も動くはずです。

参考にしたサイトなど

色々なサイトの情報をつぎはぎしながら解決しました。

補足

・JavadocMethod(メソッドJavadoc 必須チェック)についても同じような感じで
 対象外指定できます。
Eclipse Plugin で提供される GUI で設定ファイルを編集ようとすると、
 一部の設定情報が欠損したりします。直接ファイル編集したほうが早いです。

        • -

私の Eclipse 環境だと、${config_loc} や ${samedir} で置換されるパスが末尾”/"付きになっていたので、実際は
<property name="file" value=“${config_loc}suppressions.xml”/> という設定です。

いつもは Gradle 使いですが、今はお仕事の都合上 Maven 使ってます。

*1:私の Eclipse 環境だと、${config_loc} や ${samedir} で置換されるパスが末尾”/"付きになっていたので、 実際は <property name="file" value=“${config_loc}suppressions.xml”/> という設定です。

*2:いつもは Gradle 使いですが、今はお仕事の都合上 Maven 使ってます。

HTML5プロフェッショナル認定試験の勉強をはじめました

約半年ぶりのブログ。
長らく放置でしたが、最後の投稿から半年しか経っていないのかという感じです。
1年くらい前…な感じです。

HTML5プロフェッショナル認定試験(http://html5exam.jp/)の
お勉強をはじめました。

Why?

HTML5/CSS3 にはもともと興味を持っていて、きちんと使いこなしたい
…というよりもまず、きちんと理解したいという思いが長い間ありました。

そういう資格試験があるんだということを今年に入ったくらいに知って
今年度の会社の目標設定に含めて、勉強&受験しようと思った次第です。

レベル2のためにしっかり勉強しないと…

まずは「レベル1」を早々に合格して(そんなにレベル高くないと踏んでる…)
「レベル2」も今年中か今年度注に受験しようという目論見です。

「レベル1」は問題集が2冊くらいあるので安心ですが、
「レベル2」は問題集もなく、内容もハードそうです。

ということで、しっかり勉強しながら受験に臨まないと「レベル2」は落ちてしまいそう。
色々とサンプルとかも作りながらお勉強しようと思っているので、
ついでにブログにもアップしようという魂胆です。

気づきがたくさん

レベル1の問題集をざっと読んでみましたが、
知っていること半分、知らないこと半分という感じです。

"知らないこと” といっても、
HTML や CSS の仕様を知っていればスマートにできたのに
がんばって JavaScript でガリガリ書いてしまっていたな…
という感じの発見&気づきがほとんどですね。

さいごに

ブログ復活のリハビリも兼ねて、
ちょろちょろとサンプルや気づきをアップしていきます。

HTML5プロフェッショナル認定試験に関するブログは少なそうなので
アクセス数アップも期待できるかも…( ̄ー ̄)ニヤリ

『Web API: The Good Parts』を読んでみた

実務として、Web API(Web サービス)の開発に携わっているわけではありませんが、
Ajax を使用した非同期処理を実装することが多くなってきており、
その場合のサーバ・クライアント間のやりとりをうまく実装できていない不満足感がありました。

エラー発生時のレスポンスの返し方がうまく統制が取れていなかったりしています。
どういう具合に返すのがよいのか理解できていませんでした。
この点について、3章あたりでエラー時の返し方について言及されているので勉強になりました。

サーバ側は Java ですが、Servlet で Web サービスっぽく、JSON を返すようにガリガリ実装しているのですが、
Java API for JSON Processing などを使って、次はうまく作りたいと思っています。

きれいな API の事例を見ていると、気持ちがいいです。


Web API なので、当然 JavaScriptJSON の話が多いのですが、JavaScript はここまで奥が深いのかと驚かされました。
JSONPJSON Padding)とか初耳でした。実に不勉強です。
一方で、発見も多いので JavaScript を勉強するのはおもしろいです。


オライリーの動物本なので翻訳本だと思っていたら、実は翻訳ではなくて、著者が日本人でした。
事例に、楽天や鑑これといった"日本ならでは"なものが出てきます。

また、翻訳版の出版が直近だったとしても、原書は5年も10年も前に出版されていて、
情報が古くて残念なことが多いですが、その点では情報が新しくてよかったです。


次は『APIデザインの極意』も同じような感じでおもしろそうなので読んでみようと思っています。

チームを小さく保つ理由

『エッセンシャル スクラム』の 第11章 開発チーム(197ページ)に次の一節を見つけました。

Mike Cohn は、チームを小さく保つ理由をいかのように述べている。

・誰かがやってくれるから自分はやらなくてもよいという「社会的手抜き」が少ない。
・小さなチームは建設的なやり取りが頻繁に発生する。
・調整に必要な時間が少ない。
・誰も陰に埋もれることがない。
・小さなチームのほうがメンバーを満足させることができる。
・有害な過度の専門化が発生しにくい。

逆説的に考えてみると、
「大きいチーム(≒大規模開発)における弊害」みたいなものが見えてきまして…

「あっ…ウチのことや」と。 (TдT)


それはさておき、使える一節なのでメモメモ。