メモ

@adachi_koichi

仕事の進め方(Web系エンジニア)

チーム内で仕事の進め方について話す機会があったのでまとめたみた。
大切にしてるコンセプトは
集合知を活かして非効率な仕事の発生確率を下げ、その結果みんながハッピーになるための時間を増やす。」

前提

  • Webサービスやアプリを作っている開発チーム
  • 全員がフルスタックエンジニア
  • 作っているのはB2Bシステム
  • リリース済みのシステム

目指している方向

  • 各自が判断してガツガツ仕事をこなせるチーム
  • 全てチーム内で判断するのは現実的ではないので、あくまで自己組織の範囲がちょっと広い状態
  • 1から10までマネージャーに聞かなくても仕事を進められる状態にしたい

という前提条件。

結論から書くと、
いくつか案を出して比較検討。レビューを入れて集合知の良さを活かす。
というのが大切。

実装はレビューが入りますが、そもそも その実装で筋が良かったんだっけ? ってことが意外に抜け落ちます。
思いついたから比較検討せずに実装。ってことをやってしまうと、
工数がかかったり、機能追加・実装・テストがしづらい構造になったり、後から結局作り直しを検討せざるを得なくなります。
その結果、無駄なことに時間を取られる確率が高くなる。

もしくは言われたことだけやるケース。
担当者が、他の人(Aさん)が言ったことをそのまま間に受けて進めると、
Aさんが気づかない設計の穴・思った以上に実装難易度が高かった・・・
などに気づかずに進めてしまうケースがあります。
この場合は長考するケースも多く、 かけた労力/時間の割りにプロダクトへの貢献が小さい ・・・ってことに繋がってしまいます。
そうなると、せっかく使った時間がもったいない。

仕事の進め方に気をつけるだけで、たくさんの時間が生まれます。
そして心に余裕が出来、成長スピードが加速。
プロダクトへの貢献も大きくなります。

というわけで、まとめた仕事の進め方はこれ。

# 設計・検討フェーズ  
- 実現したいことを把握する  
- 設計案をいくつか出す  
- それぞれの案のメリット・デメリット、実現できること・できないことを洗い出す  
- それぞれの案の工数を洗い出す(期間・時間/日数)  
- 上記の案を複数人で検討  
- 複数人で設計の穴を見つける  
- 複数人で「実はxxxを解消したら第三案が一番いいのではないか?」的なことを考えてみる  
- どれにするか決める(工数・筋の良さ・実現可能性・メンテコストなどを考慮)  

※複数人で考えるかどうかはタスクによります。
ボタンの位置修正だったり、簡単・個人が判断しても構わないものとかはサクッとやっちゃえばいいので。

※技術的な検証が終わらないと分からないこともあると思うので、
検証タスクに時間がかかるようなら、それは方針を決める前に別タスクとして調査するのかなと。
(例えば、Pub/Sub使った方が良さそうなんだけど、使ったことがないのでどれくらいの工数になるか分からない。なので取りあえず触ってみる・・・とか)
仕事の進め方について話す機会があったのでまとめたみた。
大切にしてるコンセプトは
集合知を活かして非効率な仕事の発生確率を下げ、その結果みんながハッピーになるための時間を増やす。」

前提

  • Webサービスやアプリを作っている開発チーム
  • 全員がフルスタックエンジニア
  • 作っているのはB2Bシステム
  • リリース済みのシステム

目指している方向

  • 各自が判断してガツガツ仕事をこなせるチーム
  • 全てチーム内で判断するのは現実的ではないので、あくまで自己組織の範囲がちょっと広い状態
  • 1から10までマネージャーに聞かなくても仕事を進められる状態にしたい

という前提条件。

結論から書くと、
いくつか案を出して比較検討。レビューを入れて集合知の良さを活かす。
というのが大切。

実装はレビューが入りますが、そもそも その実装で筋が良かったんだっけ? ってことが意外に抜け落ちます。
思いついたから比較検討せずに実装。ってことをやってしまうと、
工数がかかったり、機能追加・実装・テストがしづらい構造になったり、後から結局作り直しを検討せざるを得なくなります。
その結果、無駄なことに時間を取られる確率が高くなる。

