GAS(GoogleAppsScript)を使ってみる　#006

(また休んでいたため久し振りの投稿…果たして復帰する日はやってくるのか)Oo｡(´-`*)

# 概要
　スプレッドシート出社記録を付けているのだが、この表何と手作り(* ´艸｀)ｸｽｸｽ
無くなったら新たに作成するのですが、、、（コピペと日付直しと祝祭日のセルカラー変更と～などちまちました操作が必要）

面倒なので自動化します！(`・ω・´)

…というのが[#001](https://qiita.com/koichiro-h/items/6ae372bade13f1ca889e)から続けてきた事です。前回[#005](https://qiita.com/koichiro-h/items/521501302558e112efba)はメタプロ的に（と言っても固定値ですが、、、）HTMLを生成出力してユーザプロンプトから予定出社時間と予定退社時間を受け取るという事を、[HTMLService](https://developers.google.com/apps-script/reference/html/)を利用して実現しました(`・ω・´)

---

# 課題
　今回は総まとめとして、コード全体のリファクタリングを行います(`・ω・´)
前記事にも書きましたが重複コードやべた書きなど色々とイケてないので、（まあべた書きはAfterでも残ってるんですけどね…）せっかくだからオブジェクト指向寄りに書き直しました。（もっとこうした方がよいとかここは違うんじゃないかという暖かいご指摘お待ちしております。）

リファクタリングのため実行結果は「基本的に」変わりませんので割愛します。
なお、説明の都合上まとめて掲載していますが、何度かトライ＆エラーして仕上げています。

---

# 設計
## 1. クラス化の検討
　全体の振る舞いから、まずは「日付的なものをアレコレするクラス」を作り「シート的なものをアレコレするクラス」から処理を分離することを検討しました。

▼シート的なものの振る舞い
> ・printFormatHoliday…新たなカレンダー領域の祝祭日部分の装飾をする
> ・printFormatOfWeek…新たなカレンダー領域を装飾する
> ・printDate…新たなカレンダー領域に日付を出力
> ・getLastDate…シート内で使われている日付っぽい文字列から最後の日を取得

▼日付的なものの振る舞い（新規）
> ・next…翌日をセットするメソッド。
> ・previous…前日をセットするメソッド。
> ・get…保持している日付型を返す。
> ・getDay…保持している日付型に応じた日本語曜日を返す。
> ・set…日付を保持する。この時に日本語曜日と祝祭日判定結果をインスタンスメンバとして保持する。

▼その他
> ・setPlanTime…予定出社時間と予定退社時間をセットする

## 2. 非効率なコードの最適化
　続いて、重複した線形処理（特にprintFormatHoliday）を解消するためfindRowメソッドとfindColumnメソッドを実装します。
 
▼シート的なものの振る舞い（追加）
> ・findRow…対象の範囲から、指定された文字行を検索して返す。
> ・findColumn…対象の範囲から、指定された文字列を検索して返す。

　更に、都度GoogleCalendarに祝祭日を照会するのではなく日付的なクラスインスタンスメンバとして保持・再利用するためのメソッドを準備します。実際に値を保持するのは日付的なクラスのsetメソッドで実装します。

> ・setDate…シート的なインスタンスの配列メンバに、日付的なインスタンスをpushする。
> ・classifyHoliday…シート的なクラスが保持する7日分の日付的なインスタンスから検索した列を、平日配列と祝日配列に振り分ける。
> ・getHolidayColumns…祝日配列をRangeListとして返す。
> ・getOrdinarydayColumns…平日配列をRangeListとして返す。

これらをまとめ、次のような構想とする。

---

# ドキュメント
## クラス図
![class図.png](https://qiita-image-store.s3.amazonaws.com/0/136977/9f8b98bb-af9c-1002-b9a3-78e1b642f100.png)

---

## シーケンス図（main処理）
![Sequence図（main）.png](https://qiita-image-store.s3.amazonaws.com/0/136977/3b473e87-a406-4d5a-2959-7f6a8fc6916e.png)

---

## シーケンス図（setPlanTime処理）
![Sequence図(setPlanTime).png](https://qiita-image-store.s3.amazonaws.com/0/136977/e596ba72-3ad8-6bd1-ea25-ae5511ce94d4.png)

---

# 特記事項
* mcTableインスタンスは、デザインパターンでいうFactoryMethod的なmcTableFactoryにより生成される。
* mcTableインスタンスのdecorateメソッドはデザインパターンでいうTemplateMethod的（抽象設計ではないため厳密に言えば違う）な振る舞いとして定義した。
* GASではclass構文はシンタックスエラーとなった。
* メソッドのスコープはあまり深く考えていない。
* テストパターンも網羅していないし単体テストの入れ込みも中途半端。
* プリミティブなべた書き部分もクラス化しようか迷ったがそのままにした。
* シートがゼロからでもシステム日付から表を作成出来るようにした。（その週から始まる）

---

# 終わりに
　#002くらいで完結するつもりが延ばしに延ばして#006までのシリーズ物になりました(^q^)
成果物がどこまで使えるものかは（利用頻度を鑑みても）疑問ですが、勉強や練習としては良い材料だったと思います。またGsuite関連で自動化記事書きたい。
　
ソースは[git](https://bitbucket.org/kh_private/makecalendarformat/src/master/)で公開しています(^q^)

## GAS(GoogleAppsScript)を使ってみるシリーズ一覧
\#001. [Calendar.getEvents(startTime, EndTime)の挙動がおかしい報告](https://qiita.com/koichiro-h/items/6ae372bade13f1ca889e)
\#002. [リハビリ出社記録表作成支援ツールの総括](https://qiita.com/koichiro-h/items/5391362cba0d103cbf67#_reference-58f207f493fffb992a13)
\#003. [トリガーの失敗例とソース修正](https://qiita.com/koichiro-h/items/ee273608f9d529eb105f#_reference-121516ea3f462ea13b28)
\#004. [セルの書式設定の細かいお話](https://qiita.com/koichiro-h/items/aa6c1e37fd51f671aa89#_reference-e5dd43fb30505570b1e8)
\#005. [jQueryとTimePickerをユーザプロンプトとして出力するお話](https://qiita.com/koichiro-h/items/521501302558e112efba#_reference-818310df9326a6fe6b56)
\#006. [リファクタリングとクラス設計のお話](https://qiita.com/koichiro-h/items/18e15eb383b4f7a8b08b)

ご購読ありがとうございました。m(__)m