Google App ScriptをTypeScriptとClass構文で書く - 環境導入

  1. 1. TL;DR
  2. 2. なんでやるの?
  3. 3. 開発環境
    1. 3.1. Linterとフォーマッターを導入する
      1. 3.1.1. ESLintでTypeScriptにLintをかける
      2. 3.1.2. ESLintにPrettierも組み込む
      3. 3.1.3. もっと細かい設定
    2. 3.2. 型定義の導入
      1. 3.2.1. GAS用ライブラリの型定義

GASは本当に手軽で便利。ほんのちょっと自動化したい、でもDB立てて、サーバー立ててまでやるのもなぁ、ってときにその溝を埋めてくれる良いところに収まってる感じがしますね。特にGoogleスプレッドシートとの連携もしやすいからスプシを簡易DBとして見たててやるとけっこういろいろできちゃう。

そんな感じで職場の社内ツール的なものをGASで作ってたりするんですが、昨年後半にClasp経由でTypeScriptがサポートされたのでちゃんと書きなおしてみました(以前はWebpackでやっていました)。それが一段落したのでせっかくなのでその知見をご紹介しようと思います。

書いてたら長くなってしまったので、いくつかに分けます。まずは環境構築から。

TL;DR

  • GoogleAppScriptはClasp経由でローカルで開発できるぜ
  • ローカルで開発できるってことはGitが使えたり、静的解析も使えるぜ
  • TypeScriptにも対応してるのでいろんな恩恵があって最高だぜ
  • そんなことを実現するための設定を今回は紹介するぜ

なんでやるの?

まずなんでこの路線で開発するか、というポイントは

  • TypeScriptはES6な書き方ができる
    • ESLint(TSLint)、Prettierなども使える!
    • Class構文便利!
      • ちゃんと継承もできるんだぜ
  • TypeScriptの型サポートがあると書きやすい
  • TypeScriptがサポートされたから面倒なWebpackが要らなくなった

ES6による恩恵が一番大きいので、以前からWebpackでやっていた場合は大きな変化ではないですが、Clasp側でサポートされたことによって自前でビルドする手間もなくなったのが大きいですね。
特にWebpackは時に設定がややこしく、そこでつまる人も多いと聞くので脱WebpackしつつもES6の恩恵を受けれる環境ができあがったのが嬉しい限りです。

開発環境

まずなにはともあれClaspを入れます。これは通常Web上のスクリプトエディタでGASのコードを書いていくのではなく、ローカルのファイルとしてスクリプトを書けるようにしてくれるものです。
ローカルで扱えるというだけで様々な利点があります。

  • Gitが使える
    • バージョン管理が楽になる
    • つまりもちろんGitHubによる共同開発環境が持てる
  • ESLint(TSLint)、Prettierなどの静的解析によるフォーマット、リントが効く
    • 間違いが減ったり、自動修正したり
  • 好きなエディタが使える
    • 捗る!

ここでは詳細なClaspの導入、GASとの反映方法は割愛します。公式のREADMEやちょっとググればいろいろな導入記事が出てくると思いますのでそちらをご参照いただればすぐできると思います。

あ、ちなみにNode.jsも必須です。その導入もここでは触れません。

今回の開発で特殊な事情を加味して言及するとこんなディレクト構成になります

.
├── __tests__
│   └── 各種テスト用ファイル
└── node_modules # ライブラリ格納ディレクトリ
└── src
│   ├── *.ts # これから作っていくTypeScriptファイル
│   └── appscript.json # GASの設定ファイル
├── .clasp.json # claspの設定ファイル
├── .claspignore # clasp用のignoreファイル
├── .eslintrc.js # 後述するESLint用の設定ファイル
├── .gitignore
├── index.d.ts # 型定義ファイル
└── package.json # プロジェクトの設定ファイル

とこんな感じですかね。テストは書かないんだったらないですが、せっかくローカルで開発するならテストも書きたいところです。
なので環境を整えた後はsrc/以下にガリガリ実装していく感じです。注意すべき点としてはGASの設定用のappscript.jsonはこのsrcディレクトリ内に置くことになるところです。

Linterとフォーマッターを導入する

いくつか選択肢はあると思いますが、今回は

  • ESLint経由でTypeScriptのLintをする
    • 理由: TypeScript側が「LintはESLintを使ってくれよな」って言っている
  • ESLint内でPrettierによるフォーマットをかける
    • 理由: Lint側とバッティングするルールがあるので上手く避ける

という方法で行きたいと思います。

一応TypeScriptでTSLintではなくESLintを推奨している経緯は

のLintの項目、もしくはThe future of TypeScript on ESLint - ESLint - Pluggable JavaScript linterを参照していただければと思います。

ESLintでTypeScriptにLintをかける

yarn add --dev eslint
yarn add --dev @typescript-eslint/eslint-plugin
yarn add --dev @typescript-eslint/parser

で、ESLintとESLint経由でTypeScript対応するプラグインとパーサーを入れます。
そしたら.eslintrc.jsというルール設定のファイルを作って、

.eslintrc.js
module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
}

と入れます。これが最小限の設定ですね。

これで.eslintr.js内にTypeScript用のLint設定も書いて設定ができます。

ESLintにPrettierも組み込む

ESLintの設定のいくつかはJS系の最有力フォーマッタであるPrettierと一部バッティングするルールがあります。
これが整合性が取れてないと、自動でPrettierのフォーマットとesLint --fixを連続してかけたりエディタの設定でFixOnSaveとかやってると矛盾ルールでハマります。

ということで個人的なオススメとして、eslint --fix内でPrettierをかける設定にするのが良いと思っています。またVSCodeなどでESLintのfixOnSave設定だけでキッチリPrettierもかかります。

具体的には

yarn add --dev prettier
yarn add --dev eslint-plugin-prettier
yarn add --dev eslint-config-prettier

eslint-plugin-prettier.eslintrc.js内でPrettierの設定もできるようにするもの、eslint-config-prettierはESLint側のPrettierのフォーマットルールとバッティングするルールをオフにするものです。

となると、設定は

.eslintrc.js
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
parserOptions: {
sourceType: 'module',
},
plugins: [
'@typescript-eslint',
'prettier',
],
extends: [
'prettier',
'prettier/@typescript-eslint',
],
rules: {
'prettier/prettier': ['error', {
useTabs: false, // example
}],
'no-var': 'error', // example
'@typescript-eslint/camelcase': 'error' // example
},
}

みたいな感じが最小になりますかね(Ruleに関してはサンプルで入れています。適宜カスタムしてください)。

このあたりのことはIntegrating with ESLint · Prettierを参照していただければわかりやすいかと思います。

もっと細かい設定

ここはオプショナルな設定ですが、用意されているルールなどを適用したい場合は、もうちょっと込み入ってきます。僕はStandard(JavaScript Standard Style)派なんですが、例えばそれを適用しようとするなら、standard/eslint-config-standardを使いますので、

yarn add --dev eslint-config-standard eslint-plugin-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-node

として.eslintrc.jsのextendsに'standard'を加えます。Standardにはno-undefルール(定義されていないものに警告するルール)が入ってますので、GAS特有の関数(e.g. SpreadsheetApp)が警告されます。

.eslintrc.jsglobalsに設定してあげればいいんですが、それなりの数があるのと思うので、selectnull/eslint-plugin-googleappsscriptを使ってガっと回避します。

ちなみにオブジェクト操作のライブラリUnderscore.jsや日付を扱うライブラリMoment.jsがGASでも用意されてますが、使う場合は同じようにグローバルな関数になるので、それは.eslintrc.jsglobalsで設定していきます。

そうなるとこんな感じになります

.eslintrc.js
module.exports = {
root: true,
env: {
'googleappsscript/googleappsscript': true,
},
globals: { // example
Underscore: true,
Moment: true
},
parser: '@typescript-eslint/parser',
parserOptions: {
sourceType: 'module',
},
plugins: [
'googleappsscript',
'@typescript-eslint',
'prettier',
],
extends: [
'standard',
'prettier',
'prettier/@typescript-eslint',
],
rules: { // example
'prettier/prettier': ['error', {
useTabs: false,
}],
'no-var': 'error',
'@typescript-eslint/camelcase': 'error'
}
}