もしくは言われたことだけやるケース。
担当者が、他の人(Aさん)が言ったことをそのまま間に受けて進めると、
Aさんが気づかない設計の穴・思った以上に実装難易度が高かった・・・
などに気づかずに進めてしまうケースがあります。
この場合は長考するケースも多く、 かけた労力/時間の割りにプロダクトへの貢献が小さい ・・・ってことに繋がってしまいます。
そうなると、せっかく使った時間がもったいない。

仕事の進め方に気をつけるだけで、たくさんの時間が生まれます。
そして心に余裕が出来、成長スピードが加速。
プロダクトへの貢献も大きくなります。

というわけで、まとめた仕事の進め方はこれ。

# 設計・検討フェーズ  
- 実現したいことを把握する  
- 設計案をいくつか出す  
- それぞれの案のメリット・デメリット、実現できること・できないことを洗い出す  
- それぞれの案の工数を洗い出す(期間・時間/日数)  
- 上記の案を複数人で検討  
- 複数人で設計の穴を見つける  
- 複数人で「実はxxxを解消したら第三案が一番いいのではないか?」的なことを考えてみる  
- どれにするか決める(工数・筋の良さ・実現可能性・メンテコストなどを考慮)  

※複数人で考えるかどうかはタスクによります。
ボタンの位置修正だったり、簡単・個人が判断しても構わないものとかはサクッとやっちゃえばいいので。

※技術的な検証が終わらないと分からないこともあると思うので、
検証タスクに時間がかかるようなら、それは方針を決める前に別タスクとして調査するのかなと。
(例えば、Pub/Sub使った方が良さそうなんだけど、使ったことがないのでどれくらいの工数になるか分からない。なので取りあえず触ってみる・・・とか)

整えた自宅でのリモートワーク環境

タイトル

整えた自宅でのリモートワーク環境

概要

リモートワークを始めて、一旦自宅の環境が落ち着いてきたのでメモ

背景

  • 会社全体でリモートワークが始まった。もちろん私のチームも。
  • 家では作業環境がなかった(必要もなかった)ので、マシンを置くスペースが必要になった。
  • アプリを作る仕事をしているので、どうしても機材やケーブルが多く、ごちゃごちゃしがち。机が狭くなる。
  • ストレートネックの頭痛持ちなので、作業しやすい姿勢にすると仕事の効率がかなりアップする。

ことから、机周りを中心に改善してみた。

コンテンツ

スタンディングデスク

元々職場ではアームで高さを出して立ったまま仕事をしていた。
自宅ではダイニングテーブルで仕事をしていたけど、
今回を機にスタンディングデスクにしてみた。

f:id:delightone:20200423110441j:plain
スタンディングデスク

自分の肘の位置を基準に机の面の高さを調整できるため、楽な姿勢で仕事できる
立ちっぱなしで疲れたら、丸椅子で小休止。
ガッチリとした椅子は場所を取るので、スタンディングデスクにして正解だった。

スタンディングデスクは重量があるため、床の保護目的で防音ジョイントマットを敷いた。
一日中床に立ちっぱなしよりは、楽な気がする。
会社ではクロックスを履いて立ちっぱなしだったけど、感覚的には同じくらいの疲労度。

スタンディングデスクはすごく良かった。
ただ、それだけだと目線とモニタの高さが合わず、
ずっと首を曲げて作業しなければならなくなる。
そこで、モニターアームを使用。

モニタアームで目線に合うように位置を調整

f:id:delightone:20200423122400j:plain
iMac用のアーム

普段はノーマルiMacを使用している。VESAマウント型でもない。
そうすると、iMacをVESAのアームに取り付けることができないのだけど、
iMac用のモニターアームを見つけたのでそれを使っている。

スタンディングデスクと組み合わせると、天井くらいまで高くできた(やらないけど)

分割キーボード

f:id:delightone:20200423110617j:plain
分割キーボード(Ultimate Hacking Keyboard)

