2021年の人生を振り返る

これはなに

  • 公私ともに大きなイベントがあった1年だった
  • 今年からフォーマットを変えて、目標の振り返りと、来年の目標設定に変更した

目標は達成できたか

去年の振り返りブログで宣言した、今年やりたいことは以下の2つだった。

Kipping Bar Muscle-Upは夏頃にできるようになった。肩への負担が怖くて連続は無理だけど、1回でもできたことが嬉しい。 また夏にできたから、その後はpistol squatに変更してこれも安定してできるようになった。 これでopen gamesの予選メニューで出来ない種目は、逆立ち歩きとRing Muscle-Upの二つぐらいかと思う。

ただ、CTOになった直後に業務がガッと忙しくなり、トレーニングの負荷を下げた時期が続いてしまった。 最近は業務にも慣れ、少しずつ強度を上げている。でも、結果はイマイチ。 来年2月の2022 NOBULL CrossFit Openにエントリーはするけど、去年より成績が悪くなりそう。 RxでWODを完遂できなくても、Rxで出来る種目には挑戦する。

一方、英語はマイケルの言っていることが相変わらず聞き取れない。そもそも公私の変化で英会話を夏頃にやめてしまった。 英語より優先すべき課題があったり、夏から同棲のために引っ越しをし、パートナーとの時間をさらに大切にしたくなった。 英語は嫌いではないが、プライベートやcrossfitや本業よりも優先したくはないので、来年の目標からは外す。

来年の目標

去年の振り返りで

2021年も「自分をさらに鍛えて、私生活を充実させつつ、仕事でも成果を出す」年にします 💪

2020年の自分のエンジニア人生を振り返る - kurotyannの覚え書き

と書いて締めくくっていた。たぶん、ずっとそうなんだろうと思う。 仕事が忙しくても、英会話のように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は責任と裁量がバーンと増え、やれることがドカンっと増える。

リンクが有効なものは、採用広報として年内に公開できたものだ。 来年には社外の人たちに理解できる形で他の事例もアウトプットしていく。 自社の良い事例が公開されてないので、外部から見て「何をやっているのかわからない」ことが歯痒い。

来年は本質的な課題に向かってあがく

この業界は採用広報活動が年々活発になり、コロナ禍でさらに加速している。 文章、音声、動画と多様な媒体で広がり、他社のCTOの取り組みが簡単に学べる。

年内の取り組みは他社の良い事例を参考に、自社に合致するものを選び実行したものだ。 共に働いたことがあるCTOがやっていたことも真似した。

ただ自分で考え、CTO室のKick-Off MTGで伝えたことがある。

# CTOとVPoEは全てを解決する役職ではないです

- 戦略と方向性は示しますが、CTOとVPoEが全課題を解決するわけではない
- Missionのとおり「自分たちで課題を解決する組織」を目指そう
- 余裕のあるスケジュールで常にスキルアップを忘れずに 💪

CTOになったから何でも出来るようになったわけではない。 組織課題に向き合いつつ、時間を作ってスキルアップし、先手を打ち続けないといけない。 本質的な課題はチームでないと解決できない。「忙しい、時間がない」を枕詞に言わない使わない。余裕のあるスケジュールを作り、メンバーを成長させる。

あがけるだけ、あがいて来年も成長していく。

英会話が趣味になった話

■ これはなに

  • 去年の11月から始めたレアジョブ英会話のレッスン回数が今日で200回を超え、レッスン時間が100時間を超えた
  • 仕事で必要に迫られ始めたが、途中でチームメンバーの移動があり、英語で話す・書く機会はほぼゼロになった
  • 機会は減ったけど、朝の英会話を続けることが習慣になり趣味になり楽しい
2020/11/24 〜 2021/5/29
f:id:kurotyann:20210529155353p:plain

■ 英会話が趣味になった理由

1. 毎日やらないルーティーンにした

だいたい隔日で朝8:30 ~ 9:30で行うルーティーンにした。これ以外の時間にはやってない。1レッスンが25分でこれを1日に2回やるので、1日に約1時間(25分超えることもある)となる。

レッスン前に教材となるニュースを下読みして予習もするので、実際は1時間以上はかかっている。下記がレアジョブの画面で見える僕のレッスン履歴です。

11月 12月 1月 2月 3月 4月 5月
f:id:kurotyann:20210529154743p:plain f:id:kurotyann:20210529154759p:plain f:id:kurotyann:20210529154812p:plain f:id:kurotyann:20210529154826p:plain f:id:kurotyann:20210529154844p:plain f:id:kurotyann:20210529154854p:plain f:id:kurotyann:20210529154910p:plain

