JIRAプラグイン開発方針のまとめ

業務上JIRAプラグイン開発をやっているので、その所感を開発方針という形でまとめてみました。

開発の課題と方針

Atlassianはプラグイン開発についてサポートしないし、公式のドキュメントも充実していない。おまけに、コミュニティも当てにならず、Stack Overflowでお目当てのソリューションを探すこともままならない。そのため、MarketPlaceに上がっているようなリッチなプラグインを開発しようと思えば、独自にフレームワークの解析を行う必要がありかなりの研究コストがかかってくる。おまけに、プラグイン開発で必須なコンポーネント及びモジュール群の機能についても知っておく必要があるので開発要員の学習コストもそれなりにかかる。

このように開発においてかなりの苦労が要求されますが、それでもなお自社の業務仕様に合わせてJIRAを拡張したいという需要はあります。そこで、プラグイン開発する新人向けに開発方針をまとめました。

方針1: リソース管理はREST APIを使う

JIRAのリソースと言ったらユーザ情報やプロジェクト・タスク情報。これらの管理はREST APIで十分です。主だったリソースはREST APIで取得・更新・削除できます。またJQL(JIRA Query Language)を利用すれば、条件に似合ったissue情報を好きなように取得することもできます。自社システムとの連携についてはこれで十分。あとマスタ管理であれば、JIRAのプラグインを作成するよりも別途システムを構築した方が製造及び拡張が容易です。

方針2: 主要なコンポーネント及びモジュールを押えておく

プラグイン開発のメリットは、JIRAのコンポーネントとモジュールを活用して自社の業務仕様に合わせJIRAの機能を拡張できる点です。中でも以下のコンポーネントとモジュールは使用頻度が高く、これらだけ覚えても有用なプラグインが作成できます。

ActiveObjects

独自のDBテーブルを生成します。他システムのマスタデータを取り込むときなどに使います。

EventListener

あらゆるイベントに対応する処理を付加します。

各種Manager系

IssueManagerやUserManagerなどリソース管理を行うコンポーネントです。リソース管理だけならREST APIで十分ですが、他のコンポーネントやモジュール上からリソース管理を行うなら必須です。

REST Plugin

独自のREST APIを生成します。JIRAの画面はフレームワークの制約が大きく、画面上のイベントからサーバ処理を行うにはREST APIを通じた非同期通信しかありません。そういう意味ではプラグイン開発必須のモジュールです。よくActiveObjectsとセットで利用されます。

各種Workflow系

JIRAの最大の利点といえば強力なWorkflowをおいて他にありません。WorkflowモジュールにはConditionとValidator及びPost Functionがあり、要望に応じて柔軟に拡張できます。

方針3: 画面作成は極力行わない

AtlassianにはAUIというフロントサイドフレームワークがあります。AUIにはAtlassianらしいデザインを作成するためのCSSと、Atlassianらしいモーションを実現ためのAJSが含まれます。AJSは単なるjQueryのラッパーではなく独自の関数やオブジェクトも含みます。使いこなせば有用なんですけど、ただでさえ学習コストの高いプラグイン開発のレベルを更に一段高くしてくれます。おまけに、フレームワークに従順するように開発する必要があるため、「あのページにコレ入れて」とか無闇に容認すると実現できずに失敗することになります。一見簡単そうに見えて複雑なのがフロントサイドです。

画面に対する要望は対応しないのがベストです。クライアントにはAtlassianの仕様についてよくよく理解してもらう必要があります(簡単そうなだけに)。それでも画面を作成するというなら、リスクを洗い出した上でその旨をクライアントを合意、後々もめないような手筈を整えておいてください。

最後に

開発できる仲間募集してます。

情熱プログラマー書評「新人の頃に出会いたかった本」

ITエンジニアのお勧めで何度か耳にしていた書物情熱プログラマー ソフトウェア開発者の幸せな生き方」がAmazon Japanで電書化されていたので、早速通読しました。以下その書評です。

新人始めプログラマー皆さんへお勧め

社会へ出たてでまだまだ仕事の要領が掴めない新人プログラマーには打ってつけでしょう。堅い言い回しや哲学的な内容も無い、業務知識もそこまで必要としないので結構理解できるはずです。特に、「今すぐ始めよう」の文章について一度は実践してみてください。「良かったなぁ」で終わるのでなく、今すぐ実践のためのスケジュールを作成することが肝心です。

また、日々の忙しさから自らの研鑽を忘れてしまった社会人にとっても気づきと反省を与えてくれます。皆さん一度は通読して損はありません。

例えがくどい、所感や体験談が長い