肩こりがひどいので、以前から分割キーボードを使っている。
最終的にはパームレストがついているこのこのキーボードに落ち着いている。
専用のTrackPadやTrackPointモジュールも発売予定だけど、
しばらくは

  • UltimateHackingKeyboardのマウス操作モード
  • ピンチ操作をしたいときだけTrackPad

という使い分けをしている。
Macbookを使う時も、基本はKarabiner-Elementsでキーボードをマウスポインタ操作に割り振っていて慣れているので、
一日のほとんどの時間、TrackPadを触ることはない。

自分の肩の関節の位置に左右のホームポジションがあると肩こりしにくいことが分かった。

CO2メーター

f:id:delightone:20200423110605j:plain
CO2メーター

職場でも計測していた二酸化炭素測定器。
経験上、二酸化炭素濃度が高いとパフォーマンスが落ちる気がしたため、常に表示している。
(就寝時にも濃度が高いと回復しにくい気がした。)
これも両面テープで貼り付け。
机を置いた場所が、たまたまた換気口のすぐ近くだったのがラッキー。
ちょうど部屋の位置の対角にあるキッチンの換気扇を弱モードで一日中回している。
そうすると、一日を通して600ppmを超えることがなくなった。

さらに、一日中家にいるので、余っていたPM2.5フィルタを全ての換気口に取り付け。
1週間もするとかなり汚れていた・・・
が、特に効能は感じてない。
フィルタに汚れがついてるってことは、部屋に入るはずだったチリが入らなくなったってことかな?
計測する方法がないけど、まだ余ってるので引き続き使ってみる。

加湿器・エアコン

4月の上旬はまだ寒い日もあり、弱目にエアコンをつけている。
弱とはいえ乾燥はするので加湿器は必須。
50%を目指して加湿しているけど、強くない加湿器なので
エアコンを強風にすると40%を下回ることも多い。
今シーズンはこのまま使い、冬になったら大型の加湿器に変えた方がいいかな?

SideCarでセカンドディスプレイ代わり

f:id:delightone:20200423123735j:plain
一日中見る視界

iPadをセカンドディスプレイ代わりに使っている。
もちろん手書きメモを取りたい時はiPadOS上のOneNoteを起動するけど、
それ以外の時間はセカンドディスプレイとして使っている。
主な用途は

  • AndroidエミュレーターiOSシミュレーターを表示
  • IDEの検索結果ウインドウだけSideCarで表示
  • Chromeのinspector、Charles、流しっぱなしにしたいログをターミナルで表示
  • macOSPreviewアプリで、注釈をつけたりといった画像編集(ApplePencilが使えて便利)

など、メインのIDEは表示しっぱなしにしたいけど・・・って時に便利。
使ってるのはiPadPro11インチ。ほとんど持ち運びはしないので、買い換えるタイミング(来るのかな?)があったら12.9インチを買うと思う。

机の上に置いただけだと首が疲れる。そのためタブレットスタンドで高い位置に置いている。
メガネケースでさらに微妙な位置調整。

USBハブを両面テープで貼り付け

ケーブルをまとめる意味合いも含まれる。
- iMacのポート類は背面にのみ
- 機器の都合上、ケーブル抜き差しではなくオンオフで機器の接続を管理したい
という理由から、USBハブを二つiMacの前面に貼り付けた。
スタイリッシュではないけど便利。

f:id:delightone:20200423124323j:plain
USBハブを二枚重ね

ケーブルをまとめる

f:id:delightone:20200423110736j:plain
机の裏に電源タップ

モバイル開発をしていることもあり、ケーブルが多くなりがち。
机の上にケーブルが散らかっていると、

  • 使える面積が減る
  • ごちゃごちゃする

というデメリットがあるため、なるべくケーブルをまとめている。

  • 電源タップ類はなるべく机の裏や見えない位置に配置。
  • iMacの背面にケーブルを貼り付け。

まだプラプラしてるけど、仕事には影響ないので、気分転換したくなった時に整理しよう。