やっていない平日の朝は、クロスフィットというトレーニングに出かけている。つまり、運動と英会話が交互に来るのが平日の朝のルーティーン。一方、週末は時間があるので、英会話の後にクロスフィットに行くので両方やるのが週末の朝のルーティーンです。

無理して毎日やらないこと、毎回同じ時間帯にやることが、今日まで続いている理由だと思う。

2. 同じ講師を予約しない

これはレアジョブで働く知人から勧められて、そうすると決めた。予約する講師は毎回違う人にしている。 すると、最初の1~2分がほぼ自己紹介で始まり、毎回新鮮な状態で会話がスタートする。

さらに「前回の講師とは、うまく話せなかったなー」とか「まったく聞き取れなかったー」としても「まあ、ええか」となる。これは人によるけど、「2度と会うことはないだろうから、どう思われても気にしなくてOK」なのが英会話を始める心理的ハードルを下げてくれた。

逆に教室に出向いて実際に人と話すだと、すぐに止めたかもしれない。コロナだからそもそも選択肢になかったけど。

3. 教材を途中でデイリーニュースに変えた

最初は中学や高校の教科書みたいな教材を使っていた。男女の登場人物が出てきて会話とかを聞いたり、自分と講師が登場人物になりきってロールプレイするみたいな例のやつだ。2ヶ月ぐらいたって、これにはマンネリ感とストレスを感じるようになった。

自分が英語をうまく喋れないことにストレスはもちろん感じる。でも、それ以上に教材の題材とロールプレイがストレスだった。コロナでろくに外出できないのに観光地やお祭りに行ったときの会話や、ほぼあり得ないような仕事や恋愛の出来事など、作り話だから当たり前だけど、日に日にストレスが増していった。

そこで3,4月ぐらいから、デイリーニュースに教材を変えた。これが楽しい。まず今の状況を反映してるから、リアルの日常と英会話が結びついてくる。

さらにニュースだから、社会、経済、政治とか社会人だと知っとくと良いよね的なものから、世界中の珍事件などバラエティに飛んでて飽きない。Podcastでニュースが配信されるのも良いし、レッスンの後半でニュースをもとに講師と会話するのも楽しい。講師の話も鮮度が良いから。

教材をデイリーニュースに変えたことで、純粋に会話を楽しめるようになった。

4. コロナのせいで知らない人と話すのが楽しくなった

コロナのせいで人と話す機会がどんどん減っている。だからといって、仕事で雑談や必要のない出社をしてまでコミュニケーションをとろうなんて思わない。仕事は効率的に済ませたいし、プライベートでこそ友達と会って雑談したい。でも、それも難しい。

当たり前だけど、友達もコロナで行動が制限されてて話のネタが少ない。コロナ前だと「どこ行った」「こんなことがあってさー」に加えて、美味い飯と酒を飲みながら一緒にしゃべるのが普通にできてた。それが出来ない。

そこに毎回知らない人と強制的に話す時間ができると、英語であっても面白い時間になる。人と話すことに飢えていたのかもしれない。面白い講師もたくさんいるので、あっという間に25分たったなと思う日が増えている。

英会話はコロナの時期に気軽に会話を楽しむ良い娯楽=趣味になった。

5. 仕事を理由に英会話を続けなくても良くなった

今年の5月までは自分のチームに外国人のメンバーがおり、そのマネージャーが僕だった。そのメンバーが別チームに移動となったので英語を使う機会が減り、必ずしも英語が必要とは言い切れない状態になった。

こうなると、「なんで英会話続けてるんだけ?」となり、でも止めたい気持ちもないから「あ、これもはや趣味では」となった。

■ まとめ

昨年末の振り返りブログに今年の目標の一つに「バイリンガルニュースでマイケルが言っていることを7割わかるレベルになる」を書いた。

現時点では3割も怪しい。対して英語ができない人ほどこういう無茶な目標を立てがち。しかし、年末に書いたときの気持ちより、かなり前向きに取り組めている。受験と大学時代に約2ヶ月の短期留学で英語は勉強したけど、それ以降はGoogle翻訳などのテクノロジーに依存しまくっている。今は、その方が圧倒的に効率が良い。

でももしかしたら、ここから俺の英会話力が上がっていくのかも!?て思い始めたそんな今年の上半期でした。

2020年の自分のエンジニア人生を振り返る

■ これはなに

■ アウトプット

個人ブログ

