dackdive's blog

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

累積和とは何か、およびABC098 C: Atttentionの解説

を解いていて、「累積和」という概念を知ったのでメモ。

こちらの本の「4.2 階差と累積和」でも紹介されている。

また、すでに

という素晴らしい記事があるので、ここでは累積和についての簡単な説明と、具体例としてABC098のC問題の解き方を紹介。

累積和とは

数列 a = [a_1, a_2, ... a_N] に対して

s_0 = 0  
s_1 = a_1
s_2 = a_1 + a_2
...
s_i = a_1 + a_2 + ... + a_i

つまりi番目までの和をとったものを累積和と呼ぶ。

累積和の何がうれしいのか

「配列の特定の区間の和を求める」ような処理を大量に行うシーンにおいて、
累積和を先に計算しておくことで、求めている計算結果を高速に得られる

ということだと理解した。

もう少し具体的に書くと、数列 a = [a_1, a_2, ... a_N] の l 番目から r 番目までの和を求める場合、O(N) の時間がかかる。

let sum = 0;
for (let i = l; i < r; i++) {
  sum += i;
}

これに対し、累積和を先に求めておくと、l 番目から r 番目までの和は

s[r+1] - s[l]

なので、O(1) で求まる。

なお、累積和の計算は、先頭の要素から順に足し合わせていけばいいので O(N) で求まる。

ABC098 C問題:Attentionを解く

ここで、具体例として冒頭に挙げた問題を考えてみる。

問題文は以下。

N 人の人が東西方向に一列に並んでいます。 それぞれの人は、東または西を向いています。 誰がどの方向を向いているかは長さ N の文字列 S によって与えられます。 西から i 番目に並んでいる人は、S_i = E なら東を、S_i = W なら西を向いています。

あなたは、N 人のうち誰か 1 人をリーダーとして任命します。 そして、リーダー以外の全員に、リーダーの方向を向くように命令します。 このとき、リーダーはどちらの方向を向いていても構いません。

並んでいる人は、向く方向を変えるのを嫌っています。 そのためあなたは、向く方向を変える人数が最小になるようにリーダーを選びたいです。 向く方向を変える人数の最小値を求めてください。

まず、i 番目の人をリーダーに任命した場合、

  • 1〜(i-1)番目までで「西」を向いている人
  • (i+1)〜N番目までで「東」を向いている人

は、それぞれ向く方向を変える必要がある。

これを、iを1番目からN番目までループしつつ計算すると、O(N2)の計算量になってしまう。

そこで、

s_i = 1番目からi番目までで、東(or 西)を向いている人の数の合計

と定義する。

そうすると、i番目の人がリーダーのときの求めたい人数は

1〜(i-1)番目までで「西」を向いている人
-> s_[i-1]


(i+1)〜N番目までで「東」を向いている人
-> (i+1)〜N番目までの人数 - (i+1)〜N番目までで「西」を向いている人
-> (N - i) - (s_N - s_[i])

両者を足し合わせることで導出できる。

以上を Rust で書くと、こんな感じ。

use proconio::{input, marker::Chars};

fn main() {
    input! {
        n: usize,
        mut chars: Chars,
    }

    let mut s = vec![];
    s.push(0);

    // s[i]: 1~i 番までで W を向いている人の数
    let mut count = 0;
    for &ch in &chars {
        if ch == 'W' {
            count += 1;
        }
        s.push(count);
    }

    // i 番目がリーダーだったとき、
    // 1~i-1 番目まで: W を向いている人が向く方向を変える => s[i-1] 人
    // i+1~n 番目まで: E を向いている人が向く方向を変える
    // => W を向いているのが s[n]-s[i] 人
    // => E を向いているのは {n-(i+1)+1} - (s[n]-s[i])
    let mut ans = n;
    for i in 1..=n {
        let target_num = s[i - 1] + n - i - (s[n] - s[i]);
        if ans > target_num {
            ans = target_num;
        }
    }
    println!("{}", ans);
}

おわりに

愚直に計算するとタイムアウトになっちゃいそうだなーというときに使えそうなテクニック。
ただし、わかっていても何を累積和として計算しておくか、が閃かないと難しそう。

冒頭で記載した Qiita の記事には他の過去問も紹介されてたので、何個か解いてみるとコツがつかめるかなー。

「ヘルプセンターを支える技術 ── 生成AI時代の自己解決エンジニアリング」に参加したメモ

行ってきた。

メルカリのヘルプセンター内製化:自己解決率向上とCPT削減への挑戦

(ちょっと遅れて参加)

  • CSディビジョンが目指すこと
    • Effortless Customer Experience
    • 問い合わせること
    • JR CS Engineering
      • Help Center ← 登壇者はここに所属
      • Contact Center
  • Help Center Teamが追い求める指標
    • 自己解決率
      • CPT (Contact Per Transaction) 問い合わせ数
      • 取引数を分母にして割ることで、ユーザー増加しても一定の数値にする
    • AHT (Average Handling Time) 🤔定義聞き逃した
      • 想定ガイド閲覧率
  • Help Center大幅リニューアル (2022年)
    • アプリやWebそれぞれに問い合わせフォームがあり、それぞれの開発チームがオーナーだった
    • ガイドごとに、それにひもづいたフォーム
  • Skill Base Routing
    • フォームごとにtypeが設定されてる
    • Primary Queue
      • SkillごとにQueueが建てられ、入信順にお問い合わせが並ぶ
    • Site Queue
      • Skill A はコンタクトセンターAに40%、Bに40%、…となるよう差配される
    • 🤔Skillとはコンタクトセンターの人員の能力?
  • 内製化の利点1:Data Drivenな改善サイクル
    • A/Bテストの共通プラットフォームがある
  • 内製化の利点2:Personalization
    • 問い合わせ前に購入した商品を選ばせる。そのためにメルカリのAPIと連携する
  • Help Center Platforming
    • 課題:新規ビジネスを立ち上げるたびにHelp Centerを作っている
    • 今後:内製Help CenterをPlatf

自己解決を支える検索技術と改善サイクル

Helpfeel CTO akiroom

  • Helpfeelのアルゴリズム「意図展開」
    • 登山のメタファー
    • 例:商品の返品方法 というゴールに対し、入口(登山道)はさまざま
  • 伊予銀行の事例「ハンコ なくしちゃった」
  • 曖昧検索
    • asearch
      • タイポなどを吸収
    • 意図予測検索2
      • 意図展開したデータを元にベクトル検索
      • ユーザーの話し言葉に近い文章
      • OpenAI と Qdrant
    • インクリメンタル検索をフロントエンドだけで完結する。メインスレッドをブロックしないようWeb Workerを使う
    • 400件のFAQに対し20000件ぐらいの質問文
      • 400KBぐらいしかない
  • 本当に役立つFAQ検索システムを目指して - Nota TechConf
  • 顧客体験向上のキーは「必要な情報に・正しく到達」すること(コールセンター白書より)
  • FAQは重要なユーザータッチポイント
    • 検索性の問題と、コンテンツの問題
  • 検索ヒット率の改善サイクル
    • みるべきKPI ←←大事なポイントだったのに書けなかった!

どこに何の問題があるだろう? HWからSWまでの全領域を横断した最速解決を支援する生成AI活用

佐々木 了 @gzock / 株式会社ビットキー テックリード

  • スマートロックの会社。ただそれだけじゃない
  • ビットキーにおけるAI活用
    • プロダクトへの組み込みと、社内での利用。今回のメインは後者
  • 日々現場で発生するトラブル対応の自己解決支援にAIを活用している
  • 課題:領域を横断するトラブル対応の難しさ
    • toC領域はなんとかなる
    • toB向けはカスタマーサクセス部隊の担当者へ直接つながる
    • →とんでもない脳内辞書を持った職人が生まれる
  • 解決:職人芸のAI化
    • ナレッジのデータベースが作られはじめていた
    • それを材料にSlackボットを作成
    • 結果を👍👎で評価
    • 開発側では、質問と応答と評価を後で見て色々チューニング
    • 最初はVertex AIベース→性能よくないのでAWS Bedrock→Gemini 1.5 Proが最も精度が高い
  • ビットキーはマルチクラウド
  • 生成AIの精度を上げるためにも、そもそものデータをどう集めるか?どうフィードバックして改善するか?が大事
  • それっぽいものは簡単につくれる
    • が、現場での質問は開発側の想定を軽々と超えてくる
    • 巻き込み力が必要不可欠
  • まずはスコープ絞って、それに特化したデータを集めつつ、試行錯誤するのがオススメ
    • 汎用性を持たせようとすると泥沼にハマっていく

パネルディスカッション

メルカリ濱村 甚平さん

メ)メルカリ、ビ)ビットキー、H)Helpfeel

Q1. CSチームとの目線合わせや連携をどうやってますか?

  • メ)CS組織がでかい。普段どんな問い合わせが多いのか、などを取りまとめてくれるプログラムマネージャーがいて、その方が開発側のデイリーに参加している
    • いわゆるスクラムっぽく回している?
    • YES。PdMもいるが、僕らのユーザーは社内にいるので、カウンターパートという存在
  • ビ)しょっちゅうそのへんでCSの人たちと話している。エンジニアの人と話すより多いかも。愚直に人間同士のコミュニケーション
  • H)FAQのプラットフォームを作っており、当社のCSがお客様とのMTGを行っている。そこで具体的な検索クエリを見てる。CSは顧客とかなり仲良くなっている