サブマシン(長時間ビルド及びテレビ会議用のマシン)

古いマシンをテレビ会議・チャット用のマシンとして使っている。
私のチームでは一日中テレビ会議サービスを繋げっぱなしにしているので、
地味にマシンパワーを使ってビルドが遅くなる。
カメラが捉える構図を自由に変更できるのもメリット。
なるべく室内は映さずに、自分+壁が映るようにしている。
DuetDisplayでサブモニタ化を試してみたけど、遅延が発生したり
文字がくっきり見えなかったのでサブマシンをモニタに転用するのはペンディング
アームで浮かせているので机を広く使える。
開発中に検証用の端末を並べたりするので、そのスペースを確保できるのもよかった

f:id:delightone:20200423110703j:plain
サブマシン

まとめ

腕の高さと目線の高さを自由に調整できるスタンディングデスク+アームは最強の組み合わせで、
さらに分割キーボードを使うと疲れにくく仕事ができる。
予定外の出費は痛かったが、何時間でもコーディングできることを考えると安い。 その結果、一日14時間くらい仕事しちゃうのだけど、
エンジニアとしての成長に時間を使えるようになったから、まーいいかな。

複数のツールを組み合わせて実現する、高効率なリモートワーク環境の構築メモ

タイトル

複数のツールを組み合わせて実現する、高効率なリモートワーク環境の構築メモ

概要

リモートワークをやってみて、一旦開発スタイルが落ち着いたのでメモ

4行でソリューションを要約

  • コミュニケーションを取りやすくするため、カメラをつなげっぱなしにする(音声オフ)
  • ずっと顔が映っていると恥ずかしいため、普段はカメラを半透明な何かで隠す
  • 同時に何組も話せるように、Discordで音声ルームをいくつか作っておく
  • チーム内限定のホワイトボードをOneNoteで作る

背景

新型コロナウイルスの影響でチーム全員がリモートワーク前提の職場に変わった。
全員リモートワークという状況に適応したチームを作るには? というテーマに、

  • メンバー同士がまるで近くの席にいて、話しかけやすい雰囲気を作る
  • チームで仕事をしている という雰囲気を維持すること
  • リモートワークにより通勤負荷が無くなった。むしろ今までよりも効率よくアウトプットを出すことができるのでは?

上記の観点で向き合った。
試した結果をメモ

コミュニケーションを取りやすくするため、カメラをつなげっぱなしにする(音声オフ)

ソフトウェア開発のチームなので、以前からもSlackで全員オンラインになっていたが、
全員が自宅勤務だと他の人の雰囲気を知ることができなくなった。話しかけて良さそうな雰囲気だったりとか。(※1)
そこで、常にテレビ会議サービスを繋げっぱなしにしてみては?と思い、チームで試してみた。(※2)

  • 顔が見えていると、話しかけていい雰囲気かどうかを感じることができる
  • 職場で働いているかのような、すぐ近くに同僚が働いている という感覚になる
  • 雑談からの議論が活発になった というメリットがあった

f:id:delightone:20200420120644p:plain
リモートワーク

ただし、テレビ会議サービスをそのまま使うだけでは別の問題が発生。

ずっと顔が映っていると恥ずかしいため、普段はカメラを半透明な何かで隠す(ビニール袋とテープ)

PC内蔵カメラでずっと自分の顔が映っていると、
常にドアップで恥ずかしい 😔
という声が上がってきた。
常に顔を見る必要はなく、みんなの雰囲気だけ知ることができればいいため、
カメラで映す映像が、すりガラス越し のようになればいいのでは?と考えた。
リアルな会議室の目隠しや建物のエントランスにあるような、あれ。
であればソフトウェア的に処理するか、半透明の何か を貼り付ければ済むのでは?という考えに至り、
ビニール袋をテープで貼り付ける
という方法で対応。
結果、ビニール袋をクシャクシャにしてから貼り付けたらちょうどよく半透明になり、
すりガラス越し見える人影 状態を作ることができた。

