DT Blog

catch-img

Aras Innovatorを使ったより良いコーディングの方法とサンプル紹介

この記事では、Aras Innovatorを使った、楽しい開発をするためのより良いコーディングの仕方とリファクタリング手法を紹介します。内容は主にプログラム開発者向けです。


目次[非表示]

  1. 1.はじめに
  2. 2.前段:メソッドの仕組みについて
  3. 3.メソッドやクラスの作成
  4. 4.リファクタリングのコツ
    1. 4.1.サンプル①「出口はどこだ?JavaScriptコードのクリーンアップ」
    2. 4.2.サンプル②「文字列がBooleanの想定であればbool型を使う」
    3. 4.3.サンプル③「リファクタリングは影響範囲を整理するのに便利」
    4. 4.4.サンプル④「変数が多すぎてトレースが大変なとき」
  5. 5.メソッド化の必要性とメリット
  6. 6.メソッドの再利用とその方法について
  7. 7.クライアントメソッドからの呼び出し
  8. 8.まとめ


はじめに

開発者の皆さん、プログラム開発は楽しく進んでいますか?もし、業務仕様に関係なく、コードを理解するのが難しい、または判定処理で混乱して思い通りに書けないなど、実装に苦戦してしまい楽しさを感じにくい場合は、より良いコーディングの仕方を学ぶことで、複雑な処理をシンプルに変え、楽しいコーディングができるようになるかもしれません。便利なAPIの活用や、リファクタリング方法を見ていきます。
リファクタリングとは、既存のコードを理解しやすく、効率的で保守しやすい形に改善することです。
コードを理解しやすく改善するため、実装中にリファクタリングを行います。
リファクタリングは、手本を見て理解し、「自分でコードを書いてみる」ことで初めて習得できます。
簡単なことではありませんが、習得することで何倍もの高い生産性と問題解決するスキルが得られます。
より良いコードを書きたい方はぜひご覧ください。



前段:メソッドの仕組みについて

リファクタリングに入る前に、Arasのサーバーメソッドの仕組みを確認しておきましょう。

サーバーメソッドでは普段、 return this; や newResult, newError を使って返却していますが、サーバーメソッドがどのような仕組みで動いているのか気になったことはありますか?

 
サーバーメソッドの設定はコードツリーの中に入っています。
※Arasでは、Aras Innovatorがインストールされた環境のフォルダ構成をコードツリーと呼んでいます。
Innovator/Client/Solutions は開発者が自由に使って良いフォルダです。
それ以外は開発環境の管理者と調整して、一部の設定変更を加えることができます。
サーバーメソッドのテンプレート定義を行っているのが下記のファイルです。

「Innovator/Server/method-config.xml」


