kumamotone’s blog

iOS/Android アプリエンジニアです https://twitter.com/kumamo_tone

エラー文読むのがずっと苦手だった

エラー文読むのがずっと苦手だった。

たとえばユニットテスト書いてて、

type 'Null' is not a subtype of type 'Future<T>' :test/hoge_test.dart 30:7

ってエラー文に遭遇したとき、まず「英語でそんなワーワー言わないで!😖」と思考が放棄され、でもググったりガチャガチャしても一向にどうにもなる気配がないので観念して冷静に直訳すると、 Dartくん「Null は Future型のサブタイプではありません🤓」なんだけど、 マジでなんで急にサブタイプの話してるの?ってか仮にそうだとしても、その言い方はなくない?😠みたいな感じになる

実際にこのとき読み取るべきメッセージは

  • Future<T> が返されるべきとこ実際実行したら Null だったよ」
  • 「だから Future<T> を返すように修正してね」
  • 「あっでも Future<T> じゃなくても Future<T> っぽいやつだったらOKだから!」
  • 「大丈夫だから一緒に頑張ろうねっ🤗」

みたいな感じである

自分はこういう理系的な行間を読むのがめちゃくちゃ苦手で(だから大学とかで買わされる、背表紙が謎に固くてページ数は全然ないのにめちゃくちゃ高くて「◯◯は自明」「解答略」とか書いてある数学の本とかが読めない)、マジで素質がね〜〜って長年なってたんだけど、最近はChatGPTに投げればこのあたり何が言いたいのか補間してくれて、人間のフリをできる時間が増えた(今までもググればこのあたりを補間してくれる記事はあるにはあった)

これによってエラーで長時間悩んで、勇気を出して人に見せたら「エラー文ちゃんと読みました?w(ちくちく言葉)」とか言われ、おれは己の才能の無さに傷つき、向こうは向こうで「普通にちょっと考えたら分かることを質問しにくるってわしナメられとんのかな?」みたいになる全員が悲しいだけの時間がかなり発生しにくくなって、全体的に良い感じです サンキューAIくん

CA.flutter #2 に参加しました

cyberagent.connpass.com

本日はサイバーエージェントさんのFlutterエンジニアによる勉強会、 CA.flutter #2 に参加しました!会場はサイバーエージェントさんのアベマタワーズでした。

www.youtube.com

質問は sli.do でリアルタイムに受け付けられており、とても親切な設計でした。

app.sli.do

以下発表内容になります!

Flutter × Rive 魅力的なアニメーション

発表者の Koki Yoshidaさんは、株式会社サイバーエージェントに2023年に新卒入社されて、開発業務に従事されているそうです。

Rive はインタラクティブアニメーションを作成できるツールです。インタラクティブアニメーションはうまく使えば、他の方法では難しい事柄を直感的に説明でき、楽しい体験を提供できます。

Rive は Lottie に似ていますが、ファイルサイズやCPU使用率がLottieより優れているという公式の記述があるそうです。専用のファイル形式でアニメーションを作ったら、Flutter側ではSDK経由で再生するだけ、というワークフローになっています。

metrics と diagnosis というプロパティがあって、Widget Tree で確認することができる

RepaintBoundary は不要な再描画を防ぐWidgetですが、このWidget の renderObject には metrics と diagnosis というプロパティがあり、これによって実際どのぐらいパフォーマンス向上に寄与しているのかという診断を確認することができるそうです。RiveAnimation のWidgetをRepaintBoundaryで囲むと、実際この metrics が非常に高い数値を示すケースがあるそうです。

スライドは flutter_deck で作られており、実際の動作を見せながらプレゼンされていました。

lllttt06.github.io

感想

こういったアニメーションのことを考えるのは自分も好きなので興味深く拝聴しました!RepaintBoundary で最適化を行ったことがなかったので、実際に効いているか確認する方法があるというのも知れて勉強になりました。

認知負荷を打開するFlutter的アプローチ

発表者の Seina Arakaki さんは、2023年新卒入社で、株式会社WinTicketでFlutterアプリ開発を行ってらっしゃるそうです。