文章中でサックスやジャズの例えをよく出してくるのですが、共感できるのは一握りの人だけでしょう。書物は著者の言葉で率直に書くものなので仕方ないのですが、正直くどいです。また、文章は所感や体験談が大部分を占めています。話があっちこっち行ったりしているので、個人的には小見出しつけて分かりやすくして欲しかった。後半は「今すぐ始めよう」だけ読んで何が言いたいのか判断していました。

お勧めの読み方

まずは目次を見て、気になる題目から読み始める。全体を通読するのであれば、「今すぐ始めよう」の文章を読み、その内容の経緯が気になったら導入部の文章を読もう。

メモ書き

私の本書に関するメモ書きを一部公開します。

 本当の意味で何かを習得しようと思ったら、誰かに教えてみることをお勧めする。 (師匠になる 第48頁)

要は習得した内容を自分のものとすることです。自分のものとするにはまず整理する。整理するためには実際に教えるということは最適です。

僕らの業界でも、もっと練習する時間が必要だ。 (一に練習、二に練習 第50頁)

「プロとは、クライアントの要望を実現できる技量を有し、その上で実現可能な案を提示すること」というのが私の持論です。技量は練習でしか身につかない。時間が無い?なら今すぐスケジュールを調整するしかない。1日1時間なら余裕で作れるでしょ。

君がいつも繰り返しコーディングしている処理を1つ選び、その処理に関するコードジェネレータを作成してみよう。 (自動化によって仕事を確保する 第62頁)

プログラマーとして楽することに投資を欠かさないこと。

つきに一度は約束の達成率を調べて、自分の約束の仕方が適切かどうか確認しよう。 (できないことは「できない」とはっきり言う 第99頁)

まずは自覚する事、そして改善する事が重要。

例外処理への考察からTupleでエラーを返すまでの経緯

今まで外部委託のソースコードをレビューしてきたけど、大体が例外の処理を正しく出来ていない。キャッチしながらもスルーするのはほんのご愛想、中には正常処理の一部として利用しているなんていう酷いものもある(他システムへの命令で例外が発生したのに、あたかも正常処理として扱われていた。何を言っているのか(ry)。ここは「そもそも例外処理は何なのか」を振り返る必要があるということで書き出してみました。ちなみに例外処理をディスる気持ちはありません。一応メリットも挙げていますしね。

例外処理って何なの

例外処理 - Wikipediaより以下引用します。

例外処理(れいがいしょり)とは、プログラムの上位の処理から呼び出されている下位の処理で継続不能、または継続すれば支障をきたす異常事態に陥ったとき、制御を呼び出し元の上位の処理に返し安全な状態になるよう回復処理をすること。その際に発生した異常のことを例外と呼ぶ。

全くその通りなんですが、要は「処理が続けられないですよ」ということ。それを無視したり、あまつさえ正常処理として利用するなんざご法度です。

例外処理のメリット

恒常的にあるはずのファイルがなぜか消えていた、ファイルの権限が書き換わりアクセスできない、相手先サーバが落ちて接続できない、データベースに接続できない、といった理由で一連のトランザクション処理を飛ばしたいといったときには例外処理が適してます。この場合、業務ロジック中(ここでは業務手続き処理の意)ではキャッチせず、フレームワーク側でキャッチするのが正しいでしょう。ただし、データベース処理のロールバックについては業務ロジック中に記載が必要ですけどね。

例外処理のデメリット

そもそも例外処理は扱い難いです。その理由として、プログラマ側としてはどこで例外をキャッチすべきかという設計センスが必要になること、レビュアー側としては処理を一気に飛ばされるため手順通りに追えないことがあります。特に例外のキャッチ場所については要注意、下手するとGoto文の再来です。そもそも手順をかっ飛ばして別のセンテンスに移るのは本来害悪でしかありませんから。

例外処理に代わるエラーの代替処理

エラーを戻り値として戻す方法があります。Golang関数型言語のEitherなんかが良い例です。例えば、業務上起こりえるエラーで尚且つ処理を続けるための代替手段がある場合については、やはり戻り値として返し、プログラマ側で意図的に処理してもらうのが一番でしょう。直近では、入力値が不正、ユニークなデータレコードが既に存在している、ユーザのデータアクセス権限がないという異常処理についてはこの方法が適していると思います。

私はGolangを見習い、業務上起こりえて尚且つプログラマにきちんと処理してもらいたいエラーについてはTupleを利用して返すようにしています。それをプログラマがどのように処理するかは勝手です。例外を発生させるでも良し、無視を決めるでも良しです。もちろん、レビューした上で意図を詰めるつもりですけどね。

総括

エラー処理も需要に合わせ多様になっても良いかと思います。Golang関数型言語のEitherの中で返り値として渡すのは良い傾向ですよ。