このファイルの詳細は公式ドキュメントのプログラマーズガイド(Programmer's Guide.pdf)に記載されています。
 
サーバーメソッドがC#の場合で、method-config.xmlの要点を説明します。
・ReferencedAssembliesにはサーバーメソッドが参照するDLLの設定があります。
・外部DLLを使ったカスタマイズが必要な場合に追記を行います。
・Supportタグ はサポートしているテンプレートの種類を表しています。
・<Template>タグがあるので、name=”CSharp”の中身を見に行きます。

注目して頂きたいのは $(MethodCode) の部分です。
 
勘の良い方は気がついたかもしれません。実は$(MethodCode)の部分が、メソッドのメソッドコードに置き換えられ、C#のクラスファイルとして生成されます。
 
下記のイメージです。

Item型を継承しているクラスのため、 this.getInnovator() などが利用できます。
戻り値が必要な理由もmethodCodeというメソッドの閉じタグの前にあるためです。
この構造を応用して、メソッドやインナークラスの定義ができます。
 
下記の画像は、 private void Dummy(){ } メソッドが追加されました。

このようにメソッドが利用できるため、コード量が多く冗長なコード、複雑な演算、大量の変数が作成されることを回避できます。
※「(C#7以降)ローカル関数」を利用することでもコードの整理は可能です。
※メソッドをpublicにしても、別のMethodアイテムから直接、メソッドやインナークラスの呼び出しはできません。(メソッドアイテムから別メソッドアイテムは、applyを使い、結果を受け取るのみ可能です)



メソッドやクラスの作成

前段でサーバーメソッドはメソッドやクラスが使えることを確認しました。
さて、メソッドやクラスが作れると何が良いでしょうか?
 
業務ロジックが複雑化すると、ループや判定が必然的に増えてきます。
その状態でDB取得、分岐処理、繰り返しをフラットなコードで書き続けていると、非常に書くこと、読むことが負担に感じてきます。

そこで、メソッドやクラスを使うことにより、文脈が意味を持ち、どんな処理を行っているのか素早く判断できるようになります。例えば下記の例はクラスを使った場合です。

メソッドアイテムごとにメソッドやクラスを複数定義できるため、機能を整理することが可能になります。
 
【注意事項】
メソッドの直後に、フィールド変数の設定も可能ですが、キーワードになりそうな用語や、多すぎる設定はおすすめしません。理由は2つあります。
・1つ目は将来的にAras Innovatorのバージョンアップでフィールドやキーワードが増える可能性がゼロではないことです。競合した場合アップデートが大変になるので、適切な名前付けを行ったほうが無難です。
・2つ目はコード全体が読みにくくなるためです。

例えば下記のコードは悪い例です。変数がどこで設定され、どこで変更されたのかすぐに判断できるでしょうか?

InitDataで確実にフィールド変数が設定されるのか、あるいはUpdateItemの後で変数の更新が行われていないか、コード全体を見て判断する必要がありそうです。
機能追加のタイミングでフィールド変数を参照した際に、初期設定されておらずエラーが起きる、といった事象も稀に見かけることがあります。特に複数人で作業する場合、確実に初期化され、設定のタイミングがわかるように構造を変えたほうが安全です。
※メソッドの直下にフィールド変数を作るのではなく、インナークラスを作り、コンストラクターの引数に値を渡してやると、クラス内で完結するためわかりやすく作れます。



リファクタリングのコツ

これからいくつか悪いコード例(NG例)と良いコード例(リファクタリング後)のサンプルを紹介したいと思います。

サンプル①「出口はどこだ?JavaScriptコードのクリーンアップ」

ここではJavaScriptのコードを取り上げます。
具体的には、クライアント画面のコマンドバーボタンの初期化イベントの動作部分です。
このコードは少し違和感がありませんか?
一見してどこでループを抜けるのか判断しづらい構造になっています。

 
変更前:NG例 

この処理は画面表示中のタブに応じてスタイルを変更する処理でした。リレーションシップタイプ名に該当しない場合、コマンドバーボタンは非表示になり、後続のスタイル調整は行わずに処理が終了します。この処理で違和感があるのが、該当しない場合(defaultのとき)にreturnしていることです。
一見して処理を見落としやすいため、改善が必要です。
リファクタリングを行います。


リファクタリング後

リファクタリング後は、ファンクションによってどの処理に対して返却しているのかわかりやすくなり、可読性が向上しました。ロジックは依存度が少ないほど理解しやすいので、このリファクタリングによってコードの品質を向上させることができました。ちょっとした修正でメンテナンス性を高める事が可能になります。
 
この例ではファンクションの戻り値がstringでしたが、もし複数返却したい場合は、戻り値をオブジェクト型({value1: ‘A001’, value2: ‘B001’ }など)で返却しても良いと思います。
C#の場合も似たようなやり方です。また前述のフィールド変数を使う場合でも、どこかのメソッドの中で突然設定するのではなく、 GetInitData() のようにオブジェクトを受け取る書き方であれば、影響範囲の特定がわかりやすくなります。


サンプル②「文字列がBooleanの想定であればbool型を使う」

true/falseだけを判断するのであれば、bool型を使ったほうが読みやすくなります。
文字列のままだと目視での判別が難しくなります。
if文で”1”や”0”で判定すると忘れやすいため、事前にtrue/falseへ変換すると良いです。
これがわかりやすいと感じれば、すぐにでも実践できると思います。


サンプル③「リファクタリングは影響範囲を整理するのに便利」

次のコードを見比べてみてください。
コードはかなり省略してありますが、ドキュメントのマージ処理とPDF変換処理が書かれています。変換前に対象ファイルの判定をしています。
変更前のコードで16行目~23行目までが何を行っているか、瞬時に判断できますか?
(※画像が小さい場合は右クリックで新しいタブで画像を開きご覧ください)
変更前はコードをしっかり読まないと何をしているか判断しにくいですが、リファクタリング後は文脈から何を行っているのか素早く判断できます。
そうすることで、今後の保守でどこを修正するべきか素早く判断できるようになります。


コードを書き始めるときに、文脈をコメントに書き出し、メソッドを作成してから取り組むか、一通り機能を作ってからメソッドに集約するか、やり方は人それぞれです。
※経験が浅い状態で、どこから書き始めたら良いかわからない場合は、まずは処理させたいことをコメントに書き出し、そのコメントをメソッド化にして、その後メソッドの中身の作成に取りかかると、処理したい内容に集中できるので比較的作りやすいかもしれません。


サンプル④「変数が多すぎてトレースが大変なとき」

Aras Innovatorはパラメータが自由なため、変数が多くなりがちです。
また、ItemのApply(DB処理)でデータを取得した後に判定、新しい条件検索が何度か出現すると、設計書の処理フローはシンプルなはずが、難解なコードが書かれている場合があります。
下記の例は変数が多く、判定もわかりにくく感じる内容です。

変更前:NG例

判定が多く、その後も処理を書き続ける場合は、少し見直しをかけるとわかりやすくなります。
先程のメソッドの工夫の書き方のように、リファクタリングを行ってみます。
今度は、メソッドの名前からなんとなく処理内容をイメージできますか?
直感的にわかることが、コードを早く読めるようになるコツになります。


リファクタリング後

クラスのプロパティへ値をマッピングすると、Item型よりも自由度は減りますが、確認したい値が明確になるため、適切な判定が可能になります。

※パラメータはコンストラクターで渡す場合とnewのタイミングで設定する場合あります。状況に応じて変更します。この例ではコンストラクターで設定しています。


カスタムクラスのメソッドで判定を作れるため、処理に集中できます。
必要な処理内容を必要なときだけ読むことで読むスピードが向上します。
例えば保守担当者が「開始日から完了日までの期間を1ヶ月以内とする」、という処理を追加したい場合、クラス化されていれば、影響範囲を特定しやすく、その周辺のコードを集中して調査、改修ができるようになります。
 
コードをメソッド化できそうだと思ったら実践してみましょう。



メソッド化の必要性とメリット

以前開発メンバーから「一度しか使わない処理はメソッド化の意味があるのか?」という質問を受けたことがあります。一度しか使わない場合でも、私は次のメリットがあると思っています。
 
1.可読性の向上
・メソッド化されていると目的が明確になり可読性が向上する。
2.保守容易性
・モジュール化されているので修正が容易になる。
・仕様変更が必要なとき、メソッド一箇所の修正で良くなる。
3.コードの再利用性
・類似の処理を探しやすくなり、再利用しやすくなる。
 
開発者はコード書く時間よりも、コードを読む時間のほうが多い傾向にあります。
私は文脈で読めたほうが問題箇所の把握と読む時間が短くて済むため嬉しいと感じます。
リファクタリングは開発時に少し努力しておくと、改修や保守担当者の調査時間の短縮に繋がります。



メソッドの再利用とその方法について

実装する機能によっては、同じ処理を再利用したい場面が出てきます。
これを他のメソッドでも使いたい場合、いくつかの方法があります。

状況に合わせて、作りやすい方法で対応します。
今回おすすめしたい「c.別メソッドを呼び出す」の例をいくつか記載します。
 
別メソッドを呼び出す場合も、いくつかパラメータの受け渡し方があります。
 ・IOM(Item型)を使い、setPropertyやsetAttributeを使って値を渡す。
 ・applyMethodのように、引数のXmlNodeを文字列で渡す。
コードの読みやすさ、流用のしやすさを考えると、IOMを利用したほうが便利です。
以下でその理由を解説します。
 
ここではapplyMethodで引数が多すぎる場合を悪いコード例とします。

NGの理由:読みにくい。閉じタグを間違えやすい。XMLタグのエスケープが必要。


IOMを利用した場合

結果:読みやすい。XMLタグのエスケープが不要。流用しやすい。

呼び出し方一つでも保守負担を軽減できますので、IOMの利用をおすすめします。
 
なお、JavaScriptでも同じような書き方で表現できます。
JavaScriptの場合、 applyMethod は戻り値の動作が異なるため、JavaScriptもIOMのapplyを利用したほうが学習コストも少ないのでおすすめです。



クライアントメソッドからの呼び出し

最後にJavaScriptのAPIをいくつか紹介します。
 
▼ クライアントからサーバーメソッドの呼び出し
1.「aras.applyMethod」は、アラートエラー又はResultのBody文字列が返却されます。
おそらく古い書き方で、IOMオブジェクトが戻り値ではありません。コマンドを実行してOKまたはNGのような使い方をするときに利用するものだと考えられます。
 
2.「aras.IomInnovator.applyMethod」は、C#と同じようなIOM形式の書き方になります。
 
3.下記はどれも同じ意味になります。
※プロジェクトでよく使われている方式に合わせることが良いです。
 
//① よく利用しています。(これを覚えておくと作りやすいです)
var query = aras.newIOMItem("Method", "サーバーメソッド名");
 
//② innovatorを経由した場合 C#と同じような書き方ですがinnovator変数が必要です。
var query = inn.newItem("Method", "サーバーメソッド名");
 
//③ new Itemの利用状況はnewIOMItemの1/10くらいでした。
var query = new Item("Method", "サーバーメソッド名");
 
▼ クライアントイベントの再利用に関する手段
余談ですが、JavaScriptから別のJavaScriptのメソッドを呼び出すことも可能です。
次のAPIで実現できます。既存コードの利用状況を見てみるのも良い習得方法です。
aras.evalMethod('クライアントメソッド名', inDom, inArgs);
// inDom, inArgsはオプションです。戻り値も受け取れます。
// inDomはitemノードまたはxml文字列
// inArgsはオブジェクトが可能



まとめ

何かひらめきを感じましたか?
書き方を工夫することで複雑な処理もシンプルに作り上げることができます。
リファクタリングを習得すると影響度を考慮する力を養い、徐々に広いスコープで物事を考えられるようになります。今回触れませんでしたが、単体テストも行いやすくなります。できることが増え、これらを積み重ねていくことでより楽しくなってくると考えています。
 
プログラム開発は、製品をリリースしてから数年間に渡って保守が行われるのが一般的です。経験上、悪い例のコードは、運用後にトラブルが発生しやすく、わかりにくいコードは保守担当者をとても悩ませることになります。そうならないためにも、開発者は仕組みを理解し、リファクタリングしてコード品質を保つことが重要です。そうすれば将来的な改修にも耐えられるようになります。
製品を安定動作させることや、アップデートが企画通りに進むことは顧客満足度向上の重要な鍵となります。
 
開発者一人ひとりがこれらを意識して作っていくことで、自分自身の技術力の成長、そしてプロジェクトへの貢献、関わった製品を積極的に育てたいという愛着が湧くのではないでしょうか。
より品質の高いコードを目指して実践していただければ幸いです。

神田
神田
部署名:アドバンストテクノロジー2部

おすすめ資料はこちら

Aras Innovator開発支援ソリューション

Aras Innovatorは、オープンアーキテクチャ・サブスクリプションモデルのPLM (Product Lifecycle Management)ソリューションです。Aras Innovatorの技術力を最も効果的に発揮できるシチュエーションを創造し、ユーザー視点に立って提案・対応致します。

CONTACT

社内システムのお悩みを私たちだけで解決へと導きます

ご不明な点はお気軽に
お問い合わせください

お役立ち資料は
こちらから

おすすめ資料

Aras Innovator開発支援ソリューション

メルマガ登録

人気記事ランキング

タグ一覧