2022年を振り返る
これはなに
- 今年も1年お疲れ様でした
- CTOに就任して1年経過し、5月からは取締役CTOになった
- 来年も「売上と開発の課題を同時に解決しつづける組織」にするために最善を尽くす
目標は達成できたか
ちょうど1年前に CTOになった経緯とその決意を書く - kurotyannの覚え書き を書いた。 書いた目標すべてに試行錯誤をして成果を得た。しかし、途中でこの目標の一部は方向転換が必要になった。
今年の4~5月頃に親会社から独立した。 プロダクト、組織、経営、カルチャーなど会社のすべてに手を加える必要がでた。 社内では第二創業期と呼んで新たなスタートをきった。
外部に向けた象徴的な変更だと、会社ロゴ、コーポレートサイト、会社のビジョンをリニューアルした。 さらに、プロダクトを1つ親会社へ譲渡した。
このタイミングで自分もCTOから取締役CTOになった。 経営判断に技術視点が必要だと感じ、経営サイドへも挑戦することにした。 今年1番の挑戦だったし、今後の目標達成に必要な選択だった。
来年の目標
冒頭にも書いたが、「売上と開発の課題を同時に解決しつづける組織」にするのが目標です。 おそらく今の立場を継続する限り、この目標が変わることはなさそう。
CTOに就任した当時は、技術負債や組織コミュニケーションの改善に注目してた。 これらはもちろん必須だが、会社のP/Lと連動した決定でないと解決のインパクトが小さい。 あと、今の自分にできることに注目しすぎたと反省もした。 自分が技術や決定のボトルネックにならないよう、常にGo Higherしないとダメだった。
ずっと売上と利益が伸び続ける前提なら、いくらでも好きにやれるが、あらゆる課題がそれを阻んでいる。 経営と技術の両面から根本を解決するには、役員という立場に自らを置かないとダメだった。
技術への理解不足を嘆くエンジニアもいるが、エンジニアが技術以外の立場に歩み寄る選択肢もあると思う。 あらゆる経験はスキルアップになり、デカいことやるなら、チームが必要だ。
とはいえ、コードを書いてサービスを開発するなら、エンジニアの個々の技術力とプロダクトの開発環境がベースで整ってないといけない。 そして、これはエンジニアが率先してやらないといけない。一方ではなく両方やるし、チームと個人どっちだではなく、両方だし同時だ。 これらを可能にするには、解決のインパクトが大きい課題(いろんな問題が芋づる式で解決される「解の重心」となる課題)にリソースを全集中できるようにトップが頑張らないとダメだ。
なので、最後に一言いうなら「家族に迷惑かけないレベル」で最善を尽くします。良いお年を。
2021年の人生を振り返る
これはなに
- 公私ともに大きなイベントがあった1年だった
- 今年からフォーマットを変えて、目標の振り返りと、来年の目標設定に変更した
目標は達成できたか
去年の振り返りブログで宣言した、今年やりたいことは以下の2つだった。
- Kipping Bar Muscle-Upができるようになる
- バイリンガルニュースでマイケルが言っていることを7割わかるレベルになる
Kipping Bar Muscle-Upは夏頃にできるようになった。肩への負担が怖くて連続は無理だけど、1回でもできたことが嬉しい。 また夏にできたから、その後はpistol squatに変更してこれも安定してできるようになった。 これでopen gamesの予選メニューで出来ない種目は、逆立ち歩きとRing Muscle-Upの二つぐらいかと思う。
ただ、CTOになった直後に業務がガッと忙しくなり、トレーニングの負荷を下げた時期が続いてしまった。 最近は業務にも慣れ、少しずつ強度を上げている。でも、結果はイマイチ。 来年2月の2022 NOBULL CrossFit Openにエントリーはするけど、去年より成績が悪くなりそう。 RxでWODを完遂できなくても、Rxで出来る種目には挑戦する。
一方、英語はマイケルの言っていることが相変わらず聞き取れない。そもそも公私の変化で英会話を夏頃にやめてしまった。 英語より優先すべき課題があったり、夏から同棲のために引っ越しをし、パートナーとの時間をさらに大切にしたくなった。 英語は嫌いではないが、プライベートやcrossfitや本業よりも優先したくはないので、来年の目標からは外す。
来年の目標
- 逆立ちができるようになる
- CTOになった経緯とその決意を書く - kurotyannの覚え書きのとおり、目標に向かってあがく
- 上の二つを理由に家族やパートナーの時間を犠牲にしない
去年の振り返りで
2021年も「自分をさらに鍛えて、私生活を充実させつつ、仕事でも成果を出す」年にします 💪
と書いて締めくくっていた。たぶん、ずっとそうなんだろうと思う。 仕事が忙しくても、英会話のようにcrossfitをやめることはなさそう。
ただ、最優先は家族やパートナーになった。 自分の家族やパートナーを大事にしないと、一緒に働く人の家族やパートナーも大事にできない気がする。 CTOは精一杯やるけど、それはトレーニングとプライベートが充実していることで成立し、そこから成果に結びつくと考える。 この考えを忘れずに来年も前進するぞ!
良いお年を!🎍
CTOになった経緯とその決意を書く
これはなに
- 責任ある仕事に就いたので経緯と決意を残したかった
- 会社とは独立して自分の決意を優先した文章を書きたかった
- 来年は決意に共感してくれる人を増やしたい
課題を解く意思
今年の初めに急成長中の会社に所属する優秀なエンジニアと軽く立ち話をする機会があった。 話題は、自分が大学のアルバイト時代に遭遇した「非効率な業務」だった。 どんな流れでその話題になったかは忘れたが、ただの雑談としか自分は思ってなかった。 彼が「どうすればそれは解決できるかな...」と言うまでは。彼はまさに絵文字の 🤔 のように考え出した。
軽い立ち話での雑談だ。しかも、10年以上前の大学のアルバイトの話だ。 取るに足らない話題なのは明白だ。 ただ、彼の表情からは課題を解いてみようとする意思が伝わってきた。 「ああ、ここに大きな差があるんだな」と自分は悟ったのを強烈に覚えている。
本質的な課題に向き合えない日々
さきの出来事は今年の2月ごろだった。それからずっと課題を解くことを意識してきた。 ただ、解こうとする課題がどこか的外れで本質的ではない気がしてならなかった。
必要なことだし無駄なことではない。でも、クリティカルではなくインパクトがない。 そんな課題をちょこちょこ解こうとする感じだった。
本質的な部分が見えてないわけではなかったと、今振り返ってそう思う。 ただ、解くために必要なスキルと向き合い方が全くわからなかった。 当時はスキル不足だと思い、得意とするモバイルからインフラやサーバーの課題に挑戦していた。
本質的な課題に向き合うチャンス
今年の9月だった。CEOから「会社の技術力を上げてほしい」と依頼された。 このとき本質的な課題への向き合い方が見えた気がした。 今までは組織の中での「視点、視野、視座」が定まってなかったんだと。
CEOからはCTOの言葉はなかったが、詳細を聞くとCTO以外に適切なポジションはなかった。 CTOと言わなかったのは自分が入社2年目であり、会社にCTOがいたことがなかったからだろう。
依頼されたMTGで、CEOからの依頼を承諾した。 ただし、条件に以下を提示した。
- 入社歴の長いエンジニアリングマネージャーをVPoEにすること
- CTOとVPoEでCTO室を設立して、二人三脚で課題へ向き合うこと
条件の意図は、技術力向上には組織理解が不可欠なので、入社歴の長い社員の協力が必要だった。 さらに、本質的な課題を解くために、数名のメンバーをチームとして迎える編成が必要だった。 条件は意図通りに承諾され、本質的な課題へ9月から向き合い始めている。
実はこのとき、FlutterKaigiの運営スタッフとして11月開催の準備中だった。 CTOとの兼務は難しく、10月にスタッフ業務を辞退したが、開催時のスタッフ一覧に自分を加えてくれたことは感謝しかなかった。
やれることはたくさんある
9月~12月からはクリティカルであり、解決するとインパクトのある課題にいくつか向き合えた。 CTOは責任と裁量がバーンと増え、やれることがドカンっと増える。
- 社内の標準言語に「DartとTypeScript」を選定
- 技術負債の返済計画とその実行
- エンジニアキャリアパス制度の制定
- 採用ピッチの作成
- 構造化面接の導入
- 社内ドキュメントをNotionへリニューアル
- 技術知見の共有改善(Do, Learn, Next)
リンクが有効なものは、採用広報として年内に公開できたものだ。 来年には社外の人たちに理解できる形で他の事例もアウトプットしていく。 自社の良い事例が公開されてないので、外部から見て「何をやっているのかわからない」ことが歯痒い。
来年は本質的な課題に向かってあがく
この業界は採用広報活動が年々活発になり、コロナ禍でさらに加速している。 文章、音声、動画と多様な媒体で広がり、他社のCTOの取り組みが簡単に学べる。
年内の取り組みは他社の良い事例を参考に、自社に合致するものを選び実行したものだ。 共に働いたことがあるCTOがやっていたことも真似した。
ただ自分で考え、CTO室のKick-Off MTGで伝えたことがある。
# CTOとVPoEは全てを解決する役職ではないです - 戦略と方向性は示しますが、CTOとVPoEが全課題を解決するわけではない - Missionのとおり「自分たちで課題を解決する組織」を目指そう - 余裕のあるスケジュールで常にスキルアップを忘れずに 💪
CTOになったから何でも出来るようになったわけではない。 組織課題に向き合いつつ、時間を作ってスキルアップし、先手を打ち続けないといけない。 本質的な課題はチームでないと解決できない。「忙しい、時間がない」を枕詞に言わない使わない。余裕のあるスケジュールを作り、メンバーを成長させる。
あがけるだけ、あがいて来年も成長していく。
英会話が趣味になった話
■ これはなに
- 去年の11月から始めたレアジョブ英会話のレッスン回数が今日で200回を超え、レッスン時間が100時間を超えた
- 仕事で必要に迫られ始めたが、途中でチームメンバーの移動があり、英語で話す・書く機会はほぼゼロになった
- 機会は減ったけど、朝の英会話を続けることが習慣になり趣味になり楽しい
2020/11/24 〜 2021/5/29 |
---|
![]() |
■ 英会話が趣味になった理由
1. 毎日やらないルーティーンにした
だいたい隔日で朝8:30 ~ 9:30で行うルーティーンにした。これ以外の時間にはやってない。1レッスンが25分でこれを1日に2回やるので、1日に約1時間(25分超えることもある)となる。
レッスン前に教材となるニュースを下読みして予習もするので、実際は1時間以上はかかっている。下記がレアジョブの画面で見える僕のレッスン履歴です。
11月 | 12月 | 1月 | 2月 | 3月 | 4月 | 5月 |
---|---|---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
やっていない平日の朝は、クロスフィットというトレーニングに出かけている。つまり、運動と英会話が交互に来るのが平日の朝のルーティーン。一方、週末は時間があるので、英会話の後にクロスフィットに行くので両方やるのが週末の朝のルーティーンです。
無理して毎日やらないこと、毎回同じ時間帯にやることが、今日まで続いている理由だと思う。
2. 同じ講師を予約しない
これはレアジョブで働く知人から勧められて、そうすると決めた。予約する講師は毎回違う人にしている。 すると、最初の1~2分がほぼ自己紹介で始まり、毎回新鮮な状態で会話がスタートする。
さらに「前回の講師とは、うまく話せなかったなー」とか「まったく聞き取れなかったー」としても「まあ、ええか」となる。これは人によるけど、「2度と会うことはないだろうから、どう思われても気にしなくてOK」なのが英会話を始める心理的ハードルを下げてくれた。
逆に教室に出向いて実際に人と話すだと、すぐに止めたかもしれない。コロナだからそもそも選択肢になかったけど。
3. 教材を途中でデイリーニュースに変えた
最初は中学や高校の教科書みたいな教材を使っていた。男女の登場人物が出てきて会話とかを聞いたり、自分と講師が登場人物になりきってロールプレイするみたいな例のやつだ。2ヶ月ぐらいたって、これにはマンネリ感とストレスを感じるようになった。
自分が英語をうまく喋れないことにストレスはもちろん感じる。でも、それ以上に教材の題材とロールプレイがストレスだった。コロナでろくに外出できないのに観光地やお祭りに行ったときの会話や、ほぼあり得ないような仕事や恋愛の出来事など、作り話だから当たり前だけど、日に日にストレスが増していった。
そこで3,4月ぐらいから、デイリーニュースに教材を変えた。これが楽しい。まず今の状況を反映してるから、リアルの日常と英会話が結びついてくる。
さらにニュースだから、社会、経済、政治とか社会人だと知っとくと良いよね的なものから、世界中の珍事件などバラエティに飛んでて飽きない。Podcastでニュースが配信されるのも良いし、レッスンの後半でニュースをもとに講師と会話するのも楽しい。講師の話も鮮度が良いから。
教材をデイリーニュースに変えたことで、純粋に会話を楽しめるようになった。
4. コロナのせいで知らない人と話すのが楽しくなった
コロナのせいで人と話す機会がどんどん減っている。だからといって、仕事で雑談や必要のない出社をしてまでコミュニケーションをとろうなんて思わない。仕事は効率的に済ませたいし、プライベートでこそ友達と会って雑談したい。でも、それも難しい。
当たり前だけど、友達もコロナで行動が制限されてて話のネタが少ない。コロナ前だと「どこ行った」「こんなことがあってさー」に加えて、美味い飯と酒を飲みながら一緒にしゃべるのが普通にできてた。それが出来ない。
そこに毎回知らない人と強制的に話す時間ができると、英語であっても面白い時間になる。人と話すことに飢えていたのかもしれない。面白い講師もたくさんいるので、あっという間に25分たったなと思う日が増えている。
英会話はコロナの時期に気軽に会話を楽しむ良い娯楽=趣味になった。
5. 仕事を理由に英会話を続けなくても良くなった
今年の5月までは自分のチームに外国人のメンバーがおり、そのマネージャーが僕だった。そのメンバーが別チームに移動となったので英語を使う機会が減り、必ずしも英語が必要とは言い切れない状態になった。
こうなると、「なんで英会話続けてるんだけ?」となり、でも止めたい気持ちもないから「あ、これもはや趣味では」となった。
■ まとめ
昨年末の振り返りブログに今年の目標の一つに「バイリンガルニュースでマイケルが言っていることを7割わかるレベルになる」を書いた。
現時点では3割も怪しい。対して英語ができない人ほどこういう無茶な目標を立てがち。しかし、年末に書いたときの気持ちより、かなり前向きに取り組めている。受験と大学時代に約2ヶ月の短期留学で英語は勉強したけど、それ以降はGoogle翻訳などのテクノロジーに依存しまくっている。今は、その方が圧倒的に効率が良い。
でももしかしたら、ここから俺の英会話力が上がっていくのかも!?て思い始めたそんな今年の上半期でした。
2020年の自分のエンジニア人生を振り返る
■ これはなに
- 今年はコロナや転職と変化の多い年でしたが、結果はとても良かった
- 振り返るために2020年のアウトプットや、キャリアについて書きました
- 去年の振り返りは 2019年の自分のエンジニア人生を振り返る - kurotyannの覚え書き にあります
■ アウトプット
個人ブログ
この振り返りの記事を除くと1件のブログを書いた。 前職でGoogle Drive API v3を使って手作業を自動化したとき書いた。 そこそこ対応に時間がかかったので、書いてよかった。
会社ブログ
前職の会社ブログだが、1件の記事を書いた。 ニーズのある内容だったようで、SNSやはてブでの反応が良かった。
Qiita
- FormFieldとFormFieldStateを継承して独自入力フィールドを作る方法 - Qiita
- DartのtryParseの引数にnullを渡すとnullが返らないので注意しよう - Qiita
今年は2件の記事を書いた。 どちらもアドベントカレンダーの記事で、これで5年連続となる。 Qiitaの記事は転職先で得た知見をもとに書いた。
副業
今年の7月に4年半勤めた会社を退職して別の会社へ転職した。 転職により、引き継ぎが必要だったので退職後も副業でサポートした。 後任のエンジニアへスムーズに引き継げて良い副業だった。
OSS活動
- GitHub - masashi-sutou/flutter_ios_voip_kit: One-to-one video call using CallKit and PushKit with flutter iOS app.
- GitHub - masashi-sutou/flutter_ios_webrtc_kit: flutter WebRTC sample ios app with flutter_ios_voip_kit https://github.com/masashi-sutou/flutter_ios_voip_kit
業務でVoIP対応が必要だったので、CallKitとPushKitを合わせたflutter pluginを自作しました。ついでに、やったことがなかったのでhttps://t.co/fVMoNnHFg8に公開してみました。https://t.co/tfei0lp1L1
— ストクロ (@kurotyann9696) 2020年7月16日
業務でビデオ通話やライブ機能の実装が必要だったので、今年はそれに関係するOSSへのコミットが増えた。 これがきっかけで、初めて個人でpub.devにOSSライブラリを公開できた。 個人で公開したOSSライブラリの中で最も多いスターを貰えたし、issueやPRなども世界中のエンジニアから届いたので、とても良い経験ができた。
■ キャリア
転職した
今年の7月に4年半勤めた会社を退職して別の会社へ転職した。 前職は古い順から数えて5番目で、エンジニアだと2番目の古株になっていた。
前職の最後に手掛けたサービスでFlutterとFirebaseを経験しており、転職先でも同じ技術スタックで仕事している。 FlutterとFirebaseの経験が自分のキャリアを伸ばす強みになると確信できた1年だった。
コミュニケーションが英語のチームに入った
外国人のエンジニアがいるため、GitHubやSlackのコミュニケーションが英語になった。 会話は日本語だが、エンジニアだけの会議になると英語の割合が少し増える。 特に1on1は、英語の割合が大きくなったので苦労している。
危機感を感じたので、レアジョブで英会話のレッスンを開始したり、ディクテーションなど英語の学習時間を増やした。 来年は英語も頑張っていきたい。
■ 今年と来年の目標
今年の目標は達成できたか?
去年の振り返りブログで宣言した、今年やりたいことは以下の2つだった。
- ① トレーニングして懸垂ができる健康的な身体に戻す
- ② 仕事で得た知見を今年以上にアウトプットする
①は完璧に達成した。
クロスフィットというスポーツトレーニングにどっぷりハマってしまい、週3で朝に激しめの運動をしている*1。 このおかげで転職先の健康診断の結果が「異常なし」に回復していたので、めちゃくちゃ嬉しかった。 さらに運動のおかげで睡眠も良くなり、朝型人間になった。あらゆることを午前中に完了させる癖がつき始めている。
②も達成できた。
アドカレも2本書いたし、個人でOSSライブラリを公開して良い成果を出したので、これも達成できた。
来年の目標について
今年はコロナの影響で今後の人生について考える時間が増えた。 このままでいいのだろうかとか、どう生きていきたいのかなど、思い悩む日が増えた。 自分の結論は、「仕事ばかりではなく、私生活を充実させつつ、仕事で成果を出す」となった。
つまり、来年のやりたいことは...
- Kipping Bar Muscle-Upができるようになる
- バイリンガルニュースでマイケルが言っていることを7割わかるレベルになる
来年の目標には、技術的な目標を個人ブログには書かないことにした。 エンジニアとしての成長は会社の目標設定で定めるから、個人ブログに書く必要がない。
むしろ、「今後、自分はどう生きていきたいのか、暮らしていきたいのか」の方が重要で、そのための目標を定めることにした。 2021年も「自分をさらに鍛えて、私生活を充実させつつ、仕事でも成果を出す」年にします 💪
Google Drive API v3を使ってスプレッドシート(csv)や画像(png)のダウンロード・アップロードをやってみた
■ これはなに
- Drive APIでSpread Sheet(csv)や画像(png)のダウンロード・アップロードが必要で実装に時間がかかった
- Drive APIの仕様を事前に知っておいた方が実装しやすいので、ブログにアウトプットしておく
- Drive APIのおかげで、ブラウザからGoogle Driveを開いてポチポチする無駄な手作業は無くなった
■ 前提
Google Drive API の公式ドキュメントはこちら
npm install googleapis
でインストール、バージョンはv51.0.0
でAPIは最新のv3を利用するNode.jsは
v10.20.1
、 TypeScriptはv3.9.3
です
■ やったこと
1. APIでアクセスするDriveの範囲(権限)を制限
手順やコード
- GCPの「APIとサービス」→「ライブラリ」でDrive APIを有効にする
- GCPの「APIとサービス」→「 認証情報」 →「サービスアカウント」でアカウントを作成
- サービスアカウントに設定したメールアドレスで、Driveのフォルダのユーザー権限にサービスアカウントを追加・権限変更ができるようになる
- あとは
googleapis
にサービスアカウントのキー(.json)を下記の方法で渡せば、APIを利用できる
import fs = require('fs'); import { google, drive_v3 } from 'googleapis'; import { JWT } from 'googleapis-common'; export class DriveApp { private readonly jwtAuth: JWT; /* * ref: * - https://developers.google.com/identity/protocols/oauth2/scopes#drive */ constructor() { this.jwtAuth = new google.auth.JWT({ keyFile: '../credentials/service_account_key.json', scopes: ['https://www.googleapis.com/auth/drive'], }); } private async driveApi(): Promise<drive_v3.Drive> { try { await this.jwtAuth.authorize(); return google.drive({ version: 'v3', auth: this.jwtAuth, }); } catch (e) { console.log(`🧨 method: driveApi 🧨`); throw e; } } // 省略
2. DriveのSpread Sheetをcsv形式でダウンロード
注意1: Drive APIはシート指定のダウンロードに未対応
Drive APIは、Spread Sheet内のシートを指定してダウンロードは出来ない
Drive APIは、対象のSpread Sheetの先頭のシートのみダウンロードする
使うAPIを増やしたくなかったので、Spread Sheetの複数シート管理をやめてファイル単位にシートを分割してDrive APIのみで対応した
注意2:Drive APIの検索クエリは変わってる
- 世の中には、こういう検索クエリの指定形式もあるのかもしれないが、特殊な仕様でわかりづらかった
特に注意してほしいのは、
name contains '${targetName}'
は前方一致であり、部分一致ではないところ当時の苦悩はTwitterでつぶやいたりした
Google Drive API v3のクエリ指定で文字列のcontainsは部分一致ではなく、前方一致でないとマッチしない。ドキュメントのどこに書いてあるのよ... https://t.co/YBbxEIn45Y
— ストクロ (@kurotyann9696) 2020年5月13日
手順やコード
/* * ref: * - https://developers.google.com/drive/api/v3/reference/files/list * - https://developers.google.com/drive/api/v3/reference/files/export */ async exportCSV(folderId: string, spreadSheetName: string): Promise<any> { try { const driveApi = await this.driveApi(); const response = await driveApi.files.list({ fields: 'files(id, name)', q: DriveApp.queryBuilder(DriveMimeType.spreadsheet, folderId, spreadSheetName), }); const fileId = response.data.files?.[0]?.id; if (!fileId) { throw new Error(`❌ ファイルが見つかりません(${folderId}, ${spreadSheetName})`); } const fileExport = await driveApi.files.export({ fileId: fileId, mimeType: 'text/csv', }); return fileExport.data; } catch (e) { console.log(`🧨 method: exportCSV 🧨`); throw e; } } /* * ref: * - ゴミ箱は対象外(trashed = false) * - https://developers.google.com/drive/api/v3/mime-types * - https://developers.google.com/drive/api/v3/reference/query-ref */ private static queryBuilder( type: DriveMimeType | null, folderId: string | null, targetName: string | null ): string { let query = 'trashed = false'; query = type ? `mimeType = '${getMimeType(type)}' and` + query : query; query = folderId ? `'${folderId}' in parents and` + query : query; query = targetName ? `name contains '${targetName}' and` + query : query; return query; }
3. ローカルのcsvをSpread Sheet形式でDriveへアップロード
mimeType
でアップロード形式を指定できる- 間違って別のフォルダに作成したり、ファイルを更新したりしないように、
parents
やaddParents
にファイルが配置されるフォルダIDを指定する
手順やコード
/* * ref: * - https://developers.google.com/drive/api/v3/reference/files/create * - https://developers.google.com/drive/api/v3/manage-uploads#import_to_google_docs_types_ */ async create( folderId: string, localFilePath: string, spreadSheetName: string ): Promise<drive_v3.Schema$File> { try { const driveApi = await this.driveApi(); const response = await driveApi.files.create({ media: { mimeType: 'text/csv', body: fs.createReadStream(localFilePath), }, requestBody: { parents: [folderId], name: spreadSheetName, mimeType: getMimeType(DriveMimeType.spreadsheet), }, }); return response.data; } catch (e) { console.log(`🧨 method: create 🧨`); throw e; } } /* * ref: * - https://developers.google.com/drive/api/v3/reference/files/update * - https://developers.google.com/drive/api/v3/manage-uploads#import_to_google_docs_types */ async update(folderId: string, localFilePath: string, fileId: string): Promise<void> { try { const driveApi = await this.driveApi(); await driveApi.files.update({ fileId: fileId, addParents: folderId, media: { mimeType: 'text/csv', body: fs.createReadStream(localFilePath), }, requestBody: { mimeType: getMimeType(DriveMimeType.spreadsheet), }, }); } catch (e) { console.log(`🧨 method: update 🧨`); throw e; } }
4. 画像をpng形式でDriveからダウンロード
- 一番時間がかかったところだった
- TypeScriptで書く方法がわからず苦戦したが、既にissueになってたので助かった
手順やコード
/* * ref: * - https://developers.google.com/drive/api/v3/reference/files/list * - https://developers.google.com/drive/api/v3/reference/files/get * - https://github.com/googleapis/google-api-nodejs-client/issues/1768 */ async downloadImage(folderId: string, basePath: string, imageName: string): Promise<void> { try { const driveApi = await this.driveApi(); const response = await driveApi.files.list({ fields: 'files(id, name)', q: DriveApp.queryBuilder(null, folderId, imageName), }); const fileId = response.data.files?.[0]?.id; if (!fileId) { throw new Error(`❌ 画像が見つかりません(${folderId}, ${imageName})`); } const dest = fs.createWriteStream(`${basePath}/${imageName}`); driveApi.files.get( { fileId: fileId, alt: 'media', }, { responseType: 'arraybuffer', }, (err, res): void => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore dest.write(Buffer.from(res.data)); } ); } catch (e) { console.log(`🧨 method: downloadImage 🧨`); throw e; } }
■ 終わりに
- 苦戦したもののやりたいことは全て実現できた
- こういう作業の自動化はバックオフィス(庶務や総務系)にも需要高そうだけど、既にこれに特化したサービスが世の中にはあるだろうなと思った
- 90日以上ブログを書かないと、はてぶがトップに広告を出すのでその対策もできて良かった
2019年の自分のエンジニア人生を振り返る
■ これはなに
- 12/27が仕事納めだったので今年の振り返りを書く
- 去年の振り返りは 2018年の自分のエンジニア人生を振り返る - kurotyannの覚え書き
- 振り返るために2019年のアウトプットや、キャリアについて書いた
■ アウトプット
個人ブログ
この振り返りの記事を除くと1件の記事を書いた。 今年は仕事に没頭してたので、個人の活動は少なかった。
会社ブログ
- FlutterとFirebaseで新しいサービスをリリースしました - Studyplus Engineering Blog
- FirebaseとStripe Billingを組み合わせるとき、stripe.customerのdescriptionとmetadataが便利です - Studyplus Engineering Blog
2件の記事を書いた。 どちらも今年に力を入れた新規事業で得た知見を記事にしている。
Qiita
- CircleCI 2.1 と fastlane で Flutter の iOS と Android をビルドして DeployGate で配布する - Qiita
- Cloud FunctionsからBigQueryへ自分で作成したテーブルにデータを追加する - Qiita
- FirebaseとStripe Billingを使ったサブスクリプションの支払いエラー対応 - Qiita
- GestureDetectorでSplitViewやMulti-Windowのような画面をつくる - Qiita
今年は4件の記事を書いた。 4件のうち3件はアドベントカレンダーで書いた。 これで4年連続でアドベントカレンダーに記事を書いている。
全ての記事が、新規事業で得た知見を記事にしている。 新規事業は学びが多かった。
副業
本業がとても忙しかったので、今年は副業をしなかった。
登壇
- 弊社オフィスで「Flutter Meetup Tokyo #9」を開催しました - Studyplus Engineering Blog
- リッチなポップアップ画面にはshowGeneralDialogが便利だった - Speaker Deck
今年は1回登壇した。弊社オフィスで「Flutter Meetup Tokyo #9」を開催して登壇もした。
OSS活動
- MaterialButton's shape property is not working. · Issue #29146 · flutter/flutter · GitHub
- [fireabse_auth] call reauthenticateWithCredential by EmailAuthProvider using current email and password (NoSuchMethodError: The method '[]' was called on null). · Issue #37542 · flutter/flutter · GitHub
- ストクロ on Twitter: "https://t.co/RmgCDAVhbz cocoapodsのCDNについてコメント追記しただけだけど、flutterに自分のPRが初めてマージされた 😄"
- ストクロ on Twitter: "intercom_flutterを使ってPush通知の対応したいけど、このpluginそのままだと機能しないので、別の回避策を提案した。それで困ってた人は一人救えたようだ。良かった。 https://t.co/NI6aQHAsVo"
FlutterのリポジトリにcocoapodsのCDNサポートでPRを投げてマージされた。 今年はFlutter関係のリポジトリに積極的にissueを作成したり、メンテナーとコミュニケーションを取ったことで、OSS活動に微力ながら貢献した。
去年とは比べものにならないほど、OSS活動には参加したので、issueの作成やコミュニケーションに対する心理的ハードルが下がっている。 来年もこの動きはどんどん活発にして、少しでもOSSに貢献していきたい。
個人開発
個人アプリはまったくメンテしなかったし、今年はApple Developer Programの更新すらしなかった。 今は、プライベートの時間でアプリを開発したい気持ちはなく、別のことに時間を使いたい。
■ キャリア
iOSのエンジニアリーダーから新規事業の専任エンジニアになった
去年の半ばから、iOSのエンジニアリーダーだったが、後任の方にバトンタッチした。 そして、新規事業の専任エンジニアになった。
エンジニアリーダーのときは、部下の1on1を隔週でやったり、目標設定や評価など行っていた。 ここで得た学びは、「マネジメントというのは向き不向きではなく明確なスキルである」ことだった。 そして、そのスキルが自分にはまだまだ足りないことを自覚させられた。
リモートワークを取り入れた
新規事業のデザイナーが名古屋に住んでおり、毎日リモートで勤務している。 事業部は私を含めて4名のチームで構成されており、リモートが一人だけだと、MTGのコミュニケーションに偏りが生まれがちだった。
これを解消するために自分も週2から3で、自宅のリモート作業を取り入れた。 MTGはZoomなどのWeb会議で行っている。
MTGの進め方は工夫して、アジェンダのないMTGは開催しないように徹底した。 アジェンダは事前に作成し、報告や共有は最小限にして、審議に時間を割けるようにフォーマットを工夫している。
これでリモートだからMTGが開催できないことはない。 さらに、リモートが原因で進捗が遅れることもなくなったと、個人的には感じている。
■ 来年の目標
去年の2018年の振り返りのブログで、今年にやりたいことは以下の3点だった。
- ① マネジメントスキルを上げる
- ② 新規事業のプロダクトを無事にリリースさせる
- ③ 新規事業の成果を勉強会で発表する
①は自分の求める水準までスキルを上げることが出来なかった。 ただ、マネジメントに関する経験や知識はとても増えたので、来年の自分が目指す方向が明確になった。
②はやり遂げたし、来年はプロダクトの価値をさらに高めていく。 しかし、この新規事業はハードだったこともあり、健康診断で肥満と判定されるぐらい不健康な状態になってしまった。 体調を崩すことはないけど、体型は完全に崩れたので改善する。
③は勉強会で発表はしてないが、会社ブログやQiitaにアウトプットしたので達成はできている。 来年は、さらに新規事業で得た知見を外部にアウトプットしていく。
つまり、来年のやりたいことは...
- トレーニングして懸垂ができる健康的な身体に戻す
- 仕事で得た知見を今年以上にアウトプットする
去年に比べて数が少なく抽象的だけど、この2つを意識して2020年も自分を鍛えていきたい 💪