この振り返りの記事を除くと1件のブログを書いた。 前職でGoogle Drive API v3を使って手作業を自動化したとき書いた。 そこそこ対応に時間がかかったので、書いてよかった。

会社ブログ

前職の会社ブログだが、1件の記事を書いた。 ニーズのある内容だったようで、SNSはてブでの反応が良かった。

Qiita

今年は2件の記事を書いた。 どちらもアドベントカレンダーの記事で、これで5年連続となる。 Qiitaの記事は転職先で得た知見をもとに書いた。

副業

今年の7月に4年半勤めた会社を退職して別の会社へ転職した。 転職により、引き継ぎが必要だったので退職後も副業でサポートした。 後任のエンジニアへスムーズに引き継げて良い副業だった。

OSS活動

業務でビデオ通話やライブ機能の実装が必要だったので、今年はそれに関係するOSSへのコミットが増えた。 これがきっかけで、初めて個人でpub.devにOSSライブラリを公開できた。 個人で公開したOSSライブラリの中で最も多いスターを貰えたし、issueやPRなども世界中のエンジニアから届いたので、とても良い経験ができた。

■ キャリア

転職した

今年の7月に4年半勤めた会社を退職して別の会社へ転職した。 前職は古い順から数えて5番目で、エンジニアだと2番目の古株になっていた。

前職の最後に手掛けたサービスでFlutterとFirebaseを経験しており、転職先でも同じ技術スタックで仕事している。 FlutterとFirebaseの経験が自分のキャリアを伸ばす強みになると確信できた1年だった。

コミュニケーションが英語のチームに入った

外国人のエンジニアがいるため、GitHubやSlackのコミュニケーションが英語になった。 会話は日本語だが、エンジニアだけの会議になると英語の割合が少し増える。 特に1on1は、英語の割合が大きくなったので苦労している。

危機感を感じたので、レアジョブで英会話のレッスンを開始したり、ディクテーションなど英語の学習時間を増やした。 来年は英語も頑張っていきたい。

■ 今年と来年の目標

今年の目標は達成できたか?

去年の振り返りブログで宣言した、今年やりたいことは以下の2つだった。

  • ① トレーニングして懸垂ができる健康的な身体に戻す
  • ② 仕事で得た知見を今年以上にアウトプットする

①は完璧に達成した。

クロスフィットというスポーツトレーニングにどっぷりハマってしまい、週3で朝に激しめの運動をしている*1。 このおかげで転職先の健康診断の結果が「異常なし」に回復していたので、めちゃくちゃ嬉しかった。 さらに運動のおかげで睡眠も良くなり、朝型人間になった。あらゆることを午前中に完了させる癖がつき始めている。

②も達成できた。

アドカレも2本書いたし、個人でOSSライブラリを公開して良い成果を出したので、これも達成できた。

来年の目標について

今年はコロナの影響で今後の人生について考える時間が増えた。 このままでいいのだろうかとか、どう生きていきたいのかなど、思い悩む日が増えた。 自分の結論は、「仕事ばかりではなく、私生活を充実させつつ、仕事で成果を出す」となった。

つまり、来年のやりたいことは...

来年の目標には、技術的な目標を個人ブログには書かないことにした。 エンジニアとしての成長は会社の目標設定で定めるから、個人ブログに書く必要がない。

むしろ、「今後、自分はどう生きていきたいのか、暮らしていきたいのか」の方が重要で、そのための目標を定めることにした。 2021年も「自分をさらに鍛えて、私生活を充実させつつ、仕事でも成果を出す」年にします 💪

Google Drive API v3を使ってスプレッドシート(csv)や画像(png)のダウンロード・アップロードをやってみた

■ これはなに

  • Drive APIでSpread Sheet(csv)や画像(png)のダウンロード・アップロードが必要で実装に時間がかかった
  • Drive APIの仕様を事前に知っておいた方が実装しやすいので、ブログにアウトプットしておく
  • Drive APIのおかげで、ブラウザからGoogle Driveを開いてポチポチする無駄な手作業は無くなった

■ 前提

■ やったこと

1. APIでアクセスするDriveの範囲(権限)を制限

  • API経由でアクセスできるユーザーをGCPのサービスアカウントで作成する
  • サービスアカウントがアクセスできるDriveの範囲を制限する