WINTICKETでは2022年度から2023年度に人数が5人から8人になり、それに伴ってツールやコード規約などが増え、ある意味「認知負荷」がかかりやすい環境になってきているとのことでした。

コードにおける認知負荷が高い状態には、考慮コストがかかっている場合と判断コストがかかっている場合がある

認知不可を軽減する方法には様々な方法がありますが、たとえば以下のような対策をされているそうです。

  • Dangerでプルリクエストの自動レビューを走らせることで考慮コストを減らす
  • build_runner でコードを自動生成することにより、実装のばらつきを抑制して判断コストを減らす
  • 独自のLintルールを作成することにより、知らない仕様や背景を削減し、考慮コストを削減

感想

Arakaki さんは認知負荷のことを「情報を処理し、理解する際にかかる精神的なエネルギー量のこと」と表現したり、「考慮コスト」と「判断コスト」という言葉で表現したり、独自っぽいワーディングで説明を試みようとしているところが素直に誠実で面白いなと思いました。(もしかすると引用元があるのかもしれませんが)

機械でもチェックが可能なことをコードレビューで指摘することほど不毛なことはないと思うので、BOTによる自動プルリクエストレビューや、コードの自動生成やcustom_lintに関してはできるだけ意識して拡充させていきたいところですね。

認知負荷に関しては、自分も昨年「プログラマー脳」という本を読んで以来自分でも意識していて、特に自分はこの認知負荷に弱い脳をしているなあ、と思うことが多いので、引き続き自分でも探求していきたいトピックです。

kumamotone.hatenadiary.jp

Serverpodを活用したDartフルスタックアプリケーション開発

発表者の Takumi Yoshimuraさんは、2023年5月中途入社。AI 事業本部 アプリ運用カンパニーというところに所属されているそうです。

Serverpod は Dart で書かれたオープンソースアプリケーションサーバー用のフレームワークです。Yoshimuraさんは個人開発でServerpodを利用されているそうです。

$ serverpod create mypod

でプロジェクトを作成すると、

  • mypod_server: サーバーの実装
  • mypod_client : クライアントの自動生成された実装
  • mypod_flutter: Flutterアプリケーションの実装

の3つのパッケージが生成されるそうです。

Serverpod は Flutter での利用を想定されているようで、モデルが共通化できるだけでなく、クライアントの自動生成の部分までワンストップで可能になるそうです。

ほかにも、ORMやEメール/Google/Apple/Firebaseによる認証、S3へのファイルアップロード機能などがサポートされているそうです。

Serverpod insight アプリケーションというのもあって、これによってGUIでリクエストの詳細や、サーバーのヘルスチェックなどの確認などもできるようです。

感想

思ったよりいろいろな機能が提供されていて驚きました!

同じOSSのサーバーサイドDartフレームワークにはDart frogもあると思うのですが、ServerpodはFlutterのバックエンドと銘打っているということもあり、Flutterでの開発体験を上げていくぞという気概が感じられてよかったです。

おわりに

前回の CA.flutter の1回目から引き続きオフラインで参加させていただきました。発表者の方々は前回同様全員が新卒1年目と中途1年目の方々でフレッシュさもありながら、かなり腕利きの方々という感じで、発表内容自体も丁寧で、よくまとまっておりとても勉強になりました!

また、オンラインでの配信もされていて、YouTube Live で配信内容が見れるようになっているのはとてもありがたかったです!(巻き戻しもできるので、ブログまとめたい勢としては聞き逃した部分を確認できてめちゃくちゃありがたい)

オンラインとオフラインのハイブリッドといえば…

自分が運営に参加しているYOUTRUST x ゆめみ Flutter LT会@渋谷&オンライン #5 が2023/3/25 (月) 19:00に開催されます(自主告知)。初のオンライン×オフラインのハイブリッド開催になります!

オフライン会場の参加枠はもう埋まってしまっていますが、オンラインの申し込みはいつでも可能なのでぜひお申し込みください!

yumemi.connpass.com

Scrapbox に書いた箇条書きを Markdown に変換する JavaScript

Scrapbox に書いたメモを Markdown に最低限変換するJavaScriptを書いた。