f:id:delightone:20200420142600j:plain
スーパーの透明な袋を切って雑に貼り付け
f:id:delightone:20200420142237j:plain
ぼやけた映像とSnapCamera

すりガラス状態にするにはビニール袋以外でもよく、
透明なクリアファイルを2枚ほど重ねて貼り付けてもいいですし、
凹凸のある半透明なプラスチック(コンビニ弁当の蓋)を貼り付けてもよかった。

ソフトウェア的に処理する方法、例えばSnapCameraのようなカメラ映像にリアルタイム加工を加えるようなソフトを使えば、
上記のように物理的に解決する必要はなくなるが、
ソフトウェア処理はパソコンに負荷がかかるので、開発に使うマシンで起動すると作業効率が悪くなる。
テレビ会議専用に使っていないパソコンを用意するのもありだけど、
パソコン好きでもなければ、複数台のPCが家にあるのは珍しく現実的ではない。

結局 ビニール袋をセロハンテープで貼り付ける という方法で落ち着いた。

上記のような対策をすることで、全員が常にテレビ会議サービス上でオンラインになっても気にならなくなったが、 今度は音声の問題が発生。

同時に何組も話せるように、Discordで音声ルームをいくつか作っておく

f:id:delightone:20200420125640p:plain

常にテレビ会議システムでオンラインになっていると、

  • 聞かなくてもいい話まで聞こえて集中を阻害する
  • テレビ会議システム上で、複数の組み合わせで同時に話すことができない(2人で話している時、別の2人が更に会話するなど)

という問題が発生。 どうしようかと考えていたら Discordだと複数の音声ルームを作れる ことを教えてもらい、使ってみた。

どのように運用するかというと、

  • 普段は上記画像のように 勤務中 音声ルームに入る
  • 雑談が始まったり声をかけたりしたら、別の音声ルームに移動
  • 話が終わったら、また勤務中ルームに戻る
  • 直接関係ない話であっても、他の人は出入り自由

テレビ会議サービスでも画面共有をすることができるが、
Discordでは何人でも同時に画面共有ができるので、
あれこれ話しながらやり取りするのはDiscordが便利だった。

音声と画面共有はDiscord。映像はその間もテレビ会議サービスで共有。 表情はテレビ会議サービスで見えるので雰囲気も伝わる。

ところが、使っていると仕事の効率を落としているものに気づいた。 現実世界では気軽にできていた、手書きで説明する ができなくなっていた。 毎回手書きをするわけではないけど、地味に不便🤔

チーム内限定のホワイトボードをOneNoteで作る

たいていのテレビ会議システムは簡易的なホワイトボードが存在する。 ただ、 ペンの種類が少なかったり、 消しゴムの種類を選べなかったり、 拡大縮小、ホワイトボードのサイズを後から変更するなどができなかったり。

(自分の感覚では)クラウドホワイトボードサービスはどれも扱いづらいものが多く サクサク描けなかったのでどうしようか考えていた。

そこで、普段から自分用のメモに使っているOneNoteチーム用のNotebookを作って共有 したところ、これが思いの外よかった。

f:id:delightone:20200420125125j:plain
OneNoteiPadmacOSで表示

  • 描いた線が1秒以内に他の人の画面に表示される。
  • iPadに適した書き心地
  • ペンの種類がかなりある。消しゴムも複数のタイプがある
  • 拡大縮小、描いた物を後から移動できる
  • PCでもOneNoteを表示しておけば、大画面でメモを表示できる
  • テキスト入力がiPadのキーボードでも、PCのキーボードでもどちらからでもできる

全員にMicrosoftのアカウントが必要(無料だけど)
Note単位ではなく、Noteの集合体のNotebookでしか共有することができない
若干使いにくいと感じるのは上記2点くらい。

Note単位でサクッと共有できたらかなり使い勝手がよくなるけど、改修予定はあるのだろうか?

気になって調べてみた(ネットワーク)

テレビ会議サービスとDiscordを常時使うと
実際のところネットワーク帯域はどれくらい使うことになるのか。
macOSのActivityMonitorで見てみた