ちなみに僕の場合、PrettierとESLintともにもっと細かくルール設定しています。
そして、Husky経由でGitのcommit時に自動でeslint --fixがかかるようになっています。
その辺のことは以前書いた記事をご参照ください。

LintとFormatをGitのコミット時に自動でかける方法 - Trial and Spiral

型定義の導入

これでようやく環境が整った! と思いきやまだあるんです。そうです型定義です。
ありがたいことに公式でGAS関数の型定義が用意されているのでサクっと入れます。

yarn add --dev @types/google-apps-script

これでGASの関数に関してはばっちり型サポートが有効になります。

GAS用ライブラリの型定義

GAS用ライブラリを導入した場合、多くはグローバル関数として使えるようになります。しかしローカルで開発するときはそんなことはわからないので、そんな関数の型は定義されてないぜ、っていう警告が出ます。
それを回避するためにindex.d.tsファイルを作って、例えばこんな感じに書きます。

index.d.ts
declare const Moment: {
moment(arg?: any): any
}
declare const Underscore: {
load(): any
}

これは僕の中でまだ上手くいってない部分で苦肉の策です。MomentもUnderscoreも同名のJSライブラリが元になっていてすでに型定義ファイルが用意されています。使い方がちょっとだけ違うのでそこを上手く吸収しつつ、型定義をうまく流用できたらいいなあと思っています。

どなたか解決方法があったら教えていただけると嬉しいです。

そんな感じで長くなりましたが環境構築ひとまず完了です。
次回は実装編を書けたらいいなぁ。

Git 初回コミットのメッセージをちゃんと決めてみる作戦

  1. 1. なんで決めるか
  2. 2. 一般的にどうか
    1. 2.1. 調べてみた
  3. 3. 僕はinitに決めた
  4. 4. ちなみにrebaseはできる

新しいことをいろいろやろうとすると、それがSandboxであれgit initすることはそこそこあると思う。で、毎度毎度うっすら「初回のコミットメッセージって何か決まりあるんかな」と思うけど、まあわかればいいか、と思って適当にやるっていう感じだった。今回はそれをちゃんの決めてみようというお話。

なんで決めるか

僕の行動原理として「小さなことでも何度か考えるなら論理的にルールを決めると楽」という実感がある。
これはインデントがどうとか、コーディングフォーマットにも通じるんだけど、要は本質じゃないものからのノイズを減らして本質にフォーカスしやすくする、という戦略のつもり。
余談だけど僕がSCSS嫌いでSASS好きなのもそういう理由だったり(Stylusはもっと好き)。

なんかカッコつけたけど、毎回3秒でも悩みたくないから決めちゃっておきたい、でも自分の中だけにでも納得のいく論理的理由が必要、という面倒な自分を御したいだけな話。ちょっと最近いろいろと忙し気味なので、そういう時はこういう簡単なことをサクっと処理する時間にあてていきたい所存。

一般的にどうか

そもそも絶対こうじゃなきゃいけない、というものはない様子。ならばまず最初に狙うべきは「一番多い」というところ。 Gitは複数人で扱う前提とすれば「誰もが迷わずそれが初回コミットであることを認識できる」というのが必須条件になってくるはずで。

そうすると良く見かけるのはfirst commitinitial commitのどちらかだろうと思う。ちなみに今までの僕はinitial commitを使ってきてる。
これは予想だけど、僕も含めGitを初めて扱い始めたころのチュートリアル的なものに影響される人が多いんだと思う。

もう1つ日本語メインでやっている人の場合は「初回コミット」というのも見かける気がする。考慮すべきはまあこのあたりかなぁ。

調べてみた

ちょっと面白い記事を見つけたので紹介したい。

すごい簡単に説明すると、スクリプト書いてある分野のGitHubのリポジトリの最初のコミットメッセージを集計してみた、的な感じ。

これを見る限りではやはりfirst commitinitial commitが郡を抜いて多い。ついでadd readmeのようで、これはとりあえず最初にreadmeだけアップした、みたいな感じなのだろう。
タイポや省略形もあるのでザっと見た感じで分けると

  • first派(1st commit, first commiitなど)
  • initial派(init, initial, initial commitなど)
  • add派(add files, add readme, create readme, など雑多)

の三種類に大別できるかなーって感じ。

注意すべきは対象がrOpenSciのものだけみたいなので、少し偏りがある可能性も否めない。

僕はinitに決めた

まあ「最初のコミットだよ」ってわかればなんでも良さそう。先程の例に習って僕もスクリプト回してみようかと思ったけど、結局やらずに決めてしまった。

僕はinitで行こうと思う。

理由として、

  • commitという情報はそれがコミットメッセージである以上、書かなくてもわかるので省略
  • Gitの最初のコマンドは$ git initですので
  • 正直わりとどうでもよくなったので短かくてわかりやすいのでいいやってなった

という理由。
これでもう初回のコミット時にメッセージどうしようか思いを馳せることはなくなった、1リポジトリあたり3秒ぐらいの時間的コストをカット、同時にその一瞬思考をそっちにまわす脳内ワーキングメモリコストもカット(わりと無視できる程度な差なのは否めないw)

ちなみにrebaseはできる

今回初回コミットについて調べる過程でメッセージとは違う軸の話として、

最初のコミットは前コミットが存在しないためrebaseができない、だから初回コミットはあえて空コミットにする

みたいな話を見かけたけど、よくよく調べてみると

