[GAS]オブジェクト指向によるGAS開発のススメ #4クラス設計のコツ

GAS

どうも。つじけ(tsujikenzo)です。このシリーズでは、2021年9月から始まりました「ノンプロ研GAS中級講座6期」について、全7回でお届けします。最終回の7回目を、5回に渡ってお送りしています。いつ終わるのか。。

前回のおさらい

前回は、「内部設計・コーディング・テスト」をお届けしました。

[GAS]オブジェクト指向によるGAS開発のススメ #3内部設計・コーディング・テスト
どうも。つじけ(tsujikenzo)です。このシリーズでは、2021年9月から始まりました「ノンプロ研GAS中級講座6期」について、全7回でお届けします。最終回の7回目を、5回に渡ってお送りしています。それって、全12回じゃないのでしょ...

今回は、4回目で「クラス設計のコツ」です。

最近、個人的に、「こうやって書けば、すこし業務アプリケーション開発が楽になるかもしれないなぁ」と、思う書き方があります。

今日はそんな、「オブジェクト指向(っぽいもの)」という手法を取り入れながら、プログラミングしていきます。

今日のアジェンダ

  • 引数にオブジェクトを取る
  • インスタンスの役割

引数にオブジェクトを取る

クラス化のさいに、「処理の共通化をさせよう」という想いが強くなればばるほど、自然と引数は多くなります。

なんにでも対応できるように、引数を配列でもたせたりしてしまうこともあるでしょう。

/** GmailDraftクラス */
class GmailDraft {

  /** メールの下書きを作成するためのコンストラクタ
    * @constructor
    * @param{Array} string
    */
  constructor(personArray) {
    const [name, toAddress, ccAddress, subject, body] = personArray;
    this.name = name;
    this.toAddress = toAddress;
    this.ccAddress = ccAddress;
    this.subject = subject;
    this.body = body;
  }

}

オブジェクト指向プログラミングの特徴は、オブジェクト同士が作用しあうという点です。  出典:[GAS][DDD]1章オブジェクト指向とはなにか

たとえば、GmailDraftが生成するインスタンスは、1件のGmailメッセージになるのが自然でしょう。 

toAddressやccAddressは、インスタンスによって条件分岐したいところです。

営業部に所属するスタッフが、日報を提出する先は、営業部の管理職ですし、製造部なら、製造部の管理職に送信したいです。

これまでの手続き型プログラミングでは、この条件分岐を、if文で書いていました。

/** GmailDraftクラス */
class GmailDraft {

  /** メールの下書きを作成するためのコンストラクタ
    * @constructor
    * @param{Array} string
    */
  constructor(personArray) {
    const [name, team, ccAddress, subject, body] = personArray;
    this.name = name;
    this.team = team;
    this.toAddress = team === '営業部' ? 'eigyoMG@gmail.com' : 'seizoMG@gmail.com';
    this.ccAddress = ccAddress;
    this.subject = subject;
    this.body = body;
  }

}

しかし、if文は、コードの変化に弱く、可読性を下げる原因のひとつです。

できるだけクラスでは、if文は書きたくありません。

インスタンスの役割

Aさんが営業部に所属しているなら、その状態は、Staffクラスのインスタンスが持っているはずです。

これは、コロコロ変わるものではありません。

インスタンスの状態を、プロパティにもつか、メソッドにもつかは、ときとばあいによりますが、プロパティはあまり増やさない方がいいです。

ここではあくまで例として、「所属」をプロパティに持たせてみました。

/** Staff情報を取り扱うクラス */
class Staff {

  /** コンストラクタ */
  constructor(staffName) {
    this.staffName = staffName;
    this.team = this.getTeam();
  }

  /** スタッフシートのRecordsから、所属チームを返すメソッド
   * @return{string} 所属名
   */
  getTeam() {
    const records = this.getStaffSheetRecords();
    const filter = records.filter(record => record['名前'] === this.staffName)[0];
    const team = filter['所属'];
    return team;
  }


  /** 日報提出先のメールアドレスを返すメソッド
 * @return{string} メールアドレス
 */
  getTeamManagerAddress() {
    const records = this.getStaffSheetRecords();
    const filter = records.filter(record => record['名前'] === this.staffName)[0];
    const mail = filter['管理者アドレス'];
    return mail;
  }


  /** スタッフシートのRecordsを返すメソッド
   * @return{Array} 連想配列形式のrecords
   */
  getStaffSheetRecords() { }
}



/** TEST関数 */
function testStaff() {

  //インスタンス生成
  const staffName = '辻健蔵';
  const s = new Staff(staffName);

  //所属を確認
  console.log(s.getTeam); //営業部

  //日報のメールアドレスを確認するメソッド
  console.log(s.getTeamManagerAddress()); //eigyoMG@gmail.com

}

なので、このように、GmailDraftクラスに、Staffクラスのインスタンスを渡すと、if文が消えます。

テスト関数のインスタンスの生成と、GmailDraftクラスのコンストラクタに注目してください。

/** GmailDraftクラス */
class GmailDraft {

  /** メールの下書きを作成するためのコンストラクタ
    * @constructor
    * @param{Object} Staffクラスのインスタンス
    */
  constructor(obj) {
    this.obj = obj;
    this.name = obj.staffName;
    this.team = obj.team;
    this.recipient = obj.getTeamManagerAddress();
  }

}


function testGmailDraft() {

  //Staffクラスのインスタンスを生成
  const staffName = '辻健蔵';
  const tsujike = new Staff(staffName);

  //GmailDraftクラスのインスタンスを生成
  const g = new GmailDraft(tsujike);
  console.log(g.name); //辻健蔵
  console.log(g.team); //営業部
  console.log(g.recipient); //tsujike@gmail.com

}

もしクラス内で、if文を書かなければならないような状況になったら、コンストラクタや、インスタンス生成時の引数を見直してみましょう。

PDF、Gmail、LINE、Slackなどのクラスは、生成したいコンテンツを(できるだけオブジェクトで)引数に取るとよいでしょう。

まとめ

以上で、「クラス設計のコツ」をお送りしました。

いままで、コンストラクタに渡す引数は、文字列型や配列が多かったかもしれません。

しかしこのように、コンストラクタの引数にオブジェクトを渡すと、一気に新しい世界が待ち受けています。

次回は、 最終回で 「シートクラス」 をお届けします。

このシリーズの目次

[GAS]オブジェクト指向によるGAS開発のススメ

  1. 要件定義
  2. 外部設計
  3. 内部設計・コーディング・テスト
  4. クラス設計のコツ
  5. シートクラス
タイトルとURLをコピーしました