dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

スクラムフェス大阪2024でCRE(Customer Reliability Engineer)の話をします

タイトルの通り、6/21(金)-22(土)に開催されるスクラムフェス大阪2024にて登壇します。
スクラムフェス自体初参戦です。楽しみ。

大阪と名前がついてますが鳥取トラックで採択いただき、かつ自分は当日神奈川のサテライト会場に行く予定です。
???

なぜスクラムフェスに登壇しようと思ったか

これまで「Customer系エンジニア座談会」という、CREや近しい職種の方向けのコミュニティで何度か登壇の機会をいただいたり、ブログでのアウトプットをしていました。

今年の目標として、これまでとは違ったコミュニティ、特にCREがまだ知られていなさそうな場で登壇する というのを1つの目標としていました。

その中でもRSGTやスクラムフェスは、

  • 自分自身は参加したことはないものの、前職の頃から同僚が多数参加しており馴染みがあったこと
  • スクラムに閉じずプロダクトマネジメントや組織論など多様なテーマを扱っている印象があったので、「もしかしたら無関係なようでCREの話題も受け入れられるのでは?」と思えたこと

という理由があり、思い切ってプロポーザルを出したのでした。

何の話をするのか

プロポーザルにかなり詳しく書いたので、詳細はそちらを見ていただくとして。

自分がどんな経緯でCREになり、何をしてきたのか、そしてなぜCREを面白いと感じているのかを話すつもりです。
これまでやってきたことの総まとめ的な感じです。

プロポーザルわいわい会の存在

プロポーザルを出した後、こちらのイベントに参加して外部の方から率直なフィードバックをいただくというのをやりました。

(実は金沢の方にも出してたのでこのイベントです)

これが初参加の自分にとっては非常にありがたく、自分のことやCREのことを全く知らない方からのフィードバックはとても参考になりました。

特に、

「あなたはCREに熱中している、CREオタクなんでしょう?我々が聞きたいのはそういう◯◯オタクによる熱量のこもったオタトークなんですよ」
「何が好きなのか、なぜ好きになったのか、どれくらい好きなのか」

というコメントは非常にはっとさせられました。

そこまではプロポーザルの文章は簡潔でこぎれいにまとまった感じになってたのですが、このフィードバックを受けて思いの丈をオリャーっと書きました。

大阪で採択いただけたのはこのわいわい会のおかげだと思います。

おわりに

絶賛登壇資料作成中です。少しでも良いオタトークができるようがんばります。
また、初めての参加なので自分の発表以外も楽しみたい。

AtCoder Beginners SelectionをRustで解いた

毎日ちょっとでもコード書くようにしたいなーと思っていたので、AtCoderをやってみることにした。

で、入門に良さそうな問題集としてまずはこれを解いた。

問題はこちらの記事がベースになっているらしい。

A問題はさすがに簡単なのでスキップしたけど、残りは全部解いた。

このリポジトリで管理している。

進め方

  1. 問題を読む
  2. 自力で解く
  3. ACしたら解説読む
  4. 全然違う解き方だったら解説の解き方で書き直す
  5. ChatGPTに「よりRustらしい書き方にならないかレビューしてください」って言って返ってきたコードを読む
  6. ...を1日1問ぐらいのペースでやる

ChatGPTに聞くのは気休めだけど、コレクションの操作とかで知らない書き方を教えてくれることがたまにあった。

感想

全体の感想として、これからAtCoder始めるのにちょうどいい難しさだなーと思った。
RustでAtCoderに挑戦するときの入力の受け取り方とかテストとかに慣れるのに良かった。

一方、これらの問題に関してはまだ数学的なテクニック(◯◯法、と名のつくものとか)を学ぶきっかけになったり、計算量を気にするようなものはなかった。そこは若干物足りなさがあったので、こっからステップアップしていきたい。

以後、いくつかの問題について感想を。

ABC087B - Coins

いつものfor文ゴリ押し戦法だったけど正攻法だったぽい

ABC083B - Some Sums

各桁の合計出すのに一度文字列にしたけど、10で割った余りを足して10で割るを繰り返すのがよくあるやり方らしい

ABC088B - Card Game for Two

こんな感じで書けるよってのはChatGPTに教えてもらったはず。

let (a_sum, b_sum) = a
    .iter()
    .enumerate()
    .fold((0, 0), |(a_sum, b_sum), (index, &num)| {
        if index % 2 == 0 {
            (a_sum + num, b_sum)
        } else {
            (a_sum, b_sum + num)
        }
    });

ABC085C - Otoshidama

Qiita の解説に書いてある、このへんの計算量の肌感難しい。

ABC086C - Traveling

これが一番むずかしかった。 後ろから解く、なるほどなー。

次は何やる?

とりあえずB、C問題を片っ端からやってみるかーと思ってたところ、