$ git rebase -i --root`

とか--rootオプションで一番最初のコミットを含めて修正できるし、実際試したら出来たのでこれは採用しなかった。

ただ、最初を空コミットにしてcreate this repositoryとかにしてもアリかなぁとも思った。いやいややっぱりナシで、僕はもうinitに決めたんだ、迷わないんだ!

UXデザインのペーパープロトタイプの講座を受けにいってきました

  1. 1. イベント概要
  2. 2. 参加動機
  3. 3. 講義について
  4. 4. 前半:ペーパープロトタイピングについて
  5. 5. 後半:ペーパープロトタイピング体験
  6. 6. まとめ

昨日、ユーリカ株式会社さんが催行しているUXトライアウト・2時間で学ぶペーパープロトタイプに、前回と同じくブログ書く枠として応募したところ抽選に当たったので参加させていただいたのでそのレポートです。

今回もまた詳細な内容は講義を受けたほうがより正しい内容なはずなので、主には概要と感想です。

イベント概要

UXデザイン会社のユーリカ株式会社さんで定期的に行なわれる「UXトライアウト」と題したコースがあって、基礎知識からUXデザインで行なわれる各行程ごとに2時間のワークショップ。どんなものがあるかはTECH PLAYのユーリカ株式会社|UXデザインで売れるモノづくりを応援しますのイベント・技術情報 - TECH PLAY[テックプレイ]で見ると良いと思います。

ちなみに通常は有料の講義だけどブログ書く枠は抽選枠ですが無料参加で募集しているようです。

参加動機

前回も書いたけど、良いものを作るためのUXデザインの話まで自分としても注力していきたいので。その技術を業務で活かしたいのはもちろんなんだけど、僕は個人開発も行なってるので個人でやる場合は全部を自分でやらなきゃいけない。

実は応募自体は前回のものと同時につづけざまにしたので前回と動機に違いはないものの、UXデザインの具体的な手法として例えばユーザーインタビューとかあるけど、まず個人レベルで手がつけやすそうなのはペーパープロトタイピングかなーと思っての応募。

講義について

前半は、ペーパープロトタイピングってどのようなものか、どうやってやるのか、やるための便利なツール(アプリなど)の紹介という感じ。
後半は実際にワークショップとしてやってみて、レビューしてみて、という感じの大きくは2部構成。

前半:ペーパープロトタイピングについて

まず話として、「へー」と思ったのが「評価」することを前提として作るということ。僕は何かをつくるときそれがWebでも趣味のレザークラフトでも基本的にまずラフスケッチをするんだけど、それは頭にあるものをちょっと具体化する程度のもので書き散らすことが多い。

工程としてそれも必要かもしれないけど、作るときは気分が乗ればガーっとコーディングから始めてしまう。だけどプロトタイプはちゃんと評価する、というのが違うんだなぁと思った。まあその結果が作ってる途中で「あ、これこうだとダメじゃん」とかって手戻りが発生するわけなんだけど。

で、アプリやWebの開発の場合、ペーパープロトタイピングでは全ての画面や動きなどをできるかぎり手書きでOKなので用意して、実際の操作を模して、紙を変えたり乗せたりしてシミュレーションする感じで評価するとのこと。

これは欠点として紹介されてたけど、その紙の差し替えは非常に面倒だという問題。なので例えば写真にとってデジタルツールと組み合わせてやると良いということでツールの紹介があった。

個人的にはここでFigmaの名前があがらなかったのが不思議だったけど、Sketchの名前も出なかったので、実際この講座は初心者向けなために、きっとそういうデザイナー寄りのツールではなくてまず使うための前提知識や技能が要求されないものをオススメしてくれたんだろうと思う。

ちょっと残念だったのは思ったよりこのツールの使いかたや類似ツールの説明などの話のボリュームを減らして、実際のペーパープロトタイピングの具体的なやり方とか気をつけること、守るべきルールとかをもうちょっと教えてほしかったなぁという気がしなくもない。アプリの使いかたはアプリが違えば変わってしまうので。もちろん僕は個人的にFigmaとかでやるだろうなぁ、と思ったという背景もあるけど。

後半:ペーパープロトタイピング体験

そんな説明があった後にじゃあ実際体験してみようということで出たお題は「Instagramを記憶、または想像だけで再現してみよう」というお題。

まず僕が作ったのはこんな感じ

実習

日頃から個人開発とかやるときに画面構成を書いたりしてるのと、業務でも仕様書的なものを見てるのでわりと想像はつきやすかった。

やって思ったのはInstagramはあまり使うほうではないけど、それでも迷うことなく使えている。かといってどこにどのような要素があったかというのは正確に把握してるわけでなく、なんとかそれなりに書けたのも、よくあるUIならここに置くだろうという推測で描いた要素のほうが多かった。

実際に簡易的な取り込みアプリをつかって、操作を模してレビューしてもらったりした。決定とか削除ボタンとか付けわすれた。あとは、何がどこにあるべきか、って思ったよりは難しかった。逆に面白かったのは、自分でちゃんと投稿されたかどうかのモーダルを想像できたり、「ここで多分GETのAPI叩いて、Arrayで返ってくるから」と想像してたのは無意識に発露したサーバーサイドエンジニア目線なんだろうなぁと感じて面白かった。

実際に体験してみるまでは、いきなりSketchとかFigmaとかのツールでやったほうが早くない? と思ったけどそうではなくって、触ることを意識したり、紙の状態でもいいからこれを触ったらこう反応して、というインタラクティブな動きをシミュレートすることで不足を炙りだすのにすごく役に立つと実感した。

なんというか「早く失敗する」というか。最初から最良のアウトプットを出そうとするんじゃなくて手書きでパパーっと描いてシミュレートする、過不足を早い段階で炙りだしてから問題なさそうなら次にもっとしっかりしたものをデジタルで作る、みたいな工程を組んだほうが結果的に早そう。

ただしそれが絶対というわけではなく、同じような画面や同じような部品のものは、手書きだと逆にコンポーネント化して使い回しとかできずにイチイチ書かなきゃいけないからかったるいなーとも思った。だからそういうところ上手く簡略化してやるのが良い落しどころなのかもなぁ。

まとめ

こうしてやってみたらやっぱり重要な工程だった。だけどこれだけやればじゃあUIに関してはバッチリかいうとそうではなく、使う人がどのような層なのかというコンテキストで最適な配置や表現する文言や使う単語、アイコンも変わってくる。だから他のユーザーインタビューやペルソナを想定したり、カスタマージャーニーマップも必要になってくるんだと思う。

2時間ではもちろん時間が足りないのでどうしても「お試し体験」的学習になるけど、それでも今回もなかなか良い学びでした。やっぱり何ごともトライして試して手を動かさないと。他の人はどうかわからないけど、とりあえず手をつける、体験してみる、が僕が僕を活かせる勉強のやりかただと思ってるし、そこを躊躇しないのが僕の強みだと思ってるので。

今回も今や便利ツールがいっぱいあるのに手書きでやることの意義とか効果とかも実感できたので良かった。今も職場で小さいホワイトボードが欠かせないように、デザインだけじゃなくて、シーケンスやら分岐やら、設計もわりと手で描いてみて考えるタイプなので、手書きを活かすアイデアが1つ足されたような感じ。

それと同時に余裕があれば(といってるうちはいつまでたってもそんな日は訪れないんだけど)Figmaとかももっと触っていきたいと思った。

今後もUX系の講座には参加したいと思うものの、今はそれが本業ではないのでいったんはこれくらいにして、紹介された本やUIに関するガイドラインとかをまず読むところからひとつづつ一歩づつ進むことにしよう。粛々と。

コンポーネント時代のCSSの命名ルールを考えてみよう

  1. 1. ScopedなCSSとは
  2. 2. デファクトスタンダードなBEM
  3. 3. 僕はSMACSSが好き
  4. 4. オレオレルールを模索する
  5. 5. まとめ

このブログはHexoというNode.js系の静的サイトジェネレータで作ってる。テーマはイチからフルスクラッチで自分で作った。でも自分で作ったがゆえにまだ手のゆき届いてないところがあったり。そんなこんなで久々にテーマをどう作ってたってところから見なおしてたり。

そんなことから、そういえば以前はBEMやらFLOCSSだったり、SMACSSのルールに基づいてCSSを書いてたなあ、と思った。一方、React, Angular, Vueの三大巨頭が牽引するコンポーネント時代に突入してきた今、CSSの効果範囲はScopedにものが主流になってきている。ScopedなCSSはそれに適したまた別の命名ルールが存在するのでは、と思って考えてみたという話。

ScopedなCSSとは

まずScopedなCSSについて簡単に説明したい。
そもそもScopedなCSSというのはJS系フレームワーク産の発想ではなくて、一時期はちゃんとFirefoxにも実装されたようにCSSそのもので提案された考えかた。

CSSは名前のとおりカスケーディングに処理されているけれど、カスケーディングがゆえに乱暴に言えば全てがグローバルに宣言されていると同じようなもので、そこから、あるDOMの中でだけに絞って作用させたい用途としてScopedが生まれたんだと思う(この辺あいまいです……)

残念ながらそれは正式に採用されることはなくなったようだけど、WebComponentよりも先駆けてコンポーネント指向の急先鋒となったReact, Angular, Vueには実装の形は違えど、各コンポーネント内だけでしか作用しないCSSの書き方がある。それを今回は便宜上「ScopedなCSS」と呼んでいる。

デファクトスタンダードなBEM

さて、Scopedじゃない時代、人は常にCSSの影響範囲と戦ってきた。基本的にはそれぞれにクラスをちゃんと指定して、クラス名の命名規則とつけかたで頑張りましょうという戦略。

そこで生まれたのがBEM(Mind Bemding)という手法。block__element--modifierという命名規則で、親子関係がしっかりしているのが特徴。OOCSS(オブジェクト指向CSS)としても構造がわかりやすく、今やCSS命名規則のデファクトスタンダードと言っても過言ではなさそう。

僕はSMACSSが好き

BEMもSMACSSもどちらもある単位ごとに分けて管理しよう、って概念はかなり近い。個人的にはBEMよりはSMACSSのほうがわかりやすい気がする。その反面、Mに相当するモジュールの自由度が高くて悩むこともしばしばある。でもそれはBEMにしてみてもブロックでの区切りかたに悩むのと同じようなもので。

SMACSSが大きくBEMと違うのは、ステート(状態)をマルチクラスとして宣言するところ。BEMの場合で言えばModifierに相当し、例えば同じように書くとしたらBEMなら.module--stateと指定してたのをSMACSSなら.module.is-stateというような感じ。

個人的にはこちらのほうがCSSの特性を考えると、状態の変化を上手くあつかうには適していると思っているのでこっちのほうが好きだ。

オレオレルールを模索する

じゃあコンポーネント指向になった構造でScoped CSSになったとき、どうするのが良さそうか、っていう話。

AtomicDesign的な思想をベースとすると、コンポーネントの単位はその「責務」によって分割されるべきで、これがCSSのデザインのブロックやモジュールとは非常に似つつも完全に同一でないのでちょっと混乱しやすい。

まず、SMACSSで言うようなレイアウトのプレフィックスはいらないくなってくるはず。つけたいなら付けてもいいけど、Scopedである以上、レイアウトを扱う部分とモジュールの部分は別コンポーネントになるべきだ。もし必要になるのであったらそれはCSSの話じゃなくてコンポーネントを責務にわけた設計にしたほうが良い。

コンポーネント内でのクラス名はBEM的なのが良さそう。BEMのツライところとして、1つのまとまりだけどHTMLの構造上Elementが多層になったりするとBEMのルールだけではなかなかやりづらいようなことがある。BEEMとかにしたいときとかあるはず。BEMの規則にのっとるとこれはダメなので別のブロックとしてとらえてまた別の命名を考える、となるんだろう。けどコンポーネント指向の場合、そんなに多層になるのであればそもそもコンポーネントの切りかたが悪そうな気もしてくる。

BEMで言うモディファイア、SMACSSで言うステートは、SMACSS流にのっとってis-stateとかhas-stateisもしくはhasプレフィックスをつけて、変化するところだけを指定する。これはその状態が変化したときには、SMACSS的にマルチクラス的に指定してクラスを付けかえるほうがやりやすい。hasも加えたのは、isだけだと意味がおかしいことがあるので。

その結果、僕が「これでいってみよう!」と思ったのは、Scopedなコンポーネント内だけで

.some_block--some_element.is-state

というような書きかた。

説明すると

  • 複数語の場合、単語の区切りは_(アンダースコア1つ)
  • 階層的になる場合、--(ハイフン2つ)でつなげる
  • 状態の変化した場合の指定はis-もしくはhas-というプレフィックスのクラスを足す

ここでBEMに慣れ親しみすぎてると「おいおいハイフンとアンダースコアの使い方が変じゃない?」と思うかもしれない。僕がこう定めてみたのにはちゃんと理由があって、文字の選択をする場合などで

  • ハイフンで区切られた単語はハイフンを挟んで別の単語として認識される
  • アンダースコアで区切られた単語は1語として認識される

という特徴があるため。試しに上のsome_blockとかsome_elementとかをダブルクリックとかで選択してみてほしい。

ブロックと要素の区切りがハイフン2つにしたのは、BEMがやってるように、前後は別のまとまりというのを認識しやすくするため。単語の区切りが1つはなのはそれとの差別化。これでBEMに慣れすぎていても、blockとelementは違うくくりだな、と混乱しないようになってると思う。

まとめ

ScopedなCSSをメインで書くようになってから、命名ルールすら適当でも問題なくできちゃうぐらい便利で、今までなあなあで来てしまってた。それでもやっぱりルールは欲しいもので、あっちではBEMっぽく書いてこっちではSMACSSっぽく書いて、みたいにやってしまってたのでなんかずっと喉につかえた小骨のように気持ちわるかった。

単純な静的なページでもReact, Angular, Vueなどが使われはじめてみんなScopedなCSSで書けるようになってきていて最近は以前ほどOOCSS派生のルールみたいなものを聞かなくなってた気がする。それでも今回、一応自分の中では「こういうルールで行く!」と思えるようなものを決めれたのはなかなか良かったと思う。

他のみなさんはこのコンポーネント時代のCSS命名をどのようなルールでやってるか凄く興味があるなぁ。

UXデザインの基礎知識の講義を受けにいってきました

  1. 1. イベント概要
  2. 2. 参加動機
  3. 3. 講義について
    1. 3.1. UXデザインとは
    2. 3.2. UXをデザインする方法
    3. 3.3. UXデザインの手法の解説
  4. 4. 感想

昨日、ユーリカ株式会社が催行しているUXトライアウト・2時間で学ぶUXデザインの基礎知識にブログ書く枠として参加させていただいたのでそのレポートです。

詳細な内容は講義を受けたほうがより正しい内容なはずなので、主には概要と感想です。

イベント概要

UXデザイン会社のユーリカ株式会社さんで定期的に行なわれる「UXトライアウト」と題したコースがあって、基礎知識からUXデザインで行なわれる各行程ごとに2時間のワークショップ。どんなものがあるかはTECH PLAYのユーリカ株式会社|UXデザインで売れるモノづくりを応援しますのイベント・技術情報 - TECH PLAY[テックプレイ]で見ると良さそう。

ちなみに通常は有料の講義だけどブログ書く枠は抽選枠ですが無料参加で募集しているようです。

参加動機

常々良いものづくりをしたい、と思ってるのは開発者はみんなそうだと思うんだけどじゃあその「良いもの」を狙うにはUXデザインしないとね、と思ってたのが発端。

以前からUXデザインに興味があったけど、聞いたことあるレベルだったりぼんやりなんとなくレベルの知識だったので具体的にどうやるんだろう、ということをまず知りにいきたかった。

先に結論から言えば、「これは、(デジタルアナログ問わず)ものづくりをする人にとって必修でしょ」と思えるぐらい良かった。

講義について

今回の「UXトライアウト・2時間で学ぶUXデザインの基礎知識」というコースは他のコースは基本的にワークショップらしいのだけど、今回に限っては基礎知識なので基本的には座学。

大きくわけて

  • UXデザインとは
  • UXをデザインする方法
  • UXデザインの手法の解説

の3部構成。

UXデザインとは

まず講師の森山さんは強く強く「UI/UX」と良く言われるが、これらは全く別モノで関係がない。ということを強調しておられた。 これには僕も全く同意でそこここで並記されて同一のくくりで語られることはもちろん、混同してる人も多い印象を受けてた。

そもそも「インタフェース」と「エクスペリエンス」は言葉として全く別で、僕個人では混同してるのを見ると「略語の意味すら調べない、自分の使う言葉に無責任で無頓着な人」という印象すら受ける。

つまりUXはエクスペリエンス、ユーザーの体験をデザインすることであって、UIは体験に影響を与えるほんの一要素でしかない。ということ。最初にこれを強調して話されてたのが良かった。以前なんかのセミナーでUI/UXについて語るようなものに参加したこともあるけど、そういう話がなかったので。

常々なんで別モノが並記されてるんだろう、と思っていたけど講師曰く「企業の採用ページなどで「UI/UXデザイナー」と書かれることが多く、そこから一般化してしまった」とのこと。
これにはなるほど、と思った。確かにUIデザインとUXデザインは兼任できるだろう。すべきかどうかは別として。また面白い言い方だとUXデザイナーというのはプロダクトのUXに関する監督だと。

UIはUXを左右するほんの1要素なだけ。

UXをデザインする方法

UXとは要は、

  • いいね! と思う気持ち
  • その気持ちに至るまでの過程
  • その気持ちを動機とする行動

の全て、というのをふまえたうえで「人の気持ちは設計できないけど、過程は設計できる」という言葉が印象的だった。この一言でいろんなものが腑に落ちた。ありがとうございます!

ここではその過程についてどんなものがあるか、という話を受けたんだけどその中でも「期待外れはUX的にマイナスなので期待外れを興さないように適切な予想を与える」というのが印象を受けた。ただ「これ良いよ!」って思わせればいいもんじゃないんだな、と。

で、いろんな方法の1つとしてUIデザインパターンとかガイドラインとかあるけど、それだけだと足りないので、ISO 9241-210(人間中心設計プロセス)とUXデザイン手法の、ユーザー調査、ユーザーモデリング、理想シナリオ、プロトタイピング、UX評価の説明。

UXデザインに関する手法がISOに定められてるのは全く知らなかった。それで良く話に聞くペルソナやらシナリオとかカスタマージャーニーマップとかっていうのはこの行程の中の1つ。

UXデザインの手法の解説

ここは前章で紹介されたUXデザインのプロセスについてあるサンプルにそって、1つづつ説明を受けた。例えば、インタビューはどのようなもので、それから次の行程がこうできてきて、ペルソナ作りに移行して、というような感じ。

簡単なサンプルではあるものの十分にその過程と様子とやりかたの概要は掴めて非常に有意義な説明だった。おお、なるほど、こうやるのね、と具体的にイメージできたような。

で、やっぱりUIデザインは中に出てくる。プロトタイプの作成のところで。だからやっぱりUIはUXに影響を与えるほんの1要素以上ではない、ということ。

感想

前半のUXとUIは別物で、こういうもの。っていう話、UXデザインってこういうこと、みたいな話まではだいたい知識として持っていた。そういう説明をちゃんとされたことが、けっこう自分の中で有意義で、一見持ってる知識を再度説明されるって無駄なように見れるけど、自分の理解の確認、言語されてよりクリアな認識になる、という意味は大きかった。

後半のUXのデザインの技法については、エンジニアとしてプランナーさんとかディレクターさんとかと一緒に仕事しているわけだけど、彼らはちゃんとそこまでやってるのかな、という印象。
正直、会社としてこういうセミナーや講座に授業料払ってでも行かせるべきだろうなあ、と思うし、行かしてくれないなら自分から行くべきだな、とも。エンジニアは進んで勉強するけど、エンジニア以外の職種の人が勉強会とかセミナーとか積極的に行くって話はあまり聞かない。

冒頭でも言ったけど、UXにかかわるならこのあたりまでは必修じゃないかな、と思う。

一方個人的な興味に立ち返ってみれば、StrengthFinder調べで僕の資質に「回復志向」というのがあって、これを自覚してから感じるようになったのが「僕は本来の価値を十全に発揮できない状態が嫌い」らしい。

別の見方では貧乏性というか、もったいないというか。なので「モノ自体はいい」とか、上手く機能してなくて改善する余地がある、とかそんな状態が大嫌いらしい。その価値の最大化する手段としてUXデザイン技法が使えそうだなぁと強く思った。

なにもプロダクトに限ったことじゃなくて例えばチームビルディングに関しても、チームメンバーはみんな良いところあるのに、いろいろやり方が良くなくって価値を最大化できてない、とか。それをUXデザイン技法を用いて良い方向に持っていくことも可能だろう。

あとはゲーム。ゲームってプレイヤーに楽しませるのが目的なんだけど、そこには凄く細かくいろんな心理状態への働きかけがある。ボードゲームとかやると特に顕著で、ジレンマを上手く発生させたり、とかね。

UXにつながる心理状態を作り出すための過程のデザイン、というのはかなり広範囲に応用の効くものだろうだと感じた。

そんなわけでUXデザインの興味と勉強は僕の中でもうちょっとプライオリティ上げてもいいな、と感じた。まだまだエンジニアとしてレベルアップしたいし、エンジニアとしての勉強もやりたいもの全部は難しくて効率的に適切に捨選択していかないといけない状況だけど。

これまでにも書いたけど、デジタルプロダクトだけでなくアナログでもUXデザイン技法は変わらず使えるので、ものづくりに携わる人みんな基礎ぐらいは知って損はないです。
満足度すごく高い講座でした。また別のクラスも是非参加してみたい。

LintとFormatをGitのコミット時に自動でかける方法

  1. 1. 使うもの
    1. 1.1. Husky
    2. 1.2. lint-staged
  2. 2. インストール
  3. 3. 設定
    1. 3.1. まずhuskyの設定
    2. 3.2. lint-stagedの設定
  4. 4. おまけとまとめ

前回、LintとFormatをかけるのはもちろんなんだけど、なんでGitHookのタイミングにしたかって話を書いた。今回はそれの具体的な方法を書いていこうと思う。

ちなみに前回書いたやつ。

使うもの

まず使うNPMのライブラリを使うので、Node.jsを用意してください。これmacならbrewでyarnを入れてもいいし、僕はanyenvを経由してndenvを使ってる。いろんなやり方があるし、それぞれ利点が違うので自分にあった入れ方を推奨。

それで使うライブラリなんだけど

  • husky
  • lint-staged

の2つ。以下で簡単に紹介しよう。

Husky

huskyはGitHookをプロジェクト単位で設定できるようにするツール。
GitHookの設定は通常だと{project root}/.git/hooks/配下にある。.git以下は通常ではリポジトリに含まれないので共有されない、つまりhookを共有したり強制したりできない。

だから、husky経由で共有できるところで設定できるようにする、というのがhuskyの役割。どうやらhuskyを入れたときにGit hookをhusky経由で動くように入れかえてるっぽい。

lint-staged

lint-stagedはgit addした対象に対して特定のコマンドを走らせるもの。READMEにもあるとおりhuskyと合わせて使うのがオススメとされている。ちなみに以前はhusky以外にもpre-commitをやり方やいろいろあった。あと、名前はlint-stagedだけどやることはstagingされたコミット前のものに対して何かをするのでlint以外にも使える。

ちなみに昨年前半あたりまでずーっとハンク(git add -p)したファイルの対応する方法に関してissueで議論されていたが、昨年中頃にlint-stagedがアルファ版を経て正式に対応した。個人的にハンクはかなり使うのでずっと動向を追っていたし、これが解消されたからプロジェクトに導入したし、紹介するに相なりました。

インストール

npmに慣れてる人には言うまでもないだろうけど

$ yarn add -D husky lint-staged
# or npm install -D husky lint-staged

でOK。

設定

package.jsonに設定を書いていく。ちなみに別ファイルに分けることもできるけど、そう複雑で長い設定でもなく、huskyとlint-staged両方とも連続した設定になるし、package.jsonのscriptともかかわることもあるので個人的にはpackage.jsonだけでやっちゃうのが良いと思ってる。

まずhuskyの設定

以下を追加

package.json
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},

要はhuskyの設定を、hooksのpre-commitにlint-stagedコマンドをするよ、という設定。
ここではpre-commitだけだけどもちろん他のhookも同様に書くことができる。詳しくはhuskyのREADME参照。

lint-stagedの設定

同様にlint-stagedの設定もpackage.jsonに書く。ここはどのようなファイルにどのようなlintをするかので一例として

package.json
"lint-staged": {
"*.{js,ts,vue}": [
"eslint --fix",
"git add"
]
},

みたいに設定する。
lint-staged直下の設定で対象のファイルのglobパターンを書く。例えば上の例だったらGitのStageにある拡張子がjs,ts,vueのものにeslint --fixがかかる。これで自動で修正された結果のファイルが再度addされて、問題なければcommitされる。

もちろん、lintの結果エラーが返ったときはcommitされない。意図的にpre-commitフックを避けない、という前提のもとであればコミットされたものは全てプロジェクトで設定されたLintのルールにパスしていることが担保される。

で、もちろんファイル名の条件にしたがってコマンドを走らせるだけなので、

package.json
"lint-staged": {
"*.{js,vue,ts}": [
"eslint --fix",
"git add"
],
"(*.rb|*.rabl|Gemfile)": [
"bundle exec rubocop --auto-correct --fail-level E",
"git add"
]
},

みたいにやればこの例で言えばJS系だけでなくRubyのファイルにRubocop(Ruby用のLinter兼Formatter)をかけるようにもできる。

ちなみにJS系のformatterとしてprettierがあるけど、eslintのルールとバッティングするところもあるので、eslintにpluginを噛ませてeslintの中でprettierによるformatするのがお勧め。

おまけとまとめ

あとは以前に紹介したcommitizenもNPMなので一緒に使うのも簡単で、そうするとコミットメッセージも綺麗、コミット内容もキレイ、という素敵なコミットができる。

と書いてきたけど、やってることはいろんなところで紹介されてるしそんな難しいことじゃない。
でもNPMがフロントエンド特化傾向にあるため、Node.js系をふだん使ってない人には有用であればうれしいなぁ。特にRailsはWebpackerやらYarnを採用したこともあって相性は悪くないと思う。

途中でもちょっと触れたけどこのGitのハンクに対応したこともあって、この仕組みを業務でも使ってみたけど上手くいってますのでけっこうオススメしますよ。

LintとFormatをGitHook時にかけてる理由

  1. 1. いつかけるか
    1. 1.1. Save時
    2. 1.2. GitHookにひっかける
    3. 1.3. Pull Request時にCIで回す
  2. 2. もうひとつの目的
  3. 3. 実践

LinterとFormatterをかけないコーディングはツラくて個人的にはちょっと悲しくなるんだけど、問題はどのタイミングでやるかってこと。個人的にやっていたものを昨年なかごろから業務にも取り入れてみてそこそこ上手く回っているので書き残しておきたい。

いつかけるか

LinterとFormatterをかけるとしたらいつがいいのかいろいろ考えて、結論から先に言えばGit commit時にしている。なんでそう結論づけたかっていう話の比較を交えてご紹介したい。

Save時

一番頻繁にかかる一例としてファイルの保存時。例えばVSCodeなんかではFixOnSaveとかって設定があるようにわりとメジャーだと思う。

Saveするときにかかるので一番頻繁だし、適当に書いてもガっとキレイにFormatは効くし、変なコードはすぐに警告が出る。良い。

でも残念ながらできるかどうかははエディタ頼みになってしまう。独りで開発しているときは十分かもしれないけど、みんな違うエディタだったり対応できないエディタの使用者がいたら?

例えもし開発者それぞれが使うエディタで全部対応できたとしても、エディタごとに設定もプラグインとかも違ってくるのでどうしてもノウハウが属人化してしまう。

一番大事なのは自分以外も加わるとしたら強制できないのであまり有効でないところ。ルールを適用するならそれは守られなければ意味がない。

GitHookにひっかける

GitにはGitHookという機能があって、commit時やpush時に設定したスクリプトを回すことができる。最初に言ったようにこのフックにひっかけてpre-commit時にLinterとFormatterをかける運用にしている。

理由はcommitをしないことには開発は進められないし、エディタがなんであろうと強制できる。そしてローカル上でエラーが出るのでそのcommitする開発者が自分でエラー箇所を修正することになる。また最悪どうしようもないときは--no-verifyオプションをつけることで一時的にGit Hookを飛ばすこともできる。

ちなみにpre-pushも検討してみたけど、push時に弾かれたり修正が入ることでコミットログがエラーやコーディングスタイルの修正だけになったりして、それは別コミットにすべきじゃないと思ったのでpre-commitにした。

Pull Request時にCIで回す

他の候補としてPull Request時にCI等の外部サービス経由で回すことももちろん検討した。これも結局はpre-pushと同じようにコミットをキチンと整理したいこと、その後のマージ戦略まで影響するのがちょっと面倒で見送った。

ただし方法としては一番、開発環境に依存しない方法だし悪くはないと思う。pre-commitにしろpre-pushにしろ、CIにしろ、ポイントとしては

  1. Lintに通ってないコードを採用しない(できない)。
  2. Formatterのルールにのっとってないコードを紛れこまさない
  3. 1と2を共同開発者全員で共有する

というのが前提として守りたいルールだった。

もうひとつの目的

なし崩し的にチームリーダー的なポジションになって後輩を抱えるにことになったけど、なにもイチから教えることはなくて「こういうコードがいいよね」っていうのはLinterやFormatterに助けてもらうことにした。

なにより僕がレビューコメントや口頭で「こういうコードがいいよ」っていうより、ルールの説明のドキュメントのほうがよっぽど説得力がある。

まずチームにJoinすることになったときにルールを確認してもらって、できればその時になんでそういうルールを設定してあるかもコメント等で共有する。そしてそのルールに納得してもらうようにした。反論は出なかったものの今でも合わないルールがあったら変えるからいつでも相談して欲しいとは伝えてある。

そうすることで例えばLinterではうっかり使用されない変数、到達しえない分岐、デバッグ用のコードなど紛れこんだままだったり、同じ結果だとしてもよりリーダーブルな書き方だったり、そういったことがPull Requestに紛れこまないことによってレビューの時間コストも抑えれるし、エラーが出たら自身でちゃんとルールを参照して修正してもらうようにしてる。そうすることで自身で徐々により良いコードを書けるようになってもらう作戦。

またFormatをキチっとやるのことも僕は大事だと思っていてインデントが不揃いだったり、なんか感覚的に気持ち悪いっていうことだけじゃなく、コーディングスタイルを統一することで読みやすくして、本質じゃないノイズを極力カットすることで本質にフォーカスしやすくするのが狙い。

この目的にあたって注意したのは「ルールは聖域、無視しちゃダメ」ということ。もちろんキビしすぎるルールは時に枷となって開発スピードを鈍化させたりもするんだけど、そういう場合もキチっと直すことを意識した。なんども苦労するようであればそれはルール自体を変更したり緩めたりすることで対応する。

これはLinterのルールは割れ窓理論的に悪化しやすいと思っていて「ああ、このルールはまあ無視してもいいよ」みたいにしてしまうと次第にどんどん広がっていき、最終的にはルールは守られず、無いもの同然になってしまう。その経験が僕にはある。だから「ルールは聖域、無視したいのであればルールの変更を提案しよう」として運用して、事実上手くいってる。

実践

じゃあpre-commit時にLinterとFormatterをかけるための具体的な方法なんだけど、それはちょっと次回に回したいと思います。使ってる言語と環境にも寄るんだけど、僕の主戦場がRubyとJS(TS)なのでそれら限定になってしまう。とはいえフックさせて回すのはNPMライブラリだけでやってるので他の言語のプロジェクトでもNPMを同時に使えば実現できそう。

そんなhuskylint-stagedを使った具体的な設定はまた次回。

追記
書きました。

ここ1年ちょっとで僕が作ったプロダクト

  1. 1. Pentazemin
  2. 2. MHW-cheatsheet
  3. 3. YANTAN
  4. 4. cz-conventional-changelog-ja
  5. 5. その他
  6. 6. 所感とこれから

いよいよ2018年も終わりそうで。今日は職場の大掃除があってようやく年末感を味わいはじめた。せっかくなので今年に作ったもの達を振りかえってみたいと思う。ちなみに開発系限定で。というのも開発系にフルコミットしたからなのか、単に気が向かなかったのかレザークラフトとか物体の物作りは全然してない。

Pentazemin

いわゆるポモドーロテクニックを利用したタスク管理アプリ。どっちかというとタイムマネジメントの側面が強い。気になった人はリンク先を見ていただけると嬉しいです。

時間的には去年、2017年の終わりごろにリリースしたアプリなんだけど、当時はまだVue.jsもそこまで人気じゃなくNuxt.jsのver1でさえベータ版だった。そう思うと2018年のそのあたりの速度って凄かったなぁ。

こういうアプリが欲しいなぁと思いたって、ちょうど今Vue.jsやってみたし、おっElectronも勉強しながらやったら面白いんじゃない? と思って作った。そしてこの時にガッツリVue.jsに触れて苦戦しながらもちゃんとリリースまで持ってったのが今の僕のVue.jsの基礎力となってその結果素晴しく力がついた。

作ってできたーじゃなくて、使ってもらうために紹介ページを作ったりして、いくつかのブログで紹介されたり、外からお声がかかるきっかけになった。開発力だけじゃなくて作る以外のことも含めて僕の2018年を支えてくれたプロダクトでした。

2018年いろいろ作ってきてレベルアップできた感があるので、今の技術でちゃんと一新したい。

MHW-cheatsheet

年の始めにMonsterHunter Worldというゲームが出て、夫婦ともにガッツリハマって。簡単に説明するとみんなで協力しながら大きなモンスターを狩る、みたいなゲーム。で、モンスターには属性や攻撃部位による弱点があってなかなか複雑。

ネットを見てたら早見表みたいなのが凄くバズってましてね。絶賛されてるんだけど、個人的に「おいおいまだ見やすくできるだろ」という思いが膨らんで、よっしゃいっちょ作ったるか、せっかくだからVue.jsでPWAやってみよって作った(とはいえ、最初に画像でもなんでも形にした先人達には敬意を表したい)

やってて思ったのは、開発自体は楽しいんだけどモンスターの情報入力とかは地道で面倒で辛かった。あとゲームプレイしたい時間を削って開発するのも辛かった。

でも一番辛かったのは、宣伝するのが難しくて火がつかなかったこと。使ってくれた周りの人とかごく一部の僕のTwitterフォロワーの人達にはすごく評判良かったものの、当時ゲームの全盛期でハッシュタグ付けても文字通り秒で流れていくし、目にとまらない。個人レベルでの宣伝って難しいのを思い知らされた。

技術的にはPWAに触れれたし完全に静的にアップするんでもアイデア次第ではいろいろ活用できるなーって感触が得られたのは大きい。

YANTAN

新しいタブ用の拡張って前からしっくり来てなくて。と言うのも綺麗だけど自分がとった写真じゃなくてどっかの誰かがとったやつだったりとか。あとは単純なメモが欲しかった。ある日に、あれ、SPAの技術使えばChrome拡張って作れるんじゃね? とひらめいたから作った。

CSSでかけれるフィルタをフルに搭載して、カスタマイズ性の高いものが作れたのは良かったし、なによりこれも使ってくれた人からけっこう評判良く、自分でも常用している(そりゃあ自分が欲しくて作ったわけですし)

苦戦したのは、Markdownのリスト記法の入力保管とか。入力保管って自分で実装すると以外に泥くさいことしなきゃなんなくて。とはいえなかなか楽しかった。あとこれもマーケティング的に上手くいってない。やっぱり自分のTwitter、GitHub、ブログ以外のところで上手いこと宣伝活動していかないといけないんだなぁと思う。

cz-conventional-changelog-ja

いろいろ作ってたなかでCommitizenが凄く良くって、もっとGitのコミットメッセージをちゃんと書く文化が周りにも広まればいいなぁと思ってガっと訳した。

エゴサーチしてみると影響を受けてフォークして別の何かを作ってくれたりもしてくれてるようだし、嬉しいかぎり。また、翻訳フォークとはいえNPMライブラリデビューできたのは良かった。

自分は今はcz-customizeを使ってるので、使ってないけど今もすこーしダウンロードされてるようなので嬉しい。

その他

世に出したのはこれぐらいで、業務のわりと余裕がある時期にGASを使ってGitHubのプルリクとかをChatworkに通知されるWebHook作った。GASはスプシでデータ持てるし、タダでWebアプリ的なことができるから思ってるよりアイデア次第でいろいろ化けそう。このネタで外部でLTもしたっけ。

あとはRailsとVueでイベントのペライチのWebページを作れるWebアプリのプロトタイプも作ったっけ。これはいろんな技術の中で模索して、結局リリースレベルに持っていく前に頓挫してしまった。でもアイデアはアリだと思うのでいつかちゃんと形にしたい。

所感とこれから

こうしてみると仕事以外でそこそこ作ったなあ、と思う。実感としては「やってみた」「つくってみた」は凄い大事なんだけど、さらにちゃんと自分以外の人が使えるレベルまで自分なりに仕上げてリリースする、っていうのは本当に力になった気がする。ツライけど。

やってみたレベルだとローカルどまりでデプロイとか運用とかは考えなくていいので、そもそも設計も違ってきたりする。それに「人が使える」というレベルは自分が想像するよりけっこう遠い。自分はアイデアの発案だしUIもロジックも実装して、概念も把握してるから説明無しで使えるけど、いざ始めて人が使うとすると全然配慮が足りなかったりUIが悪かったりする。業務でやってると他の役割の人がカバーしてくれたりするけど独りプロダクトだと全部そういうとこまで見すえてやらなきゃいけない。

そういう苦労した経験が事実として今年後半になって仕事をするうえでもしっかり活きてきたなぁと実感している。

最近ブログコミュニティに入ってちゃんとブログをこうして書くようにしてるけど、作ってみたものはちゃんとリリースすると、文章のアウトプットにも匹敵するか、もしくはそれを遥かに凌駕するリターンがあるので本当にオススメです。ツライけど。

エンジニアになるときの他の会社の同期とか、今の会社の同僚とかを見てもブログとかにアウトプットしてる層もそもそも多くないけど、趣味でもリリースまでちゃんとやりきったアウトプットしてる人って本当にごく少数。それにはエンジニアリング力だけじゃなくてアイデアとか他の力も要求されるので簡単ではないんだけど、それにしても少数。

やっぱりユーザーが居たり使ってくれて「いいね!」ってくれる人がでてくると本当に嬉しいです。今も1つ作りかけてとりあえず実用できないこともないギリギリレベルまで来たので、来年もいろいろリリースまでちゃんとやるのを意識しつつ、さらにそこで得た知見を文章でもアウトプットしていきたい所存。

Firestoreを使うためにVuexFireを使ってちょっぴり悩んだ話

  1. 1. 入れかた
  2. 2. VuexFireのRootのMutationのみ対応
  3. 3. ライフサイクルフックはCreatedで

ちょっと業務でFirestore使ってみようかーみたいな話がでたもんで、おっじゃあちょっと使ってみようと思いまして。で実際使ってみたらアイデアが湧いてきたのでFirestoreを使った趣味Webアプリを作ってみてます。

その過程でVuexFireというライブラリを使ってみてちょっと苦戦したけど無事できた顛末

入れかた

まずVuexFire。

ここで注意したいのはVuexFireという名前だけど、場所はGitHubのvuejs/vuefireにあること。
もともとはVuexFireだったのがVueファミリーに組みこまれたのかな?

それで、注意すべきは入れかたは

npm install vuexfire@next --save
# or yarn add -D vuexfire@next

普通に入れるんじゃなくて@nextが必要なこと。

今の環境に対応するにはalpha版の@nextで入れないと使えないことに注意。
まずこれをちゃんと読まずに入れたら上手く動かずにウンウン唸ったあげく1時間ぐらい飛ばした。無念
。いつもどおりだなーとわかったふりじゃなくてちゃんとREADME読め案件ですね。

VuexFireのRootのMutationのみ対応

そもそもVuexFireはどんなライブラリかっていうとVuexのMutationでデータの変更先をFirestoreにて、Firestore経由でVuexのStoreを扱えするやつ。従来Action経由でMutationをコミットしてStoreを変更するのがMutation部分がまるっとVuexFireになるので、Actionから変更するようなイメージに近くなる。

で、Vuexの細かい話は割愛するけども、Vuexがそこそこの大きさになるとnamespaceで分割していくと思う。でもVuexFireではMutation直で読み込むため、Rootで設定しないとちゃんと動かないみたい。
良くみるとちゃんのREADMEにも書いてある。

VueFire Usage

良く探してみたらこの件についてちゃんと言及してるQiita記事があったので詳細はそこに譲りたいと思います。言及先でもあるようにちゃんとREADME読め案件ですね、読んだつもりじゃなくてちゃんと読むの重要。

ライフサイクルフックはCreatedで

Vue.jsで読み込み時に最初にデータをロードしたい場合、beforeCreateとかで読みこんだりするのが定石だと思う。特にaxiosなんかで外部から持ってくる場合はみんなそうやってると思う。

Nuxtなんかだと、fetchとかasyncDataが備わってるからあたりまえのようにやってるんじゃないかと思う。だからこう、いつもの癖で

export default class extends Vue {
fetch({params}) {
const ref = params //雑な例
this.$store.dispatch('setUsersRef', ref)
}
}

やっちゃってた。

これでウーンおかしいなぁ、データがロードされないぞーウーンウーン、あーでもない、こーでもないってやってたわけで、慣れてないのもあって試行錯誤してみたんだけど、全然そうじゃなくてちゃんとIssueに質問として挙がってた。

というわけで

export default class extends Vue {
async created() {
const ref = params //雑な例
await this.$store.dispatch('setUsersRef', ref)
}
}

createdでフックしなきゃいけないっぽいです。これに気づかずに2時間ぐらいは飛ばした。

ただ、最近のIssueを見てみるともっと早いタイミングでbindする方法も模索してるみたいで、ちょっと期待。とにかく今はcreatedでやるしかない。

なので、絶対にデータがある前提でもcreatedフックでbindしても実際のデータがロードされるのは表示領域が発生してからということもあると思うのでそこでエラーにならないように実装する必要もある。

これで使えるようになったけど、じゃあ実際にアプリを動かしてみるとVuexFireをメインで使っていくのがいいのかはまだちょっと不明。とくにロードのパフォーマンスというかドキュメントの取得回数的に。そのへんのことはまたそのうち書くと思うけど、firestore面白いけど、反面Productionレベルでの知見がまだまだ出てきてない(そりゃBetaだから当たり前かもだけど)。

使ってみた、はたくさんあるけど、デプロイ以降運用やパフォーマンス、設計のベストプラクティス、金銭的に効率の良い使い方とかプロジェクトの扱うドキュメントの数にもよるけど考えることは無数にある感じ。なので「使ってみた」に留まらずちゃんと人が使えるレベルまで落としこんで知見をどんどん身につけていきたい所存。

そろそろ本気でちゃんとブログを書こうと思った

  1. 1. 毎週ブログを書くSlackに参加した
  2. 2. ハードモードでスタートです
  3. 3. 共闘感
    1. 3.1. slackのおかげ?
  4. 4. 手助けできたこと
  5. 5. 気後れしますがやっていこう!

また随分と最後の更新から日があいたようで。
最近いろいろ思うところあって、アレでアレな現実をソバットで一蹴する生存戦略的な考えもあってアウトプットをいよいよ本腰いれて加速していこうと思いまして。
たまたまみかけたブログで紹介されてたのでとあるSlackに参加してみた顛末。

毎週ブログを書くSlackに参加した

「write-blog-every-week」というものなんだけど、まぁその名のとおり毎週ブログを書くことをやっていこうというやつ。

仕組みとしては

  • 書かない日がしばらく続くとたまにSlackBotから通知が来る
  • 書かない週が一定期間続くと強制的に退会になる
  • 他の人のアップしたブログ記事がFeedとして流れてくる

というわりと単純なもの。

そうやってリマインドがありつつ、Slackなので通知以外にもコミュニティ的に他のみなさんと話したり
ネタをシェアしてみたり、何か質問をしてみたりとして周ってるご様子。

一番のポイントはというと一定期間、つまり4週間更新がなく5週目になったら強制的に退会させられるということ。
新参者なので僕は知らないが、今までに退会した人はいるのだろうか……

ハードモードでスタートです

おそらく僕が見たブログ記事がバズったからだと思うんだけど、僕がこうして参加したのと同じにように、どうやら同時期に一気に人が増えたらしい。

当初は参加承認は自動でやっていたようだけど、急激な人数の増加と人数の増加によるフィードが多すぎたり、リマインドの緊張感の薄れなどを懸念されたようで、現在は一旦参加を締めきってしまった様子。

ちなみに参加だけされて結局自分のブログを登録されなかった人も幾人かいらっしゃったらしく、退会となっていったようです。このまま人数が落ちつけば再度募集もあるらしいです。

そして、さらにはそれまで強制退会までの猶予週間が4週間から2週間に改訂されるとのこと。

こいつはのっけからハードだぜ……

共闘感

で、実際参加してみて一番感じたのは共闘感。

これまでブログを書くっていう作業は完全に一人の作業で、どっちかってっとちょっとしんどい。書いても別にすごくバズるわけでもなく、どこかでフィードバックが貰えるわけでもなく。それでもなんかアウトプットにしないと自分からじんわり無くなっていくようなジレンマというか。

それが他にも同じような仲間と知りあって、ちゃっとしたり、反応しあったりしてる空間というのはそれだけで気が楽になるんだなぁ、と思った。

常時そんなバシバシチャットが交わされるわけではないんだけど、誰かが新しく記事を書いたり、こういうネタが、とかあったりして良い感じで刺激がある。

slackのおかげ?

もしかしたらそれもSlackのおかげで、Slackだと絵文字アイコンのリアクションがとりやすくって
だれかが反応したら自分も同じく反応できやすい。

自分の発言として流れるわけではなく、あくまでも誰かのリアクションに賛同みたいなライトな感じがとても居心地がよくて。乗っかれる気軽さってすごい。

いつも業務では某ChatWorkなんだけど、同じようで実は大きな差異なんだなぁと思い知った。
あとはMarkdownに準拠した記法とか。なんか独自タグみたいなのじゃないのってすごく楽。
弊社、某ChatなんとかとかいうのからSlackに乗り替えてくれないかなぁ……

Slack今まで軽くは使っていたけど今回初めてちゃんと使ってこうも良いものかと知れたのは大きい。
常々僕自身、コミュニケーションをポジティブに回すためにシステムで手助けできることはある、と思っていたのを今回あらためて実感できて良かった。

手助けできたこと

先日、たまたま家の都合で休みをとって自宅で趣味開発してたときに、
「Twitterで自分の記事がシェアされたときに補足するのはどうしてる?」
という話題があがっていて、僕はTwitter検索でurl:blog.solunita.netみたいにしてますよーという返信をした。

しかしながらどうも件の方のブログのURLだと検出されないようでなんでだろうと思っていろいろ検証した結果、どうもurl:で検出したい対象を指定するとき、指定対象(URL)に-が入ってると上手くいかないようだった。例えばURLがwww.example-jp.comのような場合。

検証の結果、url:"www.example\-jp.com"みたいにクォートで囲んでやるとバックスラッシュでエスケープが効くようになるということをつきとめて解決できた。

Twitterの検索は公式でもあまり多くを言及してない印象だけど、それでもそこそこ高機能で、それ以外にも基本的には後方一致だったりもする。なのでサブドメインをまたいだ検索とかも結構楽。

あと、-from:AquiTCDでAquiTCDさんからのツイート以外(つまり自分発信じゃないものだけ)、みたいなのもできるし-rtでRTを弾くこともできたり。

ちなみに言えば僕はTweetDeck派なので、自分のブログのほか、自分が趣味でつくったアプリとか
chrome拡張とかを全部ORでつなげたごった煮な検索式でカラムを作ってウォッチしてるだけで事足りてるが、話題に上ったのはIFTTで通知をする方法とか。

Twitterの検索結果をIFTTに通知するのはすごく簡単なので、僕は天気予報とかで雨の時だけLINEに飛ばしてたりする。

気後れしますがやっていこう!

僕なんかでも参加してすぐに他の人の役にたてたり、まわりでも奮闘してる仲間がいて嬉しい反面、そればかりではなく。

このブログは技術以外の内容も書く雑記ブログなので「技術的なアウトプットをしようよ」みたいなところで全然関係ない話をアップしていいものかと躊躇する。

躊躇するものの、筋トレと同じく「まずは体裁はどうであれ、習慣化することに主眼を置くべし」と思って、これから本腰入れてがんばっていこうと思います。