scrapbox.Page.lines.map(line => {
  if (line.section.start) {
    // セクションの開始行なら見出しとしてフォーマット
    return `## ${line.text}\n`;
  } else {
    // タブの数に基づいてインデントを調整
    return line.text.replace(
      /^\s+/, 
      match => ' '.repeat((match.length - 1) * 2) + '* '
    );
  }
}).join('\n'); // 変換した行を改行コードで結合

使い方

  1. (Chromeの場合) F12 で開発者メニューを開く
  2. Console に上記のスクリプトを入力して Enter
  3. 右クリックして Copy String Contents を選択

先行研究

shokai/Scrapboxからmarkdownに変換 の内容をベースに、箇条書きが深くなったときにうまく変換してくれなかったのでそこだけ書き足した。箇条書きのみのテキストなら変換できる。画像とかアイコンとか表とかそういうのがどうなるのかわからない。

Scrapbox はマジで愛されていて、いろんな実装が存在する。TypeScript や Rust で変換できる CLI を書いてくれている人とか、ブックマークレットを書いてくれてる人とか、UserScript という仕組みを使ってパーサーを書いてくれている人がいるので、それに乗っかってポップアップメニューでコピーできる仕組みを作ってくれたりしてる人とか……めちゃくちゃ良いんだけど……なんというかみんな根気があるな……という気持ちになってしまった……おじさんは、なんとなく何をやっているのかが酔っ払っていてもわかるぐらいのコード量で、コピペしてなんか出た!ぐらいのUXじゃないと安心して安定的に運用できる気がせず……まあ別にそれがイイという哲学でやらしてもらってるんで、別にええんですけど……

コミュニケーションの方法って(たぶん)色々あって良い

このページは mhidakaが建立した Advent Calendar 2023 Vol.1 の4日目です。

きみ誰

kumamo_toneは2016年あたりからiOS/Android/Flutterを軸に活動しているアプリエンジニアで、前職がmhidakaさんと同じメルペイでした。以前は勉強会の運営やカンファレンス運営などもやっていたので、その道の先輩でもあるmhidakaさんのことは色んな面で尊敬申し上げております。

近況報告

  • 引き続きスマホアプリエンジニアやってます
    • ずっとiOS ときどきAndroid という感じだったのですが、5月から株式会社YOUTRUSTというところでFlutterアプリ作ってます
  • 2023年は絵画教室などで練習をしたり、Slay the Spireにハマって全実績を解除したりしました
  • 歯の矯正を3年9ヶ月も前からやっているのですがまだ終わってません しかもまだ毎月すんごい痛い どうしてこんなことに…

最近思っていること

刺激の強いX(Twitter)に疲れてきていて(ChromeのExtensionで心がざわつく要素を消したりいっぱいミュートを設定したりしてなんとか使っています)、改めてブログっていいな〜と感じる機会が増えました。

自分は体も弱く内向的で、超ド近眼という出自から、10代の頃からコミュ障というレッテルを貼られることが多く、未だにコミュニケーションというもの全般に苦手意識を持っています。

一応、仕事上の短時間のコミュニケーションなら問題ないように振る舞えるケースも多く、大人になった今では、面と向かって問題を指摘されることは少なくなってきましたが(まあ大人だから言わないだけかもね)、人と長時間対面で過ごした後はしばらく何もできなくなるほど疲弊してしまうこともしばしばです(そもそも、会話というフォーマットが悪すぎるのではと ターン制コミュニケーション を読んでからは思うようにもなってきました)。色々思っていることがあっても喋るスピードで思考できないし、複数人いると自分のせいで会話のテンポを落とすような気がして発言できない……なんだこの悩み……中学生か?