AtCoder に登録したら次にやること ~ これだけ解けば十分闘える!過去問精選 10 問 ~ #AtCoder - Qiita
の「ここまで解いたら」というセクションで問題がいくつか紹介されていたので、とりあえず次はこれを解くことにした。

あと、競プロ系の本いくつか家にあるのでこういうの読み進めるのと並行させたい。

2024年1月のふりかえり

あけましておめでとうございます。

✨ やったこと

「ふつうのLinuxプログラミング」を読み始めた

良い本だ、という声を昨年何度か目にしたため、買ってみることにした。
本当はもう少し積読消化してからと思っていたが、読みたいと思ったときに読むのが一番いいだろうということで。。。

数年ぶりにSalesforceを触った

とある事情により数年ぶりにSalesforceをがっつり使う機会が訪れた。
といっても今回は開発ではなく標準機能のみ。

その流れで、レポートとか実は全然わかってなかったわーといくつかTrailheadもやった。懐かしい。

Lightning Experience のレポートおよびダッシュボード | Salesforce Trailhead

ついでにCRM Analyticsも気になっている。

新しいキーボード(Keyball61)にようやく慣れてきた

昨年12月に無事組み立てが終わった Keyball61 だったが、ちょっと触っただけでは新しいキー配置に慣れなくてほとんど使いこなせてなかった。
これもう売ったほうがいいかもとか思っていたがここ1,2週間でようやく普通のテキストは打てるようになってきた。

トラックボールついているのはいいが、ずっと使い続けているとなんとなく手のどこかに負荷が溜まってる感じがする。
傾斜がないからかな。もう少し探求の余地がある。

「英語のハノン」中級突入

去年一年ぐらいかけて初級をやっていた気がする。というか毎日やる習慣は全然ついてない。
ただ何も考えずにやる教材としてはけっこう面白いので上達はあてにせず続けようと思う。

考えを雑アウトプットする訓練

今年の抱負にも書いたけど、日頃なんとなく意識していることとかを雑に言語化する、というトレーニングをやっていきたい。
ということで早速ひとつ書いた。しずかなインターネットデビュー。

sizu.me

これ以外にも書きたいなと一瞬思ったネタが3つ4つあった気がするんだけど、忘れたり億劫になったりして結局書けてない。

📕 読んだもの

↑に書いたように「ふつうのLinuxプログラミング」がWIP。

📝書いたもの・登壇

特になし。

💸 買ったもの

なんか今月は軽率に本を買いすぎた気がする。

結城浩さんの本ということで。まだ届いてないので楽しみ(そこまでにふつうのLinuxプログラミングを読めるのかというのはある)

booth.pm

大学でOSの授業とったら、その前にCPUってどういう仕組みなんだというのがだんだん気になってきて。。。
手を動かして試せる回路キットも販売されてるらしいが、5000円ぐらいするので様子見。本をぱらぱら読んでやりたくなったら買う。

本以外だと、コーヒー用の温度計を買った。

💬 所感

昨年末から今月にかけて仕事もやや忙しかったのと、家族が体調崩しがちで年明けたと思ったら最初の月が終わっていた、みたいな感じ。
目の前のやらないといけないことに忙殺されてた感は否めないが、そんな中でSalesforceのレポートとか新たに学べたのはヨシとしたい。

本当はRemixを触ってみようというテーマを持っていたんだけどそっちは最初のチュートリアルぐらいしかできていない。
あと、最近は業務では全く必要なさそうな分野(ふつうのLinuxプログラミングみたく)をもくもくとやるほうがモチベが高い。

💪2月のテーマ

というわけで2月もふつうのLinuxプログラミングをやっていく。
でもそれだけだと全然コード書かなそうだから、理想は毎日30分ぐらいコード書くような良いお題を見つけたい。

2023年のふりかえりと2024年にやりたいこと

今年も書く。はじめて年内に書くことができた。

去年

2023年中のふりかえり:

インプット(読んだもの)

まともに最後まで読んだのはこのあたり。

感想:「エンジニアのためのドキュメントライティング」を読んだ - dackdive's blog

以下は途中まで。

あと、本ではないが Tour of Rust。

書いたもの

ブログはほとんど書けていない。Customer 系エンジニア座談会 および自社のイベントでの登壇資料がいくつか。

Zenn での記事が2件。

雑感

仕事

基本的には今年も昨年と同じく CRE(Customer Reliability Engineer) として過ごした1年だった。
相変わらず「顧客の信頼性ってなんだろなー」と言う問いと向き合いながら、CRE としてやるべきだと感じたことに取り組んでいる。

今年は昨年と比べて、社内のカスタマーサクセスチームとかなり近い距離で仕事ができたのが一番の大きな変化であり、やってよかったことだと思う。
加えて、その活動の一環でカスタマーサポート体制を立ち上げ、自分自身も一部のサポート業務を担当したことは良い経験だった。サポートってどうしても縁の下の力持ちというか地味な役割だと捉えられがちな分、イケてるサポート組織を作りたいなと思った。また、テクニカルサポートという職種も面白いなと興味が湧いた。