下り
通常時 30KB〜300KB/s
テレビ会議サービスで画面共有時 50KB/s

上り
60KB〜100KB/s

前提条件

  • 普段オンラインなのは8人
  • テレビ会議サービスは音声オフ
  • Discordは話すときだけ音声オン

活発に話している間は下り帯域を300KB/sほど使っていた。
画面共有をするとむしろ他の人のカメラを表示しなくなるせいか、
25〜30KB/sくらいまで帯域を使わなくなった。

まとめ

工夫して常時オンラインをすることで、職場と変わらない状況を実現することができた。
むしろ、職場では席が離れている人には話しかけづらかった という問題があったが
全員が等距離で雰囲気を知ることができるようになったため、
その時々で適した人に話しかけやすくなった
という声も聞くようになった。

通勤時間やそれにかかる負担もなく 室内の環境は各自で調整できるリモートワーク。 トイレの個室に順番待ち・・・・といった無駄な時間も無くなった。

結果、私のチームはリモートで快適に仕事をすることができるようになった。 もうしばらく在宅勤務は続くと思われるので、しばらく経ったらまたメモしよう。

※1 雰囲気というか、適切なタイミングで議論ができるようにする工夫は、別のベクトルとして考える必要がある
※2 Discordは複数のルームでテレビ会議ができるようになったが、 まだパソコンへの負荷がかなりかかるので、別のテレビ会議サービスを使っている

会社で自作キーボードのコミュニティを作った話

会社で自作キーボードのコミュニティを作った話

f:id:delightone:20181212232456j:plain

この記事は自作キーボード #2 Advent Calendar 2018 13日目の記事です。

導入

自社でWebサービスを作っている職場で普段プログラムを作っている私は、
以前からキーボードに興味を持っていました。
最初はMacbookの日本語キーボードを使い、
その次は同僚達の勧めでUSキーボードのMacbookに変更。
それからしばらくは上記のMacbookを使っていましたが、
肩こりの解消にはならなかっため、分割キーボードの購入を考えていました。

ただ、分割キーボードを買ったところで使わなくなるともったいないなと思い、
2017年には Apple Magic Keyboard を1台追加購入。
それまで持っていたものと併せ、Magic Keyboard 2台 + Karabiner で擬似分割キーボードを使うようになりました。

f:id:delightone:20181212233204j:plain
私の机。Magic Keyboard 2台

その後 Let's Split を初めて購入し、自作キーボードの世界に足を踏み入れました。
一度自作キーボードをゲットしてしまうと、気がついたらMassDrop、AliExpressなどの通販サイトで
キーボードキットやパーツをポチポチするようになっていました。

きっかけ

周りはエンジニアだらけの職場なので、当然 HHKBRealforce に限らず外部キーボード
を使う人は多く、キーボードという道具はそれぞれ拘りをもって使っている道具になります。

私の会社には、誰でも自分の望むキーボード、マウス・トラックパッド、PC、モニタ、ソフトウェアライセンスなどを購入できる仕組みである グッジョブ という制度があり、 それを利用して各々自由に申請して購入。日々の開発に使用しています。
この制度は 個人個人でそれぞれ違う、やり易いと感じる開発環境を整え、仕事にコミットできる環境を作る 制度です。
使いづらい開発環境でプログラミングをし続けることは非効率的->人件費がもったいので、理にかなっている仕組みだと言えます。

ただ、普段から色々なキーボードを試すことの多い私の職場の同僚たちでも、 既存のキーボードではどうしてもどこか使いづらい と感じることがあり、
その中の数人から 無ければ作れば良いのでは という意見を聞くようになりました。 無ければ作る。 まさにエンジニア的な発想だったわけです。

ここ最近

最近自作キーボードが活発になったおかげで選択肢が増え、Let's Split, Helix, Mint60 などを始めとしたキットも簡単に手に入るようになりました。
ビルドブログも多数存在し、未経験でもキーボードを作りやすい有難い状況です。
そんな中、キーボード話で盛り上がっていた同僚二人から Dactylを作りたい という話を聞いたので、
上記の グッジョブ で購入することにしました。