そんな自分なので、せめてパソコンぐらいはうまく使いこなして交流できるようになりたいな〜最近はよく思っています。具体的には雑にXにpostする、ブログに考えていることや感想などを書く、Slackのtimesチャンネルとかを放置しない、Threadsとか、しずかなインターネットみたいな、新しい媒体が出てきたらできるだけ乗っかってみる、などなど…比較的元気がなかった去年とかと比べれば今年は顔を出せたかな、と思いつつ、2024年はもっと色々なところに情報を置きたい。どうせ自分のことなんて書いてもつまんないだろと思って、何も書かない、何も言わない癖がついてしまっているけど、そのせいでさらに語り下手になり、さらに話の技術が壊滅的になっていく、負のスパイラルを断ち切りたい……職場の人に「休日何やってます?」とか「普段何食べてます?」とか話題を振ってもらうたびに、おれの自己開示が足りないがゆえに、つまんねー会話をさせてしまっている……とめちゃくちゃ反省してます……自意識過剰か……昔はもっと気兼ねなくインターネットに色々書けていた気がするのだけど、なぜなのだろうか……これも自意識過剰なのかな……

というわけでこの文章に関してもその一環と思って書いているのですが、結局エディタを前にするとなんだかうまくまとまらず、日付ギリギリにうんうんうなっています たすけて〜^^;

CA.flutter #1 に参加しました

cyberagent.connpass.com

本日はサイバーエージェントさんのFlutterエンジニアによる勉強会、 CA.flutter #1 に参加しました!会場はサイバーエージェントさんのアベマタワーズでした。

オンラインでの配信もされていて、YouTube Live で配信内容が見れるようになっているのもとても良かったです!(巻き戻しもできたのでブログまとめたい勢としては聞き逃した部分を確認できるのでめちゃくちゃありがたい……!)

www.youtube.com

質問は sli.do でリアルタイムに受け付けられていたのもとても親切な設計だと感じました!質問もすべて読み上げられないほどめちゃくちゃ盛り上がっていました…!

app.sli.do

以下発表内容になります!

複雑な画面遷移を賢く管理する: AutoRouteGuardの活用法

発表者の ひろ(Hirokazu Tanaka) さんは、2023年新卒入社で、株式会社WinTicketでFlutterアプリ開発を行ってらっしゃるそうです。

auto_route は Flutter のナビゲーションパッケージのひとつで、2023年現在、 go_router に次いで人気のあるパッケージです。

Winticketでは、2021年3月にFlutter製アプリにリプレースした当初から auto_route を使用されてらっしゃるそうです。

auto_route の特徴的な機能として、 AutoRouteGuard があります。 AutoRouteGuard では、AutoRouteGuard クラスを継承したクラスを定義して、ルーティングのよくある複雑さを解消しています。

たとえば、公式の以下の例では、画面遷移時に、未ログイン時はナビゲーションを中断してログインページに遷移、ログインが成功した場合のみだけ本来行おうとした遷移を実行、失敗した場合は中止しています。

class AuthGuard extends AutoRouteGuard {                
  @override                
  void onNavigation(NavigationResolver resolver, StackRouter router) {                
    // ナビゲーションは、resolver.next() が true(ナビゲーションを続行)または false(ナビゲーションを中止)で呼び出されるまで一時停止される
    if (authenticated) {
      // 認証されている場合は、ナビゲーションを続行
      resolver.next(true);                
    } else {
      // 未認証の場合は、ログインページにリダイレクトする
      resolver.redirect(LoginRoute(onResult: (success) {                
        // success == true の場合、ナビゲーションを続行、
        // そうでない場合は中止する
        resolver.next(success);                
      }));                
    }                    
  }                
} 

たとえばWinticketではVIPユーザーと呼ばれるユーザーには、 /campaign/vip に遷移させるということをさせていることがあるようです。具体的には、以下のようにAutoRouteを定義しているそうです。

AutoRoute(
  path: '/campaign/vip',
  page: SecretVIPPage,
  guards: [
    IsLoginGuard,
    IsVerificationGuard,
    IsVIPGuard,
  ]
),

これによって、ログイン済み、本人確認済み、VIPユーザーの条件を満たす、という3つのガードを画面遷移に適用して、さらにVIPユーザーでない場合はそれ用のページに飛ばす、といった動作が実現できているようです(こういう形で組み合わせできるのはいいですね)。

また、WinTicketではフィーチャーフラグを使ったtrunk-basedなブランチ運用をされているようなのですが、フィーチャーフラグの状態を判定するのにも AutoRouteGuard を使われているそうです。

また、キーボードが閉じられるまで画面遷移を遅延させる AutoRouteGuard も定義されているようです(これも面白い)(閉じる判定 WidgetsBinding.instance.window.viewInsets.bottom == 0 でいいんだ…)。

個人的には、ナビゲーションには go_router か素のナビゲーションを使うことが多いのですが、go_router にも未ログイン時にログインページにリダイレクトさせるような機能(参考)があるようで、使ったことがなかったので気づける良いきっかけになりました!

質問コーナー

Q. go_router ではなく auto_router を選定したのはなぜ?

当時の判断らしい

How To Improve UI Quality And Performance

発表者の なるお(naruogram)さんは、2024年入社予定。サイバーエージェント24卒内定者の方で、Amebaマンガに所属。Flutter だけでなく、 iOSアプリの開発も行ってらっしゃるそうです。

UIの品質とは、「そのサービスがユーザーにとってどれだけ使いやすく、理解しやすく、効率的であるか」と定義されているようで、具体的には以下のチェックリストが考えられるとのことです。

なるおさんの所属する Amebaマンガ では、 UIの品質を Visual Regression Test を使って、改善しているそうです。テストツールは playbook-ui/playbook-flutter というサイバーエージェントの方が関わられてるツールと、 reg-suit を使っているそうです。

github.com

VRT では、以下のような点をチェックしているそうです。

  • 異なるデバイスでもUIが崩れないか→VRTテストにおいてテストする端末を増やす
  • 異なる状況でもUIが崩れないか→長い文字列や通信環境が悪くて画像が取得できなかったケースのStoryを用意する
  • 端末の文字サイズによってUIが崩れないか→ TextScaleFactor の値を設定し、複数パターンの文字サイズをテストする

また、 integration_test を使ってパフォーマンス計測を行う取り組みもやってらっしゃるそうです。

await binding.traceAction(
  () async {
    await tester.scrollUntilVisible(
      itemFinder,
      500.0,
      scrollable: listFinder,
    );
  },
  reportKey: 'scrolling_timeline',
);

計測するためには、Widget Test のコード上で、 IntegrationTestWidgetsFlutterBinding.ensureinitialized() で取得したインスタンスに対して traceAction() を使用し、引数に reportKey を文字列で指定します。

import 'package:flutter_driver/flutter_driver.dart' as driver;
import 'package:integration_test/integration_test_driver.dart';

Future<void> main() {
  return integrationDriver(
    responseDataCallback: (data) async {
      if (data != null) {
        final timeline = driver.Timeline.fromJson(
          data['scrolling_timeline'] as Map<String, dynamic>,
        );

        // タイムラインを、読みやすく理解しやすいタイムラインサマリーに変換
        final summary = driver.TimelineSummary.summarize(timeline);

        // その後、タイムライン全体をjson形式でディスクに書き込む
        // このファイルは、Chromeブラウザのトレーシングツールで開くことができる
        // トレーシングツールは chrome://tracingに移動して開く
        // オプションで、includeSummaryをtrueに設定することでサマリーもディスクに保存する
        await summary.writeTimelineToFile(
          'scrolling_timeline',
          pretty: true,
          includeSummary: true,
        );
      }
    },
  );
}

また、上記のテストドライバーを別ファイルに保存します。

もしテスト自体を integration_test/scrolling_test.dart、テストドライバーをtest_driver/perf_driver.dart というパスで保存していた場合、テストドライバーを指定して、以下のように実行するようです。

flutter drive \
  --driver=test_driver/perf_driver.dart \
  --target=integration_test/scrolling_test.dart \
  --profile

さらに、おそらく上記例の summarize のかわりに summaryJson というプロパティを使用すると、平均/最長フレームビルド時間、平均/最長フレーム描画時間、平均CPU使用率、平均メモリ使用率などをJSON形式で出力することができるようです。(これはやってみたい、、!)

懇親会で登壇者のなるおさんに質問させていただいたのですが、公式の下記の Performance profiling という記事が参考になりそうです。

docs.flutter.dev

個人的には、Flutter で VRT や PlayBook をガッツリ使った事例は貴重だと思うのでとても聞けてよかったです!また、 integration_test でプロファイリングするのはぜひやってみたい!

小売アプリのためのアクセシビリティ

発表者のKoki Masuyama(masssun)さんは、今年1月に中途入社されて、AI 事業本部アプリ運用カンパニーというところでモバイルアプリチームのリードエンジニアをされているそうです。

アプリ運用カンパニーは小売り企業の方々と協業して、アプリを中心としたデジタルでの購買体験の実現を行う事業部とのことでした。

アクセシビリティの重要性からはじまり、まずエンジニア主導で行える Flutter におけるアクセシビリティ対応としては、

  • スクリーンリーダー
  • 文字サイズ

の対応がありそうとのことでした。

スクリーンリーダー

Widget ツリーに、「このテキストは何であるか」「ボタンをタップすると何が起こるのか」などの情報を付与します。

たとえば具体的には、Semantics ウィジェットで囲んで label を設定するということができるようです。

ただ、AppBar, Text など標準Widgetの多くはそもそも Semantics でラップされているようなので、使っていれば対応が済んでいるとのことでした。

そのため、Flutterでは特別にアクセシビリティ対応を行わなくても、スクリーンリーダーが対応ができる範囲が広いようです。しかし、それを踏まえた上で、いくつかのTipsがあるようでした。

  • cached_network_image を使用している画像について、 Semantics で囲む (Image の場合は semanticsLabel という引数がある)
  • 複数のスタイルが適用されている Text は、別の Text として認識されてしまうが、まとめたい場合は MergeSemanticsRichText などを使う
  • アイコン付きのボタンについて、アイコン部分については読み上げさせたくないので、ExcludeSemantics ウィジェットでアイコン部分を囲む

文字サイズ

Text ウィジェットを使っていれば、フォントサイズはOSの設定に基づいてFlutterが自動的に計算してくれるので、これも特別な設定は必要なさそうとのことでした。

しかし、Layout overflow を起こさないような設計にする必要はあるとのことでした。そのための対応として、

  • SizedBox で width, height を固定にしない
  • ConstrainedBox で minWidth, minHeight を適切に設定
  • Column の children に設定されているWidgetは Wrap/Extended でラップすることで、画面端で改行されるようにする

などの工夫を行っているそうです。

個人的には、アクセシビリティはどうしても自分が当事者でないときに見落としがちな部分なので、Flutterでの具体的な事例や、気をつける観点などを知れる良い機会になったなと思いました!

おわりに

今回は CA.flutter の1回目の開催で、発表者の方々は新卒1年目、中途1年目、内定者の方ということでフレッシュな感じかと思いきや、かなり腕利きの方々という感じでとても勉強になりました!また、今所属しているYOUTRUSTでやっている勉強会(12/9(金)に第4回目をやります 今週 11/17(金) 13:00〜募集開始です)や、FlutterKaigi でお話した人とまた懇親会でお話できたりする機会になったのも嬉しかったです。また機会があれば参加したいです!

「プログラマー脳」を読んだ

www.amazon.co.jp

「プログラミング”力”を”鍛えて”、”優れた”プログラマーになりてぇ〜」というあるあるBIG煩悩に、筆者の個人的な経験や主観……ではなく、できるだけオープンになっている定量的な研究結果を引用して誠実に回答しようとした本だと思った。

優れたプログラマーとは?

この本で想定されている優れたプログラマーとは、以下のような人を指している。

  1. 人のプログラムを効率的に(短時間で)読むことができる
  2. バグの発見を効率的に(短時間で)行うことができる
  3. 良いコード(わかりやすく、保守性の高い)コードが書ける
  4. 大規模なシステムでも共同作業を行い、オンボーディングを行うことができる

地に足についたシゴデキ感があり、たしかに目指すべきはこれだよな〜と改めて思った。

この本では4章に渡って、以上のようなプログラマー像になるためのヒントやテクニック、それの根拠となる研究結果などを紹介されている。

認知負荷について

一冊を通じて語られていて、個人的にも意識していきたいなと思ったのは「認知負荷」についてだった。

人は見慣れないものを理解するのには時間が掛かるし、短期記憶に入っていないものは取り出すのには時間が掛かるし、日常的に慣れた操作以外を行うときは操作そのものに意識が持っていかれる。

認知負荷が高まると課題の解決に時間が掛かるが、逆に、できるだけ他人の認知負荷を高めさせないことが、チームメンバーとしては良い振る舞いだ、というメッセージを感じさせられた。

「メソッドを細かく分割するのは何故良いのか」「なんで変数名はあんまり省略すべきでないと言われているのか」みたいなところの答えにもなっていて、「焦ってとにかく一度に複数のことをやろうとするな」というのは前から感じていたことではあるが、この本によって思考が一歩前に進んだ気がする。

プログラミングに当てはめると

具体的には、以下のようなことが言われていた。

  • 短期記憶やワーキングメモリに蓄えれる情報はそんなに多くないため、メモなどの補助ツールなどを利用したり、練習などを経て、長期記憶や外部装置を充実させることにより、複雑な課題に取り組みやすくなる
  • 「関数やクラスを細かく分ける」「変数名は省略されていないものを使う」「一貫性をもたせる」などのプラクティスに従うことで、認知負荷がかからないコードを目指すと良い
  • 新人にオンボーディングするときは、新人がそもそも慣れない環境で色々慣れるべきことがあることを考慮して本当に小さいものや、慣れさせるためのタスク(リファクタリング)などから渡していくと良い

まとめ

多くのプログラマーが抱えているBIGペインに対して、できるだけ筆者の個人的な経験や主観を廃して向き合って体系的に整理された情報として、尊い書籍だなと思った。

speakerdeck.com

iOSDC Japan 2023 の shiz さんの発表資料は本書の一部が非常に良くまとまっていて、振り返るのにとても良かったのでここで紹介させていただきます。

2023年4月に、株式会社メルカリ(メルペイ)を退職しました。3年と4ヶ月ほど在籍させていただきました。

個人的な振り返りも兼ねて、簡単にどんな感じだったか書き残しておければと思います。

入社

2019年の11月に新卒で入社したヤフーを退社して、アプリ(iOS)のエンジニアとして同年12月に入社しました。

入社を決めたきっかけなどは、書き残してなかったというのもあり、もう記憶がおぼろげですが、以下のような感じだったと思います。

  • メルカリのバリューが、当時自分がありたいと思っていた像とかなり合っていると感じた
  • ペイメント事業に関わってみたいと思っていた
    • 当時WeChatとAlipayが使いたいという理由で2度中国に行くほどモバイル決済のオタクだったし、モバイル決済に可能性を感じていた
  • 勉強会などで会って印象が良かった人たちが多数在籍していた

この頃は我ながら気合が入っていて、オフィスから近いという理由で背伸びしてちょっと家賃14万の狭い1Kに引っ越し、堅実に実績や経験を貯めながら効率性を極めて、とにかくやるぞという気持ちに溢れていました。

COVID-19 の流行

ところが、2020年に入ってすぐCOVID-19が流行しはじめ、具体的な時期はうろ覚えなのですが、メルペイはかなり早い段階でフルリモートの環境に移行しました。

個人的には当時はリモートワークはうまく活用していければいいなと思っている派でした。実際、前職ヤフーのときは結構リモートワークの制度を使って家から仕事をしていたりもしました。しかし、いざ仕事をやっていくぞとなると、コミュニケーションの取りづらさや、仕事が終わった後も常に気が張り続けているのか睡眠などに影響が出てきたりして、色々な問題に直面しました。

また以前は、頻繁に技術勉強会に参加したり、技術カンファレンスの運営などにも関わっていて、それらに参加したり発表したりするためにいい仕事をするぞみたいなモチベーションがあったりとか、参加すること自体が良い息抜きになっていました。しかし、それらも(ある意味)なくなったことにより、ますます仕事との向き合い方というのがよくわからなくなっていました。

違和感に対する気付き

このあたりからフルリモートのやりづらさに加えて、

  • 提供しているサービスと、自分の価値観とのズレ
    • いわゆるリボ払いのようなものを提供していて、かなりの収益を上げていた*1
    • 世の中で言われている悪い側面だけでないことや、 evil になりすぎないように努力している人がいるのも感じたが、考えても違和感は残った *2
    • もっと決済や送金のUXに関わるプロジェクトにも参加できるのではないかと思っていたのだが、そうならなかった
  • この規模の組織で仕事をやっていくということ
    • 関わったプロダクトで、自分が作り上げたという気持ちになるのが難しかった
  • iOS のエンジニアとしてやっていくことに対しての疑問
    • ほとんどの仕事でネイティブのコードを書く必要性を感じられないジレンマ

などにも悩むようになりました。

転職

ある程度悩み尽くしたあたりで、転職サイトや Twitter DM などで何社かお話を聞く機会があり、最終的に YOUTRUST 経由でメッセージをいただいた会社に入社させてもらえることになりました。

決め手としては、

  • フルリモートではなく週3回の物理出社と週2回のリモートワークのハイブリッド型(2023年5月現在)
  • 規模が(主観的に見て)(現職ほどは)大きすぎない
  • Flutterというクロスプラットフォームフレームワークを使っている

あたりでした。関わってくれた人たちの雰囲気が良いと思ったというのもありました。

よかったこと

うまくいかなかったことも色々ありましたが、自分が関わった範囲では職場環境はかなりホワイトという感じで、給与水準も高く(と思います)、入社当時はアプリエンジニアには iMac Pro が支給されていたり、イベント運営や、採用会食する機会などもありましたが、そういうときにも全体的に羽振りが良いと感じました。

エンジニアに割り振られるタスクの量も自分が観測する範囲ではあまり多くなく、そのような余裕もあってか、困っていることがあったときにSlackに書くと、親身になって即レスしてくれるナイスな人も多かったです。カンファレンスでよく登壇しているとか本を書いてるとかデカいイベントの運営をやっているとか、自分がそうなりたいなと思っていた方向性で活躍している人もいたし、やっぱりお金や時間に余裕があるからか親切だと感じる人が多かった。

あと、人の悪口とかをしたり聞いたりするのが嫌なのですが、日本語が喋れないメンバーもいるチームでカタコトな英語でコミュニケーションしていたというのもあってか、そういうのとも比較的無縁でいられたというのも良かったです。

上達すると期待していた英語は、実感としては思ったより上達せず、会議はおろか日常会話ですらかなり怪しく、最後まで文章を書くときはDeepL Proを使い倒していました。というか振り返ると一時期は体調が悪すぎて日本語もうまく発話できてませんでした。ただ、退職時のマネージャーは入社時よりうまくなってるとも言ってくれていたので、もしかするとある程度うまくなっていたのかもしれません(DeepLに慣れて、見かけ上の文章力が上がっていた説あり)。

リモートワークについて

うまくいかなかったことの原因を、結構コロナ禍とフルリモートのせいにしてしまいましたが、世の中の状況や現時点の自分のライフスタイル(独身独居で孤立していた)などが現時点でたまたまうまく噛み合わなかっただけで、リモートワーク自体はとてもありがたい制度だと思います。

どこからでも仕事ができるということで広がる可能性はたくさんあると思いますし、都市圏の高い家賃を払い続けるのはアホくさいです。

というか本来、ステレオタイプな感覚で言ったら僕は内向的で、一人の時間が長くて、基本的に日がな一日パソコンに向かって作業しているわけなので、うまく使えば比較的相性がいいはずでもあるとも思います。

ただこのあたりは同じような性格やライフスタイルの人が体調を崩していたり、現在進行系で悩んだりしているのも見るので、現時点ではまだ自分の中で結論が出しづらいです。

おわりに

多くのWeb系の企業がリストラや採用ストップを掛けている中、安定した環境を離れて転職というのは不安な部分もあるのですが、次の職場にも楽しみな部分はたくさんあり、前向きにやっていきたいと思います!いつかそんなこともあったねって笑って話せるようになるといいな。

追記:会社や中にいる人に感謝こそすれ批判したい意図などはまったくないので、ブコメ等での、中にいる人が嫌な思いをする可能性のあるサービス等に対する批判はお控えくださると幸いです。

*1:このあたりは決算資料 で公開されているので、機密な情報ではないと思います

*2:当時自分の中でいい感じの納得ができていなかったという話であって、悪いと言いたいわけではないです。