また、今年も定期的に(だいたい半年に一度は)活動をアウトプットしておいてよかった。アウトプット時点でそこまでにやったこと考えたことを整理する良い機会になるし、間が空くと自分が何やってたかまじで何も思い出せなくなるので記録を残しておいて助かった。

反省点というか今後の展望としては、会社のイベントのLT資料にも書いたことだが来年はもっと技術的なアプローチでの貢献を増やしていきたい。
これは、今の現職において CRE が発揮できる強みがやっぱり技術的な部分になると感じているのと、あとは自身のモチベーションにつながるからというのもある。プロダクト開発じゃなくていいのでやっぱコードは書きたいよなあと。


プライベート

まずはじめに大きな反省として、定期的なふりかえりをサボってしまっていた
ブログを見ると一目瞭然だが、今年は1月、2〜6月の2回しかふりかえりをしていない。

原因として考えられることはいくつかあるが、ひとつは今年の後半はちょっと仕事が忙しくなってしまい、気持ちと時間の両面でふりかえる余裕がなくなってしまったこと。 ただこれは明らかに良くないことだったと感じていて、

  • 忙しくなる
  • →ふりかえりをサボるようになる
  • →その月(or 四半期)何をやっていたかわからなくなる
  • →成長を実感できなくなる
  • →モチベーションが低下する

みたいな心境になってしまっていた。やはり忙しいときこそふりかえり大事や。。。

あと個人でふりかえっても淡々と事実を列挙するのみになってしまう感じがしていて、コーチングとかもそろそろ受けてみようかなあという気持ちがある。

別な話題としては、趣味の大学生活(UoPeople)はなんだかんだ続いている。
ただ今年は Computer Systems と Web Programming 1 という2単位しか取得していない。今はちょうど Operating Systems 1 という講義を取っているがこの term での単位取得はすでに諦めている。

ペースとしてはめちゃくちゃ遅いので卒業要件を満たすのにはまだまだ先になりそうだが、今までちゃんと学んでこなかった分野を学ぶのは面白い。
Computer Systems の講義では気になってた コンピュータシステムの理論と実装 ―モダンなコンピュータの作り方 の前半を読むきっかけになったので良かった。

一方、英語きっついのと Peer Assessment(学生同士で議論したり採点する制度)という仕組みは自分には合わない...

技術的な勉強でいうと、今年は何かを学んだという実感がほとんどなかったなあ。。。
OpenAI を追っかけつつ大学の講義やりつつ Rust も書きたいっつってほとんど習慣化しなかったので全部中途半端になってしまったな、という感覚。

2024年にやりたいこと

これといって何かを新しく始めたいということはないので、いつものことだけどその時その時で興味を持ったことを深ぼっていくスタンスでいいかな。

今関心があるのはテクニカルライティングデータ分析とかSQL。あとコンピュータサイエンス系ももちろん引き続き興味はあって、今 OS について学んでるけど OS を理解するのに CPU の仕組みが知りたいなあとなっている。

2024年に心がけたいこととして今2つ頭の中にあるのは、1つはもっと雑なアウトプットを増やす(いつも言ってる気がする)。
ブログ投稿増やそうってのもあるし、技術以外に自分が考えていることを言語化する訓練をもうちょいしたほうがいいなと思った。 自分が好きなブログに Konifar's ZATSU というのがあって、これよりもっともっとクオリティが低くていいので普段意識してることとか大事にしてる考え方みたいなのをアウトプットしたい。

しずかなインターネット はそういう使い方にとても良さそう。

もう1つは、もっと家族と過ごす時間や勉強以外の自分の時間を大切にしたい。 家族と過ごす時間については、もっと時間を増やさねば!というよりは、時間は割いてるが脳みそは家族に向き合えてないって後から反省することがたびたびあった。話聞いてるつもりがずっと仕事のこと考えてる、とか。
子供もそうだし、妻のことも今よりもう少しだけ大切にしたい。子供3人いてしんどい時があるのは自分だけじゃないので。

また、自分自身については、若い頃に感じていた成長しないといけない病はもうだいぶ薄れたかなと思うんだけど、それでもやっぱり余暇をなるべく生産性高く過ごさねばみたいな思考は若干ある。
年末に実家帰ったら母親がSwitchとスーパーマリオブラザーズワンダー買ってて、子供と一緒にやったらめちゃくちゃ面白かったので、あーこういう時間も必要なんだよな、と思うなどした。

というわけで来年も無理せずやっていく。

Tour of Rustをやった

もう一度Rustを勉強したくなったが The Rust Programming Language をやる気力はなかったので、Tour of Rust をやってみた。