f:id:delightone:20181212232627j:plain
3Dプリンタ開封
機種選定は XYZ printing Da Vinci Pro 1.0
- 20cm x 20cm x 20cmを印刷できる
- ブログなどの情報が多い
- 箱型
などの理由から選んだのですが、これが苦行の始まり。(キャリブレーション地獄)

それでも何とかDactylの筐体を何パターンか出力し、
今はDactyl Manuformを作っています。
私は完全オリジナルの形のキーボードを楽しみながらモデリングしています。

f:id:delightone:20181212233707j:plain
DactylManuform

自作キーボードを会社で組み立てるようになってから、それがきっかけで交流が増えました。

f:id:delightone:20181212234752j:plain
会社のカフェ。開発集中エリア

今は毎週、会社のカフェで半田ごて片手におしゃべりしながら作ってます。
エンジニアの仕事道具としてだけではなく、
会話のきっかけになる自作キーボード。
このようなコミュニティは組織の活性化としても良いのではないでしょうか。

generate kotlin.js.map Kotlin/JS sourcemap for gradle build

default target file is .js file only. add setting .js.map to build.gradle.

before

 path.endsWith(".js") && (path.startsWith("META-INF/resources/") || !path.startsWith("META-INF/"))

after

 (path.endsWith(".js") || path.endsWith(".js.map")) && (path.startsWith("META-INF/resources/") || !path.startsWith("META-INF/"))

build.gradle example

task assembleWeb(type: Sync) {
    configurations.compile.each { File file ->
        from(zipTree(file.absolutePath), {
            includeEmptyDirs = false
            include { fileTreeElement ->
                def path = fileTreeElement.path
                (path.endsWith(".js") || path.endsWith(".js.map")) && (path.startsWith("META-INF/resources/") || !path.startsWith("META-INF/"))
            }
        })
    }

    from compileKotlin2Js{
        kotlinOptions.sourceMap = true
        kotlinOptions.sourceMapEmbedSources = "always"
    }

    from compileKotlin2Js.destinationDir
     into "${projectDir}/web"

    dependsOn classes
}

setup Raspberry pi zero w without monitor and keyboard

download image

2017-11-29-raspbian-stretch-lite.zip
from https://www.raspberrypi.org/downloads/

format sd card

SD Memory Card Formatter for Mac https://www.sdcard.org/downloads/formatter_4/eula_mac/index.html

install Etcher

https://etcher.io/

write image by execute Etcher

edit cmdline.txt

add modules-load=dwc2,g_ether after rootwait

rootwait modules-load=dwc2,g_ether quiet 

edit config.txt

add dtoverlay=dwc2 bottom of file

enable ssh

in boot folder

$touch ssh

access via ssh

ssh pi@raspberrypi.local

wifi setting

/etc/wpa_supplicant/wpa_supplicant.conf

country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
  ssid="hoge"
  psk="hogepass"
  id_str="ac1"
}

network={
  ssid="fuga"
  psk="fugapass"
  id_str="acc2"
}

other command

#setting
$raspi-config

#reboot
$sudo reboot

#shutdown
$sudo shutdown -P 0

update

sudo apt-get update
sudo apt-get upgrade

guard patterns in Kotlin

    fun main(args: Array<String>) {

        val thingIntOpt:Int? = 0

        if (thingIntOpt == null) return
        val something0 = thingIntOpt?.takeIf { it < 10 } ?: return

        val thingStringOpt:String? = "hoge"
        if (thingStringOpt !is String) return
        val something1 = thingStringOpt?.let { "hello" } ?: return
        val something2 = thingStringOpt ?: return
        val something3 = thingStringOpt?.apply { println(this) } ?: return


        val thingStringOptInline: String = "hogeInline" as? String ?: return
        println(thingStringOptInline)

        val thing: String? = "fuga"
        val notNullThing = thing.guard { return }
        println(notNullThing)

    }

    inline fun <T> T.guard(block: T.() -> Unit): T {
        if (this == null) block(); return this
    }