手順やコード

  1. GCPの「APIとサービス」→「ライブラリ」でDrive APIを有効にする
  2. GCPの「APIとサービス」→「 認証情報」 →「サービスアカウント」でアカウントを作成
  3. サービスアカウントに設定したメールアドレスで、Driveのフォルダのユーザー権限にサービスアカウントを追加・権限変更ができるようになる
  4. あとは 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とは別にGoogle Spread Sheet専用API(Sheets API)もある

  • Drive APIは、Spread Sheet内のシートを指定してダウンロードは出来ない

  • Drive APIは、対象のSpread Sheetの先頭のシートのみダウンロードする

    • Spread Sheet内のシートを指定してデータをダウンロードしたい場合は、Sheets APIなら可能だった
    • しかし、csv形式のダウンロードには未対応で、Sheets APIの独自形式でのダウンロードになる
  • 使うAPIを増やしたくなかったので、Spread Sheetの複数シート管理をやめてファイル単位にシートを分割してDrive APIのみで対応した

注意2:Drive APIの検索クエリは変わってる

  • 世の中には、こういう検索クエリの指定形式もあるのかもしれないが、特殊な仕様でわかりづらかった
  • 特に注意してほしいのは、 name contains '${targetName}' は前方一致であり、部分一致ではないところ

  • 当時の苦悩はTwitterでつぶやいたりした

手順やコード

/*
 * 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 でアップロード形式を指定できる
  • 間違って別のフォルダに作成したり、ファイルを更新したりしないように、 parentsaddParents にファイルが配置されるフォルダ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からダウンロード

手順やコード

/*
 * 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;
  }
}

■ 終わりに

2019年の自分のエンジニア人生を振り返る

■ これはなに

■ アウトプット

個人ブログ

この振り返りの記事を除くと1件の記事を書いた。 今年は仕事に没頭してたので、個人の活動は少なかった。

会社ブログ

2件の記事を書いた。 どちらも今年に力を入れた新規事業で得た知見を記事にしている。

Qiita

今年は4件の記事を書いた。 4件のうち3件はアドベントカレンダーで書いた。 これで4年連続でアドベントカレンダーに記事を書いている。

全ての記事が、新規事業で得た知見を記事にしている。 新規事業は学びが多かった。

副業

本業がとても忙しかったので、今年は副業をしなかった。

登壇

今年は1回登壇した。弊社オフィスで「Flutter Meetup Tokyo #9」を開催して登壇もした。

OSS活動

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年も自分を鍛えていきたい 💪

CircleCIでFlutterのCI環境を構築した話とその後

これはなに

  • 3月ごろからFlutterでアプリ開発をはじめている
  • CircleCIでFlutterのCI環境を構築したので技術的なことはQiitaに投稿した
  • ここでは技術的ではない部分(感想とか後日談)を書く

Qiitaに投稿した記事

qiita.com

今もCircleCIでやってるのか

やってる。とくに困ってない。

他のCIサービスもFlutter向けに環境を整えているのでCircleCIでなければならない理由はない。

でも、移行コストを払う必要がないくらい安定しているので、継続してCircleCIで開発する。

少し気になってるのは、CIで走らせた flutter analyze の結果で初めて気づく警告があること。

その警告は Prefer const with constant constructors で、const の指定箇所の違いなのだけど、Android Studio で開発中には警告されない。

なぜローカルで検知できないのかは調べてない。そこまで開発を困らせる課題でもないので。

警告が出れば直してCIを再度走らせてる。

Flutterの開発はどうなのか

今のところは楽しい。困ったことがあってもネット上に解決策が転がってるのでなんとかなる。

ベータ版のころから積極的に開発している方々には足を向けて寝られない。

まだアプリは完成してないが、自分の中でのFlutterは辛いよりも楽しいが圧勝している。

Dartはどうなのか

毎日が新しい発見で昨日書いたコードが良くないコードだと気づき、翌日にリファクタリングする日々が続いている。

感覚的には、3歩進んで2歩下がる感じ。

これは自分のFlutterとDartに関する知識と経験不足によるもので、フレームワークや言語に何か問題があるわけではない。

とにかく、DartはSwiftの次に書くのが楽しい言語になっている。

analysis_options.yaml の静的解析は助かるし、dartfmt でインデントなどの見た目も保存時に自動で綺麗になるのはありがたい。

async, awaitの非同期処理や、スクリプト言語のような簡潔な書き方があったり、その一方で型や修飾子で適度に制約をつけれたりもする。

モバイルアプリだけでなく、WebをDartで書いてサーバーをSwiftで書けたりすると楽しいかもと思うので、落ち着いたら個人でやりたい。

最後に

ほとんど感想というか日記になってしまった。

はてぶが90日以上更新がないブログには、トップに広告をでかく表示してくるので焦って久しぶりに書いた。

内容が薄いのは許してほしい。