tourofrust.com

大部分が日本語に翻訳されている。ありがたい。

ざっとやってみた感想としては、

  • 基本的な文法、概念は一通りカバーできていて良い
  • 文字列だけでまるまる1章使ってるのは良い(第6章)
  • 所有権、借用、ライフタイムについては難しさに対して説明はさらっとしててこれだけでの完全理解は無理だった
  • 第8章 スマートポインタは何もわからない

Tour of Rust をやってもまだ理解が不十分なところとしては

  • 所有権と借用
    • 構造体にメソッド生やすとき、どういうときに参照を受け取るような設計にして、どういうときに所有権を移動させるべきなのか。参照で済む場合は極力参照?
  • ライフタイム
  • 動的ディスパッチ

以下、各章の簡単なメモ。

第1章 - 基礎

  • 基本的な型
    • 配列型 - コンパイル時に長さが決まる同じ要素のコレクション
    • スライス型 - 実行時に長さが決まる同じ要素のコレクション
    • str(string slice) - 実行時に長さが決まるテキスト

第2章 - 基本制御フロー

  • for文は “イテレータとして評価される式を反復処理します”
  • .. 演算子は、開始番号から終了番号の手前までの数値を生成するイテレータを作成します”
  • match
    • matched_num @ 10..=100 で変数に束縛できるの知らなかった
  • loop から値を返す
  • ブロック式から値を返す
      let v = if x < 42 { -1 } else { 1 };
    

第 3 章 - 基本的なデータ構造体

  • メモリ:Rustでは次の3種類のメモリ空間を持っている
    • データメモリ:固定長もしくはスタティックなデータ
    • スタックメモリ:関数内で宣言された変数
    • ヒープメモリ:プログラムの実行時に作られるデータ
      • このメモリにあるデータは追加、移動、削除、サイズの調節などの操作が許されている
      • データをヒープメモリに入れることをアロケーション(allocation)、ヒープメモリから削除することをディアロケーション(deallocation)という
  • 列挙型にはデータを持たせることもできる

第 4 章 - ジェネリック型

  • ジェネリック
  • Option
  • Result
  • ? 演算子:Result 型が Ok なら値を取り出し、 Err 型ならその場で return
  • unwrap やっつけな Option / Result 処理
  • ベクタ型: Vec<T>
    • iter() を使うとベクタからイテレータを生成できる。for ループに使える
      let string_vec = vec![String::from("Hello"), String::from("World")];
    
      for word in string_vec.iter() {
          println!("{}", word);
      }
    

第 5 章 - データの所有権と借用

  • 所有権

    型のインスタンスを作成して変数に束縛するとメモリリソースが作成され、そのすべてのライフタイムに渡って Rust コンパイラが検証します。 束縛された変数はリソースの所有者と呼ばれます。

  • スコープベースのリソース管理
    • スコープが終わるとリソースのデストラクトと解放を行う

    C++ では Resource Acquisition Is Initialization (RAII)「リソース取得は初期化である」とも呼ばれています。****

  • 参照による所有権の可変な借用

      struct Foo {
          x: i32,
      }
    
      fn do_something(f: Foo) {
          println!("{}", f.x);
          // f はここでドロップ
      }
    
      fn main() {
          let mut foo = Foo { x: 42 };
          let f = &mut foo;
    
          // 失敗: do_something(foo) はここでエラー
          // foo は可変に借用されており移動できないため
    
          // 失敗: foo.x = 13; はここでエラー
          // foo は可変に借用されている間は変更できないため
    
          f.x = 13;
          // f はここから先では使用されないため、ここでドロップ
    
          println!("{}", foo.x);
    
          // 可変な借用はドロップされているため変更可能
          foo.x = 7;
    
          // foo の所有権を関数に移動
          do_something(foo);
      }
    
    • 💬 f は暗黙的にこれ以上使われてる箇所がないと判断されて途中でドロップするんだな
  • 借用したデータの受け渡し

    • Rust では、可変な参照が 1 つだけか、不変な参照が複数かのどちらかが許可されます。両方を同時には使用できません
    • 参照は所有者よりも長く存在してはなりません。
      • 前者はデータ競合を防ぐ
      • 後者は存在しないデータへの参照(ダングリングポインタ)を防ぐ
  • 明示的なライフタイム

    関数は、どの引数と戻り値とがライフタイムを共有しているかを、識別のための指定子で明示的に指定できます。

      // 引数 foo と戻り値はライフタイムを共有
      fn do_something<'a>(foo: &'a Foo) -> &'a i32 {
          return &foo.x;
      }
    
  • 複数のライフタイム

  • スタティックライフタイム
    • 'static という特別なライフタイム指定子
    • 文字列リテラル'static