Q2. 生成AI使ってぶっちゃけどう?上手くいってる?

  • メ)道半ば。正式に採用されてないがテストはしてる。一部問い合わせに使ってみたり
  • H)検索にそこまで深く使うということはしていない。生成AIを検索に使おうとするとRAGになるが、結局裏に検索エンジン使ってるので検索エンジンに注力
    • 無限にスケールできる頭脳ができたとみなしている。周辺領域で使ってる。雑に書いた文章から記事化する、とか(お客様が機能として使ってる)
  • ビ)同意。本当にtoC向けで表に出すのはリスキー。発表内容の事例がうまくいってるのは人間が介在しているから

Q3. ヘルプセンターを主務としている方々の今後のキャリアはどうすべき?

  • ビ)ヘルプセンターに限った話ではなく、変化についていけるかどうかだと思う。エンジニアもそうだが、本当に単純な、領域絞ったことに対してはけっこうな精度で返してくれるが、それで専門職としての仕事が完全に奪われるとは思わない。むしろ武器として使っていける人が強い

ESLintのflat configについてようやく調べた

背景

ESLint v9からflat configがデフォルトとなり、将来のリリースで古いconfigの書き方は廃止される予定なのは把握していた。その後本格的に調べないままになっていたが、そろそろまずいかもなと思って概要だけでも調査したメモ。

先に簡単なまとめ

flat configとは何か

ESLintの新しい設定システム(config system)のこと。

flat config導入の背景

ESLint's new config system, Part 2: Introduction to flat config - ESLint - Pluggable JavaScript Linter

このあたりに書いてそうだったが、あまり詳しくは理解していない。

ESLintも最初にリリースしてから10年が経過し、複雑化したため、よりシンプルで直感的な設計を目指したぽい。

flat configの書き方

参考: Configuration Files

従来は .eslintrc.* という名前の設定ファイルでJSだけでなくYAMLJSONもサポートしていたが、flat configでは eslint.config.js (または ~.mjs, ~.cjs)というようにJSに統一された。
eslint.config.js については、 package.json"type: "module" と書かれていればESM形式、そうでなければCommonJS形式とみなされる。

flat config の中身は、configuration objectと呼ばれるオブジェクトを配列形式で並べたもの。

// eslint.config.mjs (ESM形式)
import customConfig from "eslint-config-custom";

export default [
  customConfig, // configuration object その1
  
  // configuration object その2
  {
    files: ["**/*.js", "**/*.cjs"],
    rules: {
      "semi": "error",
      "no-unused-vars": "error"
    }  
  },
  // configuration object その3    
  {
    files: ["**/*.js"],
    rules: {
      "no-undef": "error",
      "semi": "warn"
    }  
  }
];

各configuration objectはこれらのプロパティで構成される。

  • name
    • configuration objectの名前。Configuration Naming Conventions によれば “optional, but it is recommended to provide a name for each configuration object, especially when you are creating shared configurations.” とのこと
  • files
    • configuration object を適用したいファイルを、globパターンの配列で指定する。省略した場合、他のconfiguration objectによってマッチしたすべてのファイルが対象になる
  • ignores
    • configuration objectの適用対象外にしたいファイルを、globパターンの配列で指定する
  • languageOptions
    • ecmaVersion, sourceType, globals, parser, parserOptionsを設定する
  • linterOptions: 以下、どちらも元からあったプロパティ
    • noInlineConfig:インラインコメントでのルール適用を禁止する(あればエラーになる)
    • reportUnusedDisableDirectives:コメントでenable/disableしたものの、コードの修正によって意味をなさなくなっているものをどう扱うか(error | warn | off)
  • processor
    • 使ったことないので割愛
  • plugins
  • rules
    • ルール。従来通りの記述
  • settings
    • すべてのルールで共有できるkey-value形式の値

注意点として、あるファイルに対して複数のconfiguration objectがマッチした場合、それらはマージされ、配列の前から順番に適用されるような挙動となる。つまりconfiguration object間でプロパティがバッティングしていた場合は後勝ちとなる。

従来のconfigとの違い

参考:https://eslint.org/docs/latest/use/configure/migration-guide

上記記事の Key Differences between Configuration Formats に主な変更点が記載されている。が、それでも量が多い。
ここでは特に気になったものだけ書く。

また、日本語記事ではこちらがわかりやすかった。

ESLint を eslintrc から Flat Config に移行する、ハマりポイントを添えて。 #JavaScript - Qiita

プラグインのインポート方法

eslintrc では外部のプラグインは以下のように文字列で指定していた。

// .eslintrc.js(抜粋)
module.exports = {
  // ...other config
  plugins: ["jsdoc"],
  ...
}

flat configでは使用するプラグインはconfigファイル内で明示的にimportし、key-valueのペアで使用するプラグイン名とプラグインオブジェクトを指定する。

// eslint.config.js

import jsdoc from "eslint-plugin-jsdoc";

export default [
  {
    files: ["**/*.js"],
    plugins: {
      jsdoc: jsdoc,
    },
    rules: {
      "jsdoc/require-description": "error",
      "jsdoc/check-values": "error",
    },
  },
];

これにより、従来はプラグイン名を eslint-plugin- で始めないといけなかったが、その制約がなくなった。

.eslintignore は廃止

同様に eslintrc の ignorePatterns も廃止。configuration object の ignores を使う。

env プロパティは廃止

特定のランタイム向けのグローバル変数globals というnpmパッケージをインストールし、 globals プロパティに指定して使う

before

// before (.eslintrc.js)
module.exports = {
  env: {
    browser: true,
  },
  globals: {
    myCustomGlobal: "readonly",
  },
  parserOptions: {
    ecmaVersion: 2022,
    sourceType: "module"
  }
  // ...other config
}

after

// eslint.config.js
import globals from "globals";

export default [
  {
    languageOptions: {
      ecmaVersion: 2022,
      sourceType: "module",
      globals: {
        ...globals.browser,
        myCustomGlobal: "readonly"
      }
    }
    // ...other config
  }
];

従来のconfigからの移行方法

ESLint Configuration Migrator (@eslint/migrate-config) というCLIが提供されている。

https://eslint.org/docs/latest/use/configure/migration-guide#migrate-your-config-file

npx @eslint/migrate-config .eslintrc.json

実行すると eslint.config.js が生成される(未確認)。

注意点として、公式ドキュメントには

not guaranteed to work immediately without further modification

とあるのでこれだけではうまくいかないケースもあるらしい。
また、 .eslintrc.js に対してはうまく動かないらしい。

手作業での移行は、先ほども記載した
https://eslint.org/docs/latest/use/configure/migration-guide
を読んで差分を理解し、移行するしかない。

flat config未対応のconfig・pluginを使っている場合

参考:Configuration Migration Guide > Using eslintrc Configs in Flat Config

依存している shareable config がまだ flat config に対応していない場合、FlatCompat というユーティリティを使うことで eslintrc フォーマットから flat config フォーマットに変換できる。

FlatCompat@eslint/eslintrc というパッケージのインストールが必要。

このように、FlatCompat インスタンスを作成した後に適宜メソッドを呼び出して flatconfig 未対応の config 名を渡す。

import { FlatCompat } from "@eslint/eslintrc";
import path from "path";
import { fileURLToPath } from "url";

// mimic CommonJS variables -- not needed if using CommonJS
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const compat = new FlatCompat({
    baseDirectory: __dirname
});

export default [

    // mimic ESLintRC-style extends
    ...compat.extends("eslint-config-my-config"),
];

.extends() 以外にもいくつかメソッドがあるみたい。詳しくは

https://github.com/eslint/eslintrc

のREADME参照。

いつまでに移行が必要?

参考:Flat config rollout plans - ESLint - Pluggable JavaScript Linter

すでに、2024年4月にリリースされた ESLint v9.0.0 からはflat configがデフォルトになっており、従来の config は非推奨(deprecated)という扱い。

v9.0.0 以降で従来の config を使用する場合、ESLINT_USE_FLAT_CONFIG という環境変数false に設定する必要がある。

$ ESLINT_USE_FLAT_CONFIG=false npx eslint src

さらに、v10.0.0 では従来の config は完全に削除される。

v10.0.0 のリリースは参考先のブログ記事では2024年末か2025年初頭と書かれている。

flat config のTypeScript型定義

参考:https://eslint.org/docs/latest/use/configure/migration-guide#typescript-types-for-flat-config-files

DefinitelyTyped にある。

$ npm i -D @types/eslint

eslint.config.js

/** @type import("eslint").Linter.FlatConfig[] */
export default [
  ...
]

と書くと補完が効くようになる。

参考リンク

公式ドキュメント

ブログ記事

スクラムフェス大阪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とスーパーマリオブラザーズワンダー買ってて、子供と一緒にやったらめちゃくちゃ面白かったので、あーこういう時間も必要なんだよな、と思うなどした。

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