「入門 考える技術・書く技術」
直近の業務において、技術的な文章を書く機会が増えてきているため購入。
わかりやすい文章の書き方、というよりもわかりやすい論理の組み立て方を伝えている書籍。
わかりやすく書くコツとしては大体下記4つを書いていた。
- 読み手の疑問に対する答えを書く。
- ピラミット型に論理を組み立て、主メッセージを明確にしたあとに、それを説明するメッセージを伝える。主張->根拠->更に詳細な説明、といったような構造。
- あいまいな言葉を使わない。
- 2文をつなげるためだけのand接続詞(〜し、〜であり)を使わずに、ロジカル接続詞(~ために、といった因果関係を示すものや、~である一方といった対象を表すもの)を使う。
ロジカルシンキングの一般的な内容で、過去そのような書籍は読んでいたことがあるため、自分にとって真新しいことは特になかった。
また、自分の目的である技術的なことをわかりやすく伝える術を学ぶ、というのとは少し違った。
技術的な文章を書くにしても、あとは実践をたくさんするしかなさそう。
過去読んだロジカルシンキングの書籍
とはいえ自分は接続詞の使い方だったり、あいまいな言葉は使ったりしがちなので振り返る良い機会にはなったとは思う。
Kaigi on Rails 2023に参加した
はじめに
2023/10/27-10/28に開催された Kaigi on Railsに参加しました。
kaigionrails.org
Ruby関連のカンファに参加するのは今年の松本でのRuby Kaigiに引き続き2度目です。
前回のRuby Kaigiでは弊社のブース担当として参加していましたが、
今回はブースのお仕事がないので発表を聞くのに専念できる・・・!ということで、ワクワクしながら参加してきました。
Voice Pocochaブース出してます!
— やや (@yayamochi) 2023年5月12日
顔出しなしのライブ配信、ということでアイマスク配ってます🙌#rubykaigi pic.twitter.com/6rc1c4HaO7
発表
自分が特に印象に残っている発表は以下の2つです。
やさしいActiveRecordのDB接続のしくみ
私が業務でConnectionPool周りにパッチを当てている部分を修正する機会(※)があり、内部実装を見にいった経験がありました。
当時、内部の仕組みを理解するのが複雑で苦戦していたので、非常に楽しみにしていた発表です。
登壇者の方はrdbgでブレークポイントを貼り、DB接続に関しての主要なクラスをあぶり出し、図解で説明してくださいました。
自分で実装を追っていった際に概要を掴むまでにしばらく時間がかかっていたのですが、本当ににこの発表がわかりやすく業務で担当する前に見ておきたかったです。笑
※自分が業務で触った内容は、AWS AuroraのFailover時にConnectionPoolで古い接続を取ってきてしまう影響でDB接続できなくなる不具合の解消のために上記の実装を追ってました。
下記の記事でも紹介のある、mysql2-auroraというgemを使うことで解決しています。(上記の接続ができないときのエラーメッセージをハンドリングして再接続するgem)
qiita.com
32個のPRでリリースした依存度の高いコアなモデルの安全な弄り方
オンラインDDLの対象操作を整理・挙動の注意点を説明し、実際のアプリケーションのデプロイフローなどを考慮すると
カラム追加 → 値の同期 → バックフィル → Not Null制約 …(略)… → カラムの削除
のように丁寧に一個ずつ手順を踏んでリリースしていくしかないね、というお話です。
最後にあった「モデルの拡張性・柔軟性について」の話はとても共感しました。
「将来的にはこうなりそう」と予想して不確実なものを設計に組み込むよりも、今ある情報で確実に設計していくべき。
テーブル変更定義は大変で危険だが、安全にリリースするためのDBの機能や実践例はたくさんあるし、それらを学んで行き、その技術を身に着けておくことが大事。
私自身、業務での新規機能開発の頻度は高く、テーブル設計の際には、企画者に対して「将来こういった機能の実装予定はありますか!?」という質問を投げかけて困らせがちだったり、機能を拡張する際にテーブル設計がしんどくて実装が辛くなったりすることも経験として多くありますが、上記思想は大事にしていきたいし、勉強していきたい。
補足
当日の発表については下記のブログに掲載されていました🙌
qiita.com
まとめ
今回Kaigi on Railsに参加してみて、自分の興味軸としては、フレームワークのRailsがどうこう、っていう話ももちろん面白いけど、そもそもの根本のテーブル設計やDBあたりの話に結構向いているかも?と思って聞いてました。
また、学生時代にインターン先でお世話になった方や、前回のRuby Kaigiで知り合った方とも再会でき、とても嬉しかったです。
ほんとこれです。
カンファレンスの参加回数を重ねるごとに知り合いが増えて、「お久しぶりです!」って言えるのが嬉しい#kaigionrails
— 井上 周/ INOUE Amane (@isaka1022) 2023年10月27日
自分はこれからもRubyにお世話になることが増えていきそうな予感だし、自分もアウトプット出していきたい。
「エンジニアリングマネージャーのしごと」を読みました
はじめに
なんと3年ぶりにブログを書く✏️
一年間とすこし務めたリードエンジニア業が終わり、再び開発に集中できる環境になってきたのでこれからまたアウトプットしていこうと思う。
ちなみに私の経歴としてはクライアントエンジニアから始まり、サーバーサイドエンジニアとリードエンジニア、採用業務を経験し、現在はまた開発中心の生活に戻って、サーバーサイドを中心にやっており、新卒から三年半、ライブ配信サービスの開発に日々取り組んでいます😎
5月に松本で参加したRubyKaigiのイベントにて、@TimeeDevさんから「エンジニアリングマネージャーのしごと」を頂きました!
RubyKaigiで@TimeeDev のキャンペーンで当たった書籍読み始めてみる!
— やや (@yayamochi) 2023年5月31日
マネージャーではないけど、開発以外の業務がかなり多いので視座高めるためにも頼んでみた✌️ pic.twitter.com/PK42wLRGGE
結構ボリューミーな書籍で、かつ自分のためになって実践したポイントがいくつかあったので紹介していく✌️
本の構成
第1部 オリエンテーション
まず、マネジメントをする前に自分の業務の整理術に関してのパート
- 1章 新たな冒険
- 2章 まず自分を管理しよう
第2部 個人と働く
チームメンバーと働く上でのすべてのことに関してのパート
- 3章 人間と関わる
- 4章 1on1
- 5章 その人に合った仕事とは
- 6章 1年でいちばん輝かしい季節
- 7章 採用中!
- 8章 ゲームオーバー
- 9章 友人を作り、人に影響を与えるには
第3部 全体像
プロジェクト・職場全体での働き方に関してのパート
読書メモ
2章 まず自分を管理しよう
手際よく業務を進める上での整理方法についてまとめられています。
自分はこれをきっかけに以下を整理しました。
- 机の整理
- 机に収納ボックスを取り付けて、小物類が目に入らないようにした
- 頻度の高すぎる1on1の整理
- 不要なメールのサブスク解除
- 朝読むリストの作成・ルーティン化
- notion Web Cliperを使うことで、朝見返しやすく
3章 人間と関わる
リーダーが自分自身で大事なタスクを全てやろうとすると、膨大すぎてどうにかなってしまいます。
そうならないための、タスクの委譲(タスクの責任を自分から部下に移す)について記載がありました。
- やるべきこと
- メンバーに取ってチャレンジングになるくらい委譲する
- チームができることが増え、メンバーの能力も増え、WinWin
- メンバーに取ってチャレンジングになるくらい委譲する
- やってはいけないこと
- 渡したタスクを散り返す
- タスクの学習機会はもちろん、感情も害する
- 他人のやりかたが自分と同じであることを期待する
- 渡したタスクを散り返す
リベラルアーツ大学の動画、 ついていきたいリーダーvs距離をとりたいリーダー【部下たちの本音】【人生論】でも似たようなことを言っていたことを思い出した。
youtu.be
任せるって心配だけど、体験して失敗することで、メンバー自身が学ぶきっかけにもなるし、リーダー業務する上で一番意識しながら働いたポイントかもしれない。
7章 採用中!
本書に記載の通り、エンジニアが全然足りない最中にいた私は、まさに「ただエンジニアを増やそうとする」「できる限りシニアな人を雇おうとする」「自分と似ている人だけを雇おうとする」に陥っていたw
そのため、面接の際の自分の質問が人によってぶれていたり、後からこれ聞いておけばよかった、となることがあった。
- モチベーション
- コミュニケーションスキル
- 学ぶことへの前向きさ
- 会社と価値観・倫理観の一致
- どういったスキルの人がいればチームが伸びるか
まずはカルチャーフィットの特徴である上記を弊チームに合わせて定義することによって、
じゃあこのスキルを持っているか判断するにはどういう質問をしたら良いのか?と逆算した質問リストを作成することができ、一定の質で面接が進行できるようになった。
まとめ
本の中では長々と記載している部分もあったが、マネージャーの視点に限らず、1エンジニアとして、個人の業務~プロジェクトの進行において円滑に進めるためのストーリがたくさん載っていた。
また業務で気になる観点があれば読み返してみたいと思う。
【Flutter】チーム開発でflutter_blocを導入したらめちゃめちゃ良かった
はじめに
研修でのチーム開発にて、某画像検索アプリのクローンのクライアント側をFlutterで実装しました。
状態管理手法としてBLoCパターンを採用し、その際にflutter_bloc というパッケージを使用しました。
使用感として
- 誰が書いても同じコードスタイルになる
- テストがしやすい
という印象をもち、大人数で開発する上では非常に使いやすいと感じたのでご紹介したいと思います。
BLoCとは🤔
BLoCとは Business Logic Component の略で、簡潔に説明するとUIからビジネスロジックを分離する設計パターンです。 2018年に開かれたDart Conferenceで発表されています。
BLoCの全体像やガイドラインに関しては、以下の記事が非常にわかりやすいのでぜひご覧ください。
【Dart/Flutter】導入したBLoCパターンアーキテクチャについて全体像をまとめてみた
このBLoCパターンを実現するには、DartのStreamを用いてデータを送り、providerを用いて、必要なWidgetにDIする手法がよく使われるかと思います。
以下参考記事。
flutter_bloc✨
flutter_blocは、上記で説明したBLoCデザインパターンの実装を容易にすることができるpackageです。 手法としては、UI側から何かしらのeventを送ることで、blocを通じてstateを変更するという方法で状態を変更しています。
[引用: https://pub.dev/packages/bloc]
ディレクトリ構造
lib/
├ api/
├ data/
├ model/
├ util/
├ values/
├ view/
└ main/
└ home/
├ home_widget.dart
└ bloc/
└ bloc.dart
└ home_bloc.dart
└ home_event.dart
└ home_state.dart
eventの定義
// home_event.dart import 'package:equatable/equatable.dart'; abstract class HomeEvent extends Equatable { @override List<Object> get props => []; } class LoadData extends HomeEvent {}
データを変更させるためのイベントを定義します。
stateの定義
// home_state.dart import 'package:equatable/equatable.dart'; import 'package:path/model/book_model.dart'; //ここのパスは適宜合うものに変える abstract class HomeState extends Equatable { @override List<Object> get props => []; } class LoadingState extends HomeState {} class LoadedState extends HomeState { LoadedState(this.books); final List<BookModel> books; @override List<Object> get props => [books]; } class NoDataState extends HomeState {} class ErrorState extends HomeState { ErrorState(this.exception); final Exception exception; }
アプリの取りうるState(状態)を記述します。 StateにてEquatable packageを使う理由としては、 propsに入っているプロパティが一致しているかを判断することができ、これらの値が全く一緒であればイベントをaddしたとしても、Streamは流れないようにすることができるからです。(間違っていたら指摘してください。)
blocの定義
// home_bloc.dart import 'package:bloc/bloc.dart'; import 'package:path/data/books_repository.dart'; import 'package:path/model/book_model.dart'; import 'bloc.dart'; class HomeBloc extends Bloc<HomeEvent, HomeState> { HomeBloc(this._booksRepository); final BooksRepository _booksRepository; @override HomeState get initialState => LoadingState(); @override Stream<HomeState> mapEventToState(HomeEvent event) async* { if (event is LoadData) { try { final books = await _booksRepository.getBooks(); if (books.isEmpty) { yield NoDataState(); return; } yield LoadedState(books); } on Exception catch (e) { yield ErrorState(e); } } } }
mapEventToStateにてどのイベントがきたら、どのような状態の変化をするのかを記述します。
また、以下のようなファイルを準備しておくことで
// bloc.dart export 'home_bloc.dart'; export 'home_event.dart'; export 'home_state.dart';
widgetでblocをimportする際は、以下のような記述で済むようになります。
import 'package:path/home_widget/bloc.dart';
widgetでのBlocの使用方法
BlocProviderwidgetを用いることで、BlocクラスをDIします。
// home_widget.dart Widget build(BuildContext context) { return BlocProvider<HomeBloc>( create: (context) => HomeBloc(context.repository<BooksRepository>())..add(LoadData()), child: : _buildScreen(context), ); }
add(EventClass())メソッドを使うことによってイベントを発火することができます。
またDIした後は、BlocProvider.of<HomeBloc>(context);のようにblocを呼び出すことが可能です。
BlocBuilderwidgetを用いると、状態によってwidgetを変更することが出来ます。
Widget _buildStaggeredGridView() {
return BlocBuilder<HomeBloc, HomeState>(builder: (context, state) {
bloc = BlocProvider.of<HomeBloc>(context);
if (state is LoadedState) {
final books = state.books;
return // booksを使ったwidget
} else if (state is NoDataState) {
return // データが無いときの表示処理
} else if (state is LoadingState) {
return // ローディング中の表示処理
}
return Container();
});
}
}
BlocConsumerwidgetを用いると、状態によって処理を分けることができます。
Widget _buildScreen(BuildContext context) {
return BlocConsumer<HomeBloc, HomeState>(
listener: (context, state) {
if (state is LoadedState) {
Navigator.pop(context); // データ取得処理が成功した場合のみpopする
}
}, builder: (context, state) {
return // widgetを生成
});
詳しくはflutter_blocをご覧ください。
テスト
テストに関するサポートもばっちりです。
詳しい説明は割愛しますが、次のようにStateをテストすることができます。
blocTest<HomeBloc, HomeEvent, HomeState>( 'テストの説明', build: () async { // blocを生成 // モックの作成等はここで行う return HomeBloc(mockPinsRepository); }, act: (bloc) { // イベントの発火 bloc.add(LoadData()); }, expect: <HomeState>[LoadingState(), LoadedState(books)]); //期待されるState }
気になるポイント🙋♀️
- 小規模なアプリや個人の開発だと冗長な処理になりがち
この場合はsetState()やStateNotifierパターンなど、もっとシンプルなものを選べば良いと思います。
- 記述量が増える
bloc、event、state用のクラスをわざわざ作成する必要があり、記述量がどうしても増えてしまいます。 コード生成ライブラリであるhttps://pub.dev/packages/freezed freezed packageを活用するのも一つの手です。
以下のサイトにはflutter_blocにてfreezedを使用した例が書かれています。
まとめ
flutter_blocではbloc、event、statteを定義し、そこからデータをwidgetに流すという方針をとっているため、誰が書いても似たようなコードスタイルになりました。 blocのUIガイドラインには、
Each "complex enough" component has a corresponding BLoC.
という記述があります。
今回は1widgetに対して1blocを用意するという原則を守ることで、どこに何の処理が書いているかを判別しやすくなりました。
複数人で開発する際には非常に役に立つpackageだと思うので、是非使ってみてください。
「リファクタリング - 既存のコードを安全に改善する」を読んでみた
おすすめされていた本の、「リファクタリング - 既存のコードを安全に改善する」を読んでみました!
本の内容
前半はJavaScriptで書かれたコードを題材に、この本で紹介されている原則に則ってリファクタリングをしていきます。
後半では前半のリファクタリングの際に用いた、様々な原則を丁寧なリファクタリング手法と共に説明されています。
より良いコードを書くためのテクニックをまとめた本といえば、「リーダブルコード」は名著として有名ですよね。
私は「リーダブルコード」も何度か読んでいますが、この本と比較すると「リファクタリング」はより具体例が豊富で、辞書的にも使いやすそうな書籍だなあという印象を持ちました。
参考になった具体例
確かに読みやすさが変わるなと思った項目を適当に2つ紹介していきます。
ファクトリ関数によるコンストラクタの置き換え
コンストラクタだけで初期化すると少し戸惑ってしまいそうな処理を、ファクトリ関数として置き換えることでよりわかりやすくできる原則のこと。 私自身はわりとシンプルにコンストラクタを使いがちだったので、これだけで扱いやすさがだいぶ変わるなという印象。
リファクタリング適用前
// sample.js leadEngineer = new Employee(document.leadEngineer, 'E');
リファクタリング適用後
// sample.js leadEngineer = createEngineer(document.leadEngineer); func createEngineer(name) { return new Employee(name, 'E'); }
委譲によるスーパークラスの置き換え
継承は既存の機能を再利用するのに強力な手法ですが、 何でもかんでも継承をしてサブクラス化してしまうと、ただ処理が複雑になってしまったり、使われない操作までもが継承されてしまう場合がありますよね。
古典的な継承の失敗例として、StackをListのサブクラスにしていることが挙げられていました。(Javaを例にすると、実際に継承されているのはVectorで、VectorがListのinterfaceを実装しているもよう。) Stackを実装するために、Listのデータ構造や処理を再利用するために継承する設計になっていたようですが、Listの操作はStackにあまり適合していないイメージ。 docs.oracle.com
//sample.java Stack<Integer> stack = new Stack<Integer>(); stack.push(2); stack.add(1);
たしかにJavaだとStackにVectorクラスのaddが実装されているのは気持ち悪い…。
C#のStackのドキュメント見てみたら、こっちのStackは割とシンプルで良さそうだった。 docs.microsoft.com
話は逸れたが、スーパークラスの関数をサブクラスで活用出来ないような場合は継承するのではなく、Listをフィールドに保持しておき、必要な操作はStackに任せたほうがスッキリする。
リファクタリング適用前
// sample.js class List { // 具体的な処理 } class Stack Extends List { // 具体的な処理 }
リファクタリング適用後
// sample.js class Stack { constructor() { this._storage = new List(); } } class List { // 具体的な処理 }
まとめ
具体的な改善例が丁寧に書かれていて、納得感が多い事例ばかりでした!
長いけど、読む価値はあると思います!!!
FlutterでMockitoを使うときにレスポンスが返却されない問題
問題
final Client _client; Future<Response> get(String relativeUrl, {Map<String, String> query}) async { final token = await _authenticationPreferences.getAccessToken(); final header = {'token': token}; _client.get( Uri.http(domain, relativeUrl, query), headers: header, ), ); }
このように定義しているメソッド(headerを付与してGETリクエストを送る)に対して、テストを行う。
group('ApiClient error handling', () { setUp(() async { //色々セットアップ }); test( 'when API return response with status code 401, [get] function should throw [UnauthorizedError]', () { when(mockHttpClient.get(any, headers: {})) .thenAnswer((_) => Future.value(Response('body', 401))); final getFuture = apiClient.get('401'); expect(getFuture, throwsA(isInstanceOf<UnauthorizedError>())); });
mockito | Dart Packageを用いてテストを行うと以下のようなエラーが帰ってきていてレスポンスが返却されない。
NoSuchMethodError: The getter 'statusCode' was called on null. Receiver: null Tried calling: statusCode
解決策
when(mockHttpClient.get(any, headers: anyNamed('headers')))
.thenAnswer((_) => Future.value(Response('body', 401)));
final getFuture = apiClient.get('401');
expect(getFuture, throwsA(isInstanceOf<UnauthorizedError>()));
headers: anyNamed('headers')
ここが重要。
dart - Flutter/Mockito. Testing API provider with mockito, problem with api headers - Stack Overflow
こちらのStack Overflowによる実際のリクエストと合う形にしないとレスポンスが返却されないもよう。
最近読んだ本や漫画と積読書
今年は2記事/月は書く!と言っていたのに全く記事を書いていなかったので、
最近読んだ本とかについてゆる〜〜〜〜く書きました。
技術書やエンジニアの方が読むと面白い書籍が多い気がします。
読んだ📖
岩田さん 岩田聡はこんなことを話していた。
任天堂の岩田元社長のことばを集めた書籍なのですが、
エンジニアとして人としても岩田元社長の姿勢というか考え方を意識していきたいと思えるので定期的に読み返している一冊!
個人的には「MOTHER2」開発中のエピソードが衝撃的だったーーー。かっこよすぎるよ!!
以下のサイトで書籍の一部分が無償公開されているので、気になる人は是非読んでほしい。
www.1101.com
WEB DB Press vol115/vol110
今回の特集は全部興味がある内容だったから全体的にがっつりよんだ。
iOSの開発最近あんまりしてないから参考なったーー🙄
gihyo.jp
こっちはgRPC周りを使う予定だったのでそのために。よくまとまっていた。
ついでに載っていた名前付け大全も良かった。
名前付け関係の話って言われればわかるわかるーって思うんだけど、いざやるとわりと悩むことがむっちゃ多い。むずい。
gihyo.jp
これだからゲームづくりはやめられない!
ゲーム会社で働くエンジニアとデザイナーのお話!
ものづくりのモチベあがるううう!まじで読んでほしいい。

これだからゲーム作りはやめられない!(2)
ランウェイで笑って
ただただ二人を見守りたいから買い続けている。最近アニメ化されたーー。

ランウェイで笑って(15)
積読📦
ノンデザイナーズ・デザインブック
個人アプリの開発の参考のために!
色んな人からもおすすめだーーってコメント来たけどまだ途中。
立ち読みして面白そうだったから買ってみた
— やや (@yayamochi) February 16, 2020
全然知識ないから個人でアプリ作るときの参考なるかなーーー pic.twitter.com/uYsacgfzPw
リファクタリング 既存のコードを安全に改善する
いつも自分のためのコードしか書いてこなかった私がバイト中に大反省した暁に購入したやつ。
ちょこちょこ直していきたい部分を読みすすめてる。もうちょっとしっかり読んだら詳しい記事書くかもしれない。

リファクタリング 既存のコードを安全に改善する