第6章 - テキスト

  • 文字列リテラル&'static str

    str は常に有効なutf-8であるバイト列を指していることを意味しています。

  • utf-8 とは
  • 文字列スライス

    文字列スライスは、常に有効な utf-8 でなければならないメモリ内のバイト列への参照です。

    • 常に有効な utf-8 でなければならないとは? → 絵文字の途中とかでスライスするとパニックする
  • Chars

    • utf-8バイトのシーケンスを char 型のベクトルとして取得する
      let chars = "hi 🦀".chars().collect::<Vec<char>>();
    
  • String

    • メモリがヒープ上にあるので拡張や修正が可能
  • 関数パラメータとしてのテキスト

    文字列リテラルや文字列は、一般的に文字列スライスとして関数に渡されます。 これによって、実際には所有権を渡す必要がないほとんど場合において柔軟性が増します。****

  • 文字列の構築
    • concatjoin
  • 文字列のフォーマット
    • format!マクロ
  • 文字列変換
    • 多くの型は to_string でStringに変換可能
    • 文字列や文字列リテラルからparse で型付きの値に変換できる。失敗する可能性があるので Result を返す

第7章 - オブジェクト指向プログラミング

  • オブジェクト指向プログラミングとは?
  • Rustはオブジェクト指向プログラミング言語ではない
    • データと動作の継承機能を意図的に持っていない
  • 選択的な公開による抽象化
    • pub キーワードで構造体のフィールドやメソッドをモジュール外に公開
    • フィールドとメソッドは、デフォルトではそれらが属しているモジュールにのみアクセス可能
  • トレイトを用いたポリモーフィズム
    • trait はinterfaceみたいなもの
  • トレイトに実装されたメソッド
    • トレイトは実装されたメソッドを持つこともできる
  • 動的ディスパッチと静的ディスパッチ
    • 静的ディスパッチ - インスタンスの型がわかっている場合、どの関数を呼び出せばよいかを直接知ることができる
    • 動的ディスパッチ - インスタンスタイプが不明な場合、正しい関数を呼び出す方法を見つけなければならない
    • 要は、関数やメソッドの引数に構造体ではなくトレイト(&dyn MyTrait)を受け取るように書かれているもの
      • fn dynamic_make_noise(noise_maker: &dyn NoiseMaker) {
  • トレイトオブジェクト
    • &dyn MyTrait型のパラメータに渡すとき、トレイトオブジェクトと呼ばれるものを渡す
    • 🤔

    インスタンスの正しいメソッドを間接的に呼び出すことを可能にするのがトレイトオブジェクトです。 トレイトオブジェクトは、インスタンスのポインタと、インスタンスのメソッドへの関数ポインタのリストを保持する構造体です。

  • サイズの合わないデータの処理
    • 🤔

    トレイトは元の構造体を難読化するため、元のサイズも難読化されます。

    • 構造体に格納されるサイズの合わない値は、2つの方法で処理される
  • ジェネリック関数
  • ジェネリクス関数の省略記法
    • where のかわりに、引数に impl Trait と書くこともできる
    • 「実践Rust入門」だともう1つ、型パラメータに <P: Trait> と書く方法も紹介されていた
  • ボックス(Box)
    • データをスタックからヒープに移動させるためのデータ構造
    • スマートポインタと呼ばれる構造体で、ヒープ上のデータへのポインタを保持する
    • たとえば Vec<dyn NoiseMaker>>dyn NoiseMaker のサイズがコンパイル時に決まらないためエラーになる。Boxで囲むことでコンパイルエラーを解決できる
  • ジェネリクス構造体

[未翻訳] Chapter 8 - Smart Pointers

  • References Revisited
    • 参照 (reference) とは、単にメモリ上のバイトの開始位置を示す数字でしかない
    • 何が参照とただの数字を異なるものにしているかというと、Rustは参照のライフタイムが参照先(所有者)より長く存在していないことを検証するという点
  • Raw Pointers
    • 参照は生ポインタ型(raw pointer)というよりプリミティブな型にコンバートできる
    • 数値とよく似て、多少の制約はあるもののコピーやムーブができる
    • Rustは生ポインタが指し示す先のメモリ位置についてなんの保証もしない
    • 2つの生ポインタがある
      • *const T 不変
      • *mut T可変
  • Dereferencing 参照外し
  • The * Operator
  • The . Operator
    • 勝手に dereference するので * つけなくていい
  • Smart Pointers
  • Smart Unsafe Code
    • 数値を生ポインタとみなして参照外しをする場合、Rustはそのメモリ位置が妥当であることを何も保証できないので unsafe ブロックで囲む必要がある
  • Familiar Friends
    • Vec<T>String もスマートポインタ
    • サンプルコードの alloc とか Layout は理解するの諦めた
  • Heap Allocated Memory
    • Box 型
    • データはヒープに置かれ、そのポインタをスタックに保存する。が、あたかもスタックにデータがあるかのように値に直接アクセスできる
  • Failable Main Revisited
    • fn main() -> Result<(), Box<dyn std::error:Error>> とするとmainですべてのErrorを捕捉できる****
    • Errorはトレイトなのでdynにする必要あり
  • Referencing Counting
  • Sharing Access
  • Sharing Across Threads
    • Mutex
    • マルチスレッドで使う?

[未翻訳] Chapter 9 - Project Organization and Structure

モジュールの基本的な考え方は昔まとめた:

Rustのモジュールシステムの基本 - dackdive's blog

  • Modules
    • すべてのRustプログラムあるいはライブラリはクレート
    • すべてのクレートはモジュールの階層構造でできている
    • すべてのクレートはルートとなるモジュールを持つ
    • モジュールは、グローバル変数や関数、構造体、トレイトや他のモジュールを保持できる
  • Writing a Program
    • プログラムは main.rs というルートモジュールを持つ
  • Writing a Library
    • ライブラリは lib.rs というルートモジュールを持つ
  • Referencing Other Modules and Crates
    • モジュール内の各要素を利用する方法。フルパス指定か、use キーワード
  • Referencing Multiple Items
    • use std::f64::consts::{PI,TAU}
  • Creating Modules
    • foo というモジュールを定義する方法は2つ
      1. foo.rs
      2. foo/mod.rs
  • Module Hierarchy
  • Inline Module
  • Internal Module Referencing
    • use で使える特別なキーワード:crate , super, self
  • Exporting
    • pub で他モジュールからも使えるよう公開できる
  • Structure Visibility
    • 構造体のフィールドも個別に pub つける必要がある
  • Prelude
    • 何も use してないのに VecBox が使えるのはなぜか?
    • std::prelude::* というモジュールは自動的に読み込まれているから
  • Your Own Prelude
    • 独自のライブラリを作ったときも、そのライブラリを使用するための最も一般的なデータ構造を prelude として公開すると良い

2023年2月〜6月のふりかえり

毎月書く!って言ってたのに、1月のふりかえりから半年も空いてしまった。。。

2023年1月のふりかえり - dackdive's blog

✨ やったこと

3月〜4月:「エンジニアのためのドキュメントライティング」を読んだ

dackdive.hateblo.jp

詳しくは↑の感想記事に譲る。

5月:イベント登壇した

customer-x-engineer.connpass.com

昨年10月にも登壇させていただいたこちらのイベントに2度目の登壇をさせていただいた。
CRE としてのアウトプットを話す場はここぐらいしかないのでありがたい。

資料はこちら。

speakerdeck.com

前回もそうだったが、登壇を通じてこれまでやってきたことの棚卸しができた&対外的なアウトプットの機会になったので非常に良かった。
ブログをもう少し書いていきたい...!

📕 読んだもの

これ、半額セールで買ったけど面白かった!すごい勉強になる、っていうより日常的によく見るいじわるなUIがサンプルとして多数紹介されててわかりみが深い〜ってなった。

📝書いたもの・登壇

登壇は上に書いたとおり。ブログも、エンジニアのためのドキュメントライティングのやつを除くとわずか1件。

💸 買ったもの

子供の見守り用に。小さいしアプリの出来も良くて好き。

積読系は以下。

作ってわかる!自然言語処理AI

作ってわかる!自然言語処理AI

Amazon

頑張って読み始めたけど全然わからんのでゼロからわかる〜を読んだ、という流れ。

💬 所感

この半年でやったことを思い出しつつ、最近感じたことなどを。
せっかくなので最近できた有料記事機能を使ってここから先は有料にしてみる。

この続きを読むには
購入して全文を読む

「エンジニアのためのドキュメントライティング」を読んだ

読んだのでメモ。

本書の目次

PART I ドキュメント作成の準備
- CHAPTER 1 読み手の理解
- CHAPTER 2 ドキュメントの計画

PART II ドキュメントの作成
- CHAPTER 3 ドキュメントのドラフト
- CHAPTER 4 ドキュメントの編集
- CHAPTER 5 サンプルコードの組み込み
- CHAPTER 6 ビジュアルコンテンツの追加

PART III ドキュメントの公開と運用
- CHAPTER 7 ドキュメントの公開
- CHAPTER 8 フィードバックの収集と組み込み
- CHAPTER 9 ドキュメントの品質測定
- CHAPTER 10 ドキュメントの構成
- CHAPTER 11 ドキュメントの保守と非推奨化

この本について

ドキュメントを書くことになったエンジニアが意識すべきことが網羅的にまとめられた本、という印象。

本書の主張を端的に表すと「ドキュメントもプロダクト開発と同じような考え方で計画・実装・運用しましょう」ということに尽きる、と解釈した。

プロダクト開発と同じように、とはたとえば次のようなこと。

  • 読み手(ユーザー)を理解し、何がドキュメントとして必要なのかを書き始める前に明らかにしておこう
    • プロダクト開発において、機能を作る前にユーザーのニーズを把握しようという話と似ている
  • いきなり最終的な文章を書き始めるのではなく、はじめにアウトラインを作り、ドラフトを書こう
    • プロダクト開発において、実装前におおまかな設計方針を立ててレビューしたり、実装時にまずコメントでおおまかな処理を書いてから肉付けしていくやり方に似ている
  • レビュー時にはレビュー観点を明確にしよう
  • リリースプロセスを明確にしよう。最終レビュー者は誰か?どこに公開するのか?新しいコンテンツをどのように発表するか?
  • リリースしたドキュメントに対してユーザーからフィードバックを受けるチャンネルを作ろう
  • リリースしたドキュメントが良いものであったか、品質を測定しよう

なので、(これは読む前の期待値とギャップがあった箇所でもあるが)単に良い文章を書くためのポイントではなく、その前後も含めた計画フェーズ、運用保守フェーズについても書かれている。というよりそちらのほうに重点が置かれている。

そのため、きれいな日本語文章を書くためのテクニックが知りたいという人にはあまり適さないように感じた。そういう人には日本語スタイルガイドのような書籍のほうが適切だと思う。(そっちも買ったけど読み途中)

もうひとつ、読む前の期待値とのズレがあったところとしては、本書では主に開発者向けのドキュメントの書き方を扱っているというところ。そのため、たとえばCHAPTER5では1章まるまる使ってドキュメント中のサンプルコードについて言及されている。なので自分のように非開発者向けのドキュメントを書こうとしている人には少々学びにしにくいところがあるかもしれないが、CHAPTER5 以外はおおむねどんなドキュメントに対しても言えることが書かれていたように思う。

感想

ドキュメントを書く「前」と書いた「後」のことまで扱った書籍は初めて読んだので参考になった。特に、公開後の品質測定と保守、非推奨化のところは読んでいてなるほどと思う部分が多かった。
また、構成に関しては、各章の冒頭に架空の企業(「Corg.ly」という、犬の鳴き声を人の言語に翻訳するサービスを開発している企業)のストーリーが書かれており、内容がすっと頭に入ってきやすかった。

あと、末尾に発展的な学習のためのリソースや参考文献のリンクが大量にあってありがたい。

不満な点、というかいまいち腹落ちしきれなかった点があるとすると、本書はドキュメントを書く前から書いた後までを体系的に学べる分、一個一個のトピックについてはさらっとしている。そのため、具体的なテクニックについてはそこまで書かれておらず、明日からすぐに使える実用的な知識が身についたかと言われるとそうではなかった。
この記事のように感想や要点をメモしておかないと「なんか良いこと書いてあったなー」で終わってしまいそうな本だった。※自分の場合、技術書以外は大体そうなりがち
逆に言うと、エンジニアとしてのキャリアでもっと早くから出会いたかった本。

メモ

印象に残った箇所をメモ。

読み手(ユーザー)を理解する

CHAPTER 1 読み手の理解 より。
効果的なドキュメントを書くためにはとにかく読み手となるユーザーへの共感、具体的にはユーザーがそのドキュメントに何を求めているのかを理解する必要があると書かれている。そして、ユーザーを理解するために次のような方法を紹介している。

  • ユーザーのゴールを理解する
    • ユーザーがドキュメントを読んで達成したいこと(例:犬の鳴き声を人の言葉に翻訳する)と、ユーザー全体に渡る組織のゴール(例:Corg.lyのAPIを新規ユーザーが組み込めるように支援することで、新規ユーザーを獲得してオンボードする)との整合を取る
  • ユーザーを理解する
    • ユーザーが開発者だったら、スキルレベルは?役割は?
  • ユーザーの理解を検証する
    • サポートチケットなど既存の情報リソースを活用したり、インタビュー、開発者アンケートなどを通じて新しい情報を集める
  • ユーザー調査から得られた知見をまとめる
    • ペルソナ、ユーザーストーリー、ジャーニーマップ、フリクションログ

個人的には最後に出てくるフリクションログというのが初耳だった。フリクション = 摩擦、抵抗 の意味で、本書ではソフトウェアやサービスの利用時にうまく使えなかったことや、違和感などを示している。ユーザーに代わって自分自身がソフトウェアを試して体験を記録し、そのときに感じた違和感やイライラがドキュメントやソフトウェアの改善のヒントになる。

フリクションログの例(「CHAPTER 1 読み手の理解」より引用)

機能品質と構造品質

CHAPTER 9 ドキュメントの品質測定 より。
まず、章の冒頭でこのような文がある。

ドキュメントの品質を測定する前に、まず「品質」の定義から始める必要があります。幸いなことに、Googleの執筆者とエンジニアのグループがまさにこの質問に取り組んでいました。つまり、コード品質の評価と似た方法によって、ドキュメントの品質を測定していたのです※60。彼らの作成したドキュメントの品質の定義はとても簡単です。

ドキュメントが優れているのは目的にかなっている場合である。

そして、ドキュメントの品質を機能品質と構造品質に分類し、以下のように定義している。

  • 機能品質:ドキュメントの目的やゴールが達成されているかどうか
  • 構造品質:ドキュメント自体がうまく書かれているか、うまく構成されているか

ここで重要なのが、機能品質と構造品質では機能品質のほうがより重要であるということ。ドキュメントとしていかに上手にかかれていたとしても、目的やゴールが達成されない限りは良いドキュメントとは言えないということになる。

ドキュメントの品質をどう測定するか

同じく CHAPTER 9 ドキュメントの品質測定 より。
先ほど機能品質のほうが構造品質よりも重要だと書いたが、じゃあ機能品質をどう測定すればいいの?については明言されていない。 "機能品質全体の測定は困難です" と書かれているぐらいだ。ただ、CHAPTER1で定義した読み手のゴールやより上位の組織のゴールと照らし合わせて、そのゴールの達成度合いをどう測定すればいいかを考えることになる。

また、少なくとも次の質問に応えられるようにすべき。

  • なぜ測定したいのか?
  • その情報を使って何をするのか?
  • その努力で、どのように組織のゴールを前に進められるのか?

ドキュメントの保守:いかにして新鮮な状態に保つか

CHAPTER11 ドキュメントの保守と非推奨化 より。
プロダクトのリリースプロセスにドキュメントの変更も組み込むことで整合を取りましょう、という話はせやなって感じ。

あと面白かったトピックとしては

ドキュメントオーナーを決める

ドキュメントの責任は全員にある、と考えられることが多くあります。それゆえに、誰も責任を負ってないとも言えるでしょう。そこで、ドキュメントの課題への対応、ドキュメントの変更に対するレビュー、必要であればドキュメントの更新に責任をもつドキュメントオーナーを明示的に任命することで、責務を明確にしてください。責務の明確化は、ドキュメントが古くなることの防止に役立ちます。

コンテンツの鮮度確認

ドキュメントが大規模になると知らず知らずのうちに情報が古くなることもあるので、コンテンツを確認する予定日を決めておくという手もある。たとえばGoogleでは、ドキュメントの上部に次のようなメタデータを埋め込んでおくことで、コンテンツが現在でも正確かどうか確認するようなリマインダーを飛ばすしくみがあるらしい。

<!--
Freshness:{owner:“karthik”reviewed:2021-06-15}
-->
リンクチェッカー

ドキュメント内で大量にリンクされてるといつの間にかリンク切れが発生するので、それを防ぐリンクチェッカーというツールがある。本書で紹介されているのは htmltest というもの。よさそう。


ドキュメントオーナーと鮮度確認の話を読んで、Notion に最近追加された Wiki 機能を思い出した。

Wikiとページの有効性確認 – Notion (ノーション)ヘルプセンター

まだ自分では使いこなせていないんだけど、Verification というのが「このページは○日間は新鮮な情報です!」という意思表示をすることで、読み手に今も有効なドキュメントかどうか示すことができるし、期限切れ時に通知がくるので最新かどうかチェックする役目も果たせる。(○日までは新鮮!って言ってもそれまでに情報が古くなってる可能性は全然あるんだけど、ないよりまし的な)

気に入った一節

可能ならば、よく報告される課題と顧客からのフィードバックのトレンドを理解するために、サポートチームと密に連携しましょう。顧客が同じ課題に何度も遭遇しているなら、ドキュメントまたはプロダクトを更新することで、その課題を解決する必要があります。

CHAPTER8 フィードバックの収集と組み込み より。
ドキュメントへのフィードバックを受け付けるチャンネルのひとつとしてサポートチケットもあるよね、ぐらいのさらっとした内容なので全然重要でもなんでもないんだけど、最近カスタマーサポート体制のこととかを考えていたので思うところがあった。

問い合わせ対応ってプロダクト開発における割り込みタスクとして敬遠されがちだったり、専門チーム作ってそっちに任せるのが定石っぽくなってるけど、やっぱりお客様から一番最初にいただく声ってプロダクトやドキュメントの改善の種としてはものすごい財産なんだよなー、だからチーム分けるにしてもそこをうまくつないであげる必要があるよなー、みたいなことを考えていた。ドキュメント関係ない。

余談

読書メモの残し方はこの2つの記事を参考にした。

前者を真似してメモを残す作業をやらなかったら絶対記憶に残らない本になってたと思うし、後者の気に入った一節を探す作業も「んーどこが一番お気に入りだったかな」って考えながらハイライト箇所を行ったり来たりして楽しかった。

参考リンク