Classi開発者ブログ

教育プラットフォーム「Classi」を開発・運営するClassi株式会社の開発者ブログです。

Classiのエンジニアが 関西Ruby会議08 に参加しました

はじめに

2025年6月に入社しました、id:tommy1038 です!

2025年6月28日、京都・先斗町歌舞練場にて開催された「関西Ruby会議08」に参加してきました。

regional.rubykaigi.org

関西圏ではこれまでも「大阪Ruby会議」など地域のRubyイベントが継続的に開催されてきましたが、「関西Ruby会議」としての開催は実に8年ぶり。 久しぶりにこの“冠”が復活したこともあり、全国から多くのRubyistが集まりました。

会場となった先斗町歌舞練場は、歴史ある建物で、出囃子や「めくり」などの演出もあり、Rubyのイベントでありながら、どこか和の趣が感じられる特別な空間でした。

関西Ruby会議08の会場(先斗町歌舞練場)

会場内にはスポンサー企業のブースや書籍紹介スペースも設けられ、交流の場としても大いに賑わっていました。 Rubyという言語を通じて、これほど多様な表現や熱量が集まる場があるのだと、改めて実感しました。

気になったKeynoteやSessionをいくつかピックアップしてご紹介します。

Witchcraft for Memory by Masataka Kuwabara(@pocke)さん

Ruby/RBSコミッターでもある @pocke さんによるKeynoteです。
RBS/Steepまわりのメモリ削減に関する工夫が詰まっており、とても学びの多い発表でした。

前半は、Rubyの memory_profiler では把握しづらいピーク時のメモリ使用状況にアプローチするためのツール「Majo」の紹介。

github.com

Cレベルの TracePoint APIを活用して、

  • オブジェクト生成・解放のフック
  • GCを生き残ったオブジェクトのみを記録
  • 記録は Ruby オブジェクトを使わず、Cの構造体と配列で実施

といった低レイヤーなアプローチが印象的でした。
「GCが走っているときに、GCを走らせてはいけない」── そんな制約のなかで、工夫を凝らして適切に処理する発想と技術力には、心から感動しました。

後半では、SteepのLSPサーバーにおけるworkerプロセスのメモリ増加問題に対し、「Refork」という手法で解決を図った取り組みが紹介されました。

Steepでの refork 実装では、まず管理プロセスが全ワーカープロセスをforkし、一度型検査を行ってメモリを“暖気”。
その後、各ワーカープロセスがさらに新しいワーカーをforkし、古いプロセスを順次終了させていく流れになっていました。
この過程での課題や、実運用に耐える仕組みに仕上げていくまでの苦労と工夫が丁寧に語られ、非常に勉強になりました。

普段の業務では、Rubyのメモリ管理やGCについて意識する機会は少ないですが、こうした低レイヤーの知見に触れることで、Rubyの内部動作やパフォーマンス改善の可能性を強く感じることができました。

Masataka Kuwabara さん、素晴らしい発表をありがとうございました。

資料も公開されていますので、詳細を知りたい方はこちらもぜひご覧ください。

speakerdeck.com

「1ヶ月でWebサービスを作る会」で出会った rails new、そして今に至る rails new by kiryuanzu さん

社内でもおなじみ、id:kiryuanzu さんによるセッション。

自身が開発・ローンチしたポッドキャスト系Webサービスを題材に、開発の過程で直面した壁や、それをどう乗り越えたかをリアルに語ってくれました。

「どうすれば本当にリリースまでたどり着けるのか?」
この問いに向き合いながら、“やるぞ!!” と思えるエネルギーを参加者に届けてくれる力強い発表でした。

特に印象的だったのは、ローンチ達成のための3つの秘訣です。

まず1つ目は、「小さく作って出す」こと。
ポッドキャストのRSSフィード発行という最小限の目標に絞り、3週間という短期間で運用開始まで持ち込んだスピード感には、自分も大いに刺激を受けました。

次に、「様子を実況する」こと。
プロポーザル提出時点でサービスが半分もできていなかったという裏話には驚かされましたが、SNSで制作の過程を発信し、自らを奮い立たせるスタイルがとても印象的でした。

そして3つ目は、「自分が最初のユーザーであること」。
本当に “あったらいいな” と思えるサービスを作り、自分で使い続けることで、愛着と改善意欲を自然と保ち続けられるという気づきは、個人開発を続ける上での重要なヒントだと感じました。

この3つのシンプルで本質的な行動が、「つくるだけ」で終わらず、ちゃんと世の中に届ける力になっている。 個人開発で立ち止まりがちな人こそ、背中を押してもらえる発表だったと思います。

kiryuanzu さん、素晴らしいお話をありがとうございました。

資料も公開されていますので、詳細を知りたい方はこちらもぜひご覧ください。

speakerdeck.com

ちなみに、登壇に至るまでの経緯や準備の様子については、こちらのブログで紹介されています。

tech.classi.jp

ふだんのWEB技術スタックだけでアート作品を作ってみる by Akira Yagi さん

八木章(@akira888)さんによるセッション「ふつうの技術スタックでアート作品を作ってみる」では、Rails・Hotwire・HTML・CSSといったおなじみの技術を用いて制作された、時計モチーフのアート作品が紹介されました。

私自身も、過去に Processing や p5.js を使ってインタラクティブな作品を作った経験があり、共感しながら聴き入ってしまいました。

今回の挑戦が面白いのは、特別なライブラリやフレームワークを使わず、いつものWebアプリ開発の延長線上で表現に挑んでいる点です。

  • HTMLとCSSで時計のビジュアルを構成
  • 針の動きをCSSアニメーションで表現
  • 時刻やパターンのロジックをRailsで生成
  • 時間経過による切り替えをStimulusで制御

という構成で、MVCの概念をそのままアートに応用していました。 時計を構成するモデル設計やマッピングロジックの美しさも印象的で、技術と表現が見事に調和していました。

中でも心に残ったのは、「Railsを使っても、ユーザーアクションのない作品を作っていいんです」というメッセージ。 Rubyとアート、その両方を大切にしている姿勢が伝わってきて、温かい気持ちになるセッションでした。

Akira Yagi さん、素敵な発表をありがとうございました。

資料も公開されていますので、詳細を知りたい方はこちらもぜひご覧ください。

speakerdeck.com

Rubyで世界を作ってみる話 by Akira Matsuda さん

Matsuda さんによるセッション「Rubyで世界を作ってみる話」は、Rubyのオブジェクト指向表現を用いて “世界” をモデリングし直すという、遊び心と技術的探究心に満ちたチャレンジでした。

class Atom から始まり、電子や分子といった構成要素を定義していく中で、Rubyのクラスやモジュールを通じて現実世界を抽象化していく──
まさにオブジェクト指向の原点に立ち返るような体験でした。

中でも印象的だったのが、InChI記法で記述された複雑な化学構造式をRubyでパースする実装です。 構文と意味の“橋渡し”としてのプログラムの美しさがあり、DSL的な発想としても非常に刺激的でした。

さらに、Gitの履歴を使って世界の始まり(ビッグバン)まで遡ろうと試みるも、1970年が技術的な限界だったというオチには、会場から笑いが起こり、セッション全体に心地よいユーモアが漂っていました。

会場が京都だったこともあり、京大の先生方の理論をRubyに取り込もうとする試みも紹介され、参加者の関心を集めていました。

業務アプリの枠を超え、Rubyという言語の表現力を最大限に活かして「世界を再構築する」という視点は、 コードを書く楽しさや、創造する喜びをあらためて思い出させてくれるセッションでした。

Akira Matsuda さん、素晴らしい発表をありがとうございました。

それぞれの「関西Ruby会議08」

一緒に参加したClassiメンバーも、それぞれ自分の言葉で感想を残しています。

雰囲気や熱量の伝わる素敵な記事ばかりなので、よければこちらも覗いてみてください!

kiryuanzuさんの登壇資料より

歌舞練場という普通の技術カンファレンスではやらないような特別感のある会場と演出がとても良く、自分でも何か手を動かしたくなる刺激的なトークばかりで最高に楽しい地域Ruby会議でした!

ブログの詳細はこちら 👉 関西Ruby会議08に参加してきた - kozy4324の日記

私自身、人生初の技術カンファレンスでした。 運営の方はとても熱量をもってやられており、登壇された方々の内容もとてもおもしろく、自分で手を動かしたくてウズウズしてしまいました! また次回も参加したいと思いました!!

ブログの詳細はこちら 👉 関西RubyKaigi08に行ってきた - nekobitsdreams’s diary

今回のRuby会議に参加し、「個人開発をしたい」と素直に思いました。バグとの戦いも含めてそれも「ものづくりの楽しさ」であることを登壇者の方のお話から気付かされました。 これから、楽しみながらいろんなことに挑戦していきたいです。

ブログの詳細はこちら 👉 関西Ruby会議08に参加しました!|Akinko

初めての大型技術系カンファレンスで刺激がたくさんありました!特に個人開発の登壇をしていらっしゃる方が多くて参考になる点が多く、自分も趣味と重ねて個人開発を進めていきたいです!目指せ登壇!

ブログの詳細はこちら 👉 関西RubyKaigi行ってきた件! - butyooo’s blog

初めての登壇でとても緊張しましたが、無事終えることができ本当に良かったです!発表準備から当日までの過程を暖かく見守ってくださったClassiのメンバーの方々に改めて感謝の気持ちを伝えたいです。

ブログの詳細はこちら 👉 関西Ruby会議08に登壇してきた、それらにまつわる全ての感情 - 桐生あんずです

終わりに

関西Ruby会議08。ここで紹介しきれなかったセッションも含めて、本当に刺激の多い一日でした。
低レイヤーの深掘りからアートの表現、個人開発のリアルな奮闘記まで、「Rubyでこんなこともできるんだ」という気づきがいくつもあり、あらためてこの言語の懐の深さを実感しました。

ふだんの業務ではなかなか出会えない視点や発想に触れ、自分も何か作ってみたいな、という気持ちが自然と湧いてきました。 歴史ある先斗町歌舞練場という特別な場所で、Rubyへの愛や技術への熱量が会場のあちこちから伝わってくる、うれしくて、ちょっと誇らしい時間でした。

運営のみなさま、登壇者のみなさま、本当にありがとうございました!

最後に、会場で撮ったClassiメンバーとの写真や、Matzとの記念ショットをいくつか載せておきます📸

ClassiメンバーとMatzとの記念写真など

ライブラリメンテナンスのための自作ESLintルール作成

こんにちは、プラットフォーム部の id:lacolacoです。

Classi社内では、複数のWebアプリケーションで共通のUIコンポーネントを社内ライブラリ化しています。ライブラリを長くメンテナンスしていると、過去に提供していたAPIを廃止して、新しいAPIに置き換えたいことが多々あります。いきなり古いAPIを消して新しいAPIを提供する破壊的変更のアプローチは、社内ライブラリであれば利用者とコミュニケーションしやすいため妥協してしまいそうになります。しかし、破壊的変更への追従が利用者側で負担となって棚上げされた結果、後になって急いで適用して欲しいセキュリティパッチのバージョンアップがなかなか適用できない、なんてことになるのは避けたいところです。

そんな流れで、今回はライブラリメンテナンスの上でAPIの非推奨化から廃止までのプロセスを支援するためのESLintルールを自作した話をします。AI要素もちょっとあります。

社内ライブラリと破壊的変更

Classiで採用しているAngularフレームワークを例にあげると、Angularの非推奨化ポリシーでは廃止予定のAPIはまず非推奨APIとしてマークされ、最低でも2メジャーバージョン(1年間)の猶予期間が与えられます。その猶予期間のあとのメジャーバージョンにて、非推奨APIは破壊的変更として廃止されます。社内ライブラリは広く使われるOSSではないのでここまでの厳格なポリシーは必要ありませんが、少なくとも非推奨化の段階を踏み、既存の利用箇所を新しいAPIに移行したうえで安全に廃止できるようなプロセスを取りたいと考えています。

そういうモチベーションで、社内ライブラリのTypeScriptコードにはいくつもJSDocの @deprecated アノテーションが付けられたAPIがありましたが、いざ廃止しようとすると困ることがありました。まず、現状、どのAPIに非推奨マークが付けられているのかの一覧もなく、毎回コード検索をするしかありません。また、一度にすべての非推奨APIを廃止するわけではなく、残すものもあるため、 @deprecated アノテーションの有無だけでは一律に処理ができません。

やりたいことは以下の2点です:

  • ライブラリ中で非推奨化されているAPIが一覧できる
  • 削除されるべき非推奨APIと、まだ残しておきたい非推奨APIが区別できるようになる

これを実現するにあたって考えたのが、自作ESLintルールでした。

APIの非推奨アノテーションを検出するESLintルール

TypeScript ESLintにはno-deprecatedルールがありますが、これは非推奨マークされたAPIを「参照している」コードを検出するものです。今回欲しいのは、ライブラリ開発者側の立場で、非推奨マークされたAPIの「宣言」を検出するものです。これはある程度探した限りでは見つかりませんでしたので、自作することにしました。

シンプルなルール適用例として、次のような設定をすればライブラリ中のすべての @deprecated アノテーションがついた宣言をエラーとして検出します。

// eslint.config.js  
import customRules from './tools/eslint-rules';

export default [  
  {  
    plugins: {  
      custom: customRules,  
    },  
    rules: {  
      'custom/deprecated': 'error',   
    },  
  },  
];  

これだけだと残しておきたい非推奨APIを検出してしまうので、つぎのように allow オプションによって明示的に許可された名前のシンボルは対象外とできるようにしました。

// eslint.config.js  
export default [  
  {  
    rules: {  
      'custom/deprecated': [  
        'error',  
        {  
          allow: ['allowedFunction', 'AllowedClass'], // 許可する名前のリスト  
        },  
      ],  
    },  
  },  
];  

クラスの一部のメソッドだけ非推奨化することもあるため、 ClassName.memberName というパターンもサポートしています。

{  
  allow: [  
    'MyClass.deprecatedMethod',   
    'MyClass.deprecatedProp',  
  ];  
}  

このようなルールを作成してESLintを実行すると、既存の非推奨APIがエラーとして可視化されます。最初は仕方ないのでひとつひとつ手で allow 配列に入れていくと、 allow 配列はまさに「ライブラリ中で非推奨化されているAPIが一覧できる」場所になりました。

この状態ができてしまえばあとは簡単です。廃止したいAPIだけを allow 配列から取り除き、ESLintを実行すると対応すべきコードがわかります。直近のアップデートではそこそこの数の非推奨APIを削除したのですが、 allow 配列をいじったあとのコード変更作業はAI(今回はGitHub Copilot ChatのAgentモード)だけで完結しました。

プロンプト:

TDDを開始

- 目的: 非推奨マークされたAPIのうち、eslint.config.ts で許可されていないものだけを廃止する  
- テストコマンド: pnpm lint  
- 完了条件: ESLintエラーから custom/deprecated ルールのエラーがなくなる  
- 禁止事項  
  - ESLintエラーと直接関係のないコードの変更

完了条件が明確で、ESLintのエラー出力からどのファイルのどの宣言が処理対象か迷うこともないので、残っていた非推奨APIへの参照を置き換えつつAPIの削除までスムーズに進行しました。「TDDを開始」と言ってテストの仕方と完了条件を教えておけばだいたいうまくいく。

ESLintルールの実装

今回のESLintルールは TypeScript ESLintの力を借りて、TypeScriptの型情報を使っています。2025年5月に開催されたTSKaigi 2025でも自作ESLintルールの話は多く、それに触発された部分もけっこうあります。

基本的にはそれぞれの宣言についてJSDocが付いているか、付いていれば @deprecated アノテーションが含まれているか、ということを見ていくだけなのですが、一部の構文ではちょっとした工夫が必要だったので書いておきます。とはいえ、実際には自分はテストコードだけを書いていて、ASTを走査する実装コードはほとんどGitHub Copilot Chatに書かせています。

変数宣言のJSDoc

TypeScriptの変数宣言に付いたJSDocは、それぞれの変数の宣言(VariableDeclarator)ではなく const といったレベル(VariableDeclaration)に付きます。これは const a = 1, b = 2 のような構文がありえるためですね。この場合、JSDocが付いているノードと、報告すべきシンボルの名前を取り出すノードがずれるので注意が必要でした。

   /**
     * 変数宣言の@deprecatedチェック
     * JSDocコメントは親のVariableDeclarationに付くため、そちらをチェックする
     */
    const checkVariableDeclaration = (node: TSESTree.VariableDeclarator): void => {
      const name = getIdentifierName(node.id);
      if (!name || isAllowed(name)) {
        return;
      }

      // JSDocコメントは親のVariableDeclarationノードに付いているのでそちらをチェック
      const parentNode = node.parent;
      if (parentNode && parentNode.type === TSESTree.AST_NODE_TYPES.VariableDeclaration) {
        if (hasDeprecatedTag(parentNode)) {
          reportDeprecatedError(node, name);
        }
      }
    };

エクスポート文のJSDoc

エクスポート宣言では、宣言自体とエクスポート文の両方のコメントをチェックします。以下の2つの例は結果的には同じ意味ですが、fooFunction が非推奨APIであるということを検出するには ExportSpecifierFunctionDeclaration の両方を見る必要があります。

/**
 * @deprecated エクスポート文のコメント
 */
export function fooFunction() {}

// または

/**
 * @deprecated 関数自体のコメント
 */
function fooFunction() {}
export { fooFunction };

加えて、APIの命名だけが変更されたケースでは、次のようにエクスポート文でのエイリアスに対する非推奨化もあります。次のようなケースでは ExportSpecifier のノードのJSDocをチェックしつつ、報告するシンボルは ExportSpecifier.name ではなく ExportSpecifier.exported というズレを考慮する必要があります。

export {
   NewExport,
   /**
     * @deprecated Use NewExport instead
     */
   NewExport as DeprecatedExport,
};

まとめ

破壊的変更を安全にリリースしていくための非推奨化プロセスにおいて、当初のねらい通り「ライブラリ中で非推奨化されているAPIが一覧できる」ことと「削除されるべき非推奨APIと、まだ残しておきたい非推奨APIが区別できるようになる」が実現できました。これまではメンテナの脳内にしかなかったライブラリ全体の非推奨化の状況がコードベースに可視化されたことで、忘れても大丈夫になりマインドシェアの解放にも繋がっています。

ESLintに限らず、ASTと仲良くなればソースコードに対する問題解決の幅が大きく広がるので、まだ自作Lintルール未経験の方もぜひ挑戦してみてください。最後に参考リンクを紹介して終わります。

関西Ruby会議08に「『1ヶ月でWebサービスを作る会』で出会った rails new、 そして今に至る rails new」というタイトルで登壇します

こんにちは、Classi でソフトウェアエンジニアをやっている id:kiryuanzu です。

2025年6月28日(土) に京都府京都市の先斗町歌舞練場にて開催される関西Ruby会議08で「『1ヶ月でWebサービスを作る会』で出会った rails new、そして今に至る rails new」というタイトルで登壇させていただくことになりました。

regional.rubykaigi.org

今回はこの発表のプロポーザルを提出した時の背景や、登壇の意気込みについて事前にお伝えしたいと思います。

プロポーザルを提出した際の背景

実は、LT形式ではない少し長めの発表(今回は20分)のプロポーザルを提出したのはこの関西Ruby会議08が初めてでした。
プロポーザルを出すことを本格的に意識した際、まずは関西Ruby会議08の運営の方が書かれた「関西Ruby会議の再開に寄せて」という記事を熟読し、運営の方がどのようなトークを求めているかを自分なりに考えてみました。

note.com

かなり抽象的なテーマですが、Rubyのコードが1行でも発表に含まれているのであれば問題ありません。むしろその人にしか話せない作ったものの「好き」や「苦労」や「思考」などのストーリーを聞きたいと思っています。

「その人にしか話せない作ったものの『好き』や『苦労』」というキーワードを目にした時、自分にとってのそれは学生時代から趣味としていた個人でのWebサービス開発がまず浮かびました。

その上で「聞く人も何か作ろうと思えるような話」も意識しつつ、趣味のPodcastの音声データを自前で配信する個人Webサービスを開発した際の体験談をテーマにプロポーザルを提出するに至りました。
発表の概要は以下のリンクを参照ください。 https://regional.rubykaigi.org/kansai08/presentations/kiryuanzu

発表の意気込み

発表内容は個人開発の体験談がメインとなります。その上で「どうしたら自分の個人サービスをローンチまでやりきれるのか」についても深掘りをする予定です。
この発表を通して、サービスを作っていてローンチを目指している方や、直近の自分のように久々に個人開発したいけれど作る勢いがまだつかない方が「自分もやってみよう」と思えるようなお話ができたらと思います。

先日アップされたタイムテーブル解説記事でも自分が伝えたい発表のイメージを共有してくださっています。こちらも参考にしていただけると幸いです。

関西Ruby会議08 チーフオーガナイザーの ydah さんにタイムテーブルを解説してもらいました - ANDPAD Tech Blog

tech.andpad.co.jp

ydah: そうなんですよね。 まさに「どうしたら個人サービスをローンチまでやりきれるか」についての話を自らの経験をもとに話していただけると思っていて、それは本当に貴重な体験談ですし、個人開発で悩んでる人にとっても、すごく勇気づけられる内容になりそうだなと思っています。 「rails newはするけどローンチまでいかない」って、とても共感する人多いと思うんですよね。これから個人開発を始めたい方にとって非常に参考になるトークだと思います。

筆者以外のトークもたいへん丁寧に解説されています。現地に参加される方は必見の記事です!

おわりに

当日は大変ありがたいことに Classi のメンバーが現地で応援しにきてくださるとのことです!

id:kiryuanzu含む一部のメンバーは Day0 の晩餐会当日の Official Party にも参加予定です。現地でぜひたくさん交流しましょう!

それでは、当日みなさんにお会いできることを楽しみにしております!!

Classiエンジニアの「OSSやっていきの集い」 〜4ヶ月間の取り組みと、初めてのOSSコントリビューション〜

こんにちは。Classiでソフトウェアエンジニアをしている中村( id:kozy4324 )です。

今回は、社内で継続している技術活動「OSSやっていきの集い」についてご紹介します。活動開始から4ヶ月の間に取り組んできたこと、そして実際にOSSプロジェクトへプルリクエストを送ってマージされた経験についてまとめました。

OSSやっていきの集いとは

この活動は、SmartHRさんの取り組み「OSSやっていきの集い」から着想を得て、名称もそのままお借りして始めました。

OSSに関心はあるものの、実際に関わるのはハードルが高く感じられることがあります。私自身もそうでした。 一人では難しく感じることでも、仲間と取り組めば少しずつ前に進めるのではないか。そんな思いからスタートした活動です。

社内でこの活動を始める際には参加するメリットを明確にすることも意識しました。 活動を通じて期待できるアウトカムは以下のようなものです。

組織にとってのメリット

  • OSSに貢献するエンジニアが増え、企業としての発信力も高まる
  • 技術広報の題材として活用できる
  • 開発スキルの向上が期待できる
  • チームを越えた交流が生まれる

個人にとってのメリット

  • OSSに関わる心理的ハードルを下げられる
  • 実践を通じた学びが得られる
  • 社外発信や登壇の機会にもつながる

また、東京Ruby会議12前夜祭での発表 「Rubyと暮らし、OSSに貢献し、登壇する ── 半年間続けた『OSSやっていきの集い』の成果と学び」 にも背中を押されました。実践例を知ることで自分たちの活動がどう発展しうるか、イメージを持てるようになりました。

立ち上げから4ヶ月で取り組んだこと

活動の最初のテーマとして、Rubyのコード整形・静的解析ツールであるRuboCopを選びました。 まずは「RuboCopを知る・使う」ことからスタートし、段階的に理解を深めていきました。

RuboCopの活用に向けた取り組み

  • 基礎固め
    2月4週目〜3月1週目(約2週間)
    RuboCopのGitHubリポジトリや公式ドキュメントを読み、基本的な使い方を習得しました。

  • Copの実装を読む
    3月2週目〜5月2週目(約2ヶ月)
    Style/RedundantConditionなど具体的なCopのコードを読み解きながら、抽象構文木(AST)の概念を学習しました。

  • カスタムCopの作成
    5月3週目〜6月3週目現在(約1ヶ月経過)
    社内プロジェクトで使えそうなカスタムCopの作成にチャレンジしています。例えば社内ライブラリに対して不適切な使い方を検知するCopなど、アイデアレベルから持ち寄り、それをどう実装できるかを参加者で会話しながら取り組んでいます。

  • リリース情報の追跡と適用
    2月4週目〜6月3週目現在(約4ヶ月経過)
    RuboCopのリリースノートを定期的に確認し、社内プロジェクトでのバージョンアップにも取り組んでいます。 エラーが発生した際は「これは貢献のチャンスかもしれない」と前向きに捉える意識も芽生えはじめました。

RuboCop 1.76.0で気づいたエラーメッセージの違和感

ある日、RuboCopを1.76.0にアップデートしたところ次のような指摘を受けるようになりました。

C: Style/ItBlockParameter: Avoid using numbered parameters for multi-line blocks.
            some_ids = some_ids.map do ...
                       ^^^^^^^^^^^^^^^

実際のコードは以下のようになっていました。

some_ids = some_ids.map do
  do_something(with: it)
end

調査したところ、Style/ItBlockParameterEnforcedStyleのデフォルト値がv1.76.0で変更されたことが原因でした。

https://github.com/rubocop/rubocop/releases/tag/v1.76.0

  • #14066: Add EnforcedStyle: allow_single_line as the default to Style/ItBlockParameter. (@koic)

v1.75.xまではonly_numbered_parametersがデフォルトでしたが、v1.76.0からはallow_single_lineが新たに追加され、こちらがデフォルトとなっています。その結果、設定を明示していないプロジェクトでは複数行ブロック内でのitの使用が許容されなくなりました。

このようにエラーの理由は理解できたのですが、表示されるメッセージには少し違和感がありました。

Avoid using numbered parameters for multi-line blocks.

今回のコードでは「numbered parameter(_1, _2など)」は使っておらず、itを使っているにもかかわらずその利用を避けるようにというメッセージに読めてしまいます。

コードとエラーメッセージを見比べても、なぜ警告されているのかが直感的に理解しづらい状況でした。

RuboCopへの修正プルリクエストとマージ

このメッセージの違和感を解消するためエラー文言の修正に特化したプルリクエストを作成しました。

そしてありがたいことに当日中にマージしていただくことができました。これは「OSSやっていきの集い」を始めた当初から目指していた「実際にOSSに貢献できる経験を得る」という目標の達成でもあります。

日々の開発のなかでOSSを継続的に利用していたからこそ、違和感に気づき、改善のきっかけを掴むことができました。 ゼロからのスタートでも数ヶ月で貢献のチャンスを得られたことは非常に嬉しい成果です。

これからの展望

「OSSやっていきの集い」はまだ始まったばかりの取り組みです。今後もRuboCopの内部実装を読み解きながら、カスタムCopの開発や小さな改善の提案を通じて、OSSとの関わりを深めていきたいと考えています。

この活動を通じて、ClassiのエンジニアがOSSと自然に関わり、学びを得て、最終的にはOSSコミュニティに貢献できるような文化を育てていければと思います。

Classi 2025年新卒エンジニア研修「そーだい塾」を開催しました

 こんにちは。Classiのみんなの頼れるお兄さん id:Soudai です。 Classiでは例年、新卒エンジニア向けの研修「そーだい塾」を実施しており、今年も2時間の研修を3回にわたって開催しました。

 今日はこの研修をご紹介しながら、当日の雰囲気やスライドには書いていない部分や大切な考え方をご紹介します。

  1. 第1回:リリースの極意
  2. 第2回:日々の仕事の中で成長する
  3. 第3回:具体と抽象と現場

第1回:リリースの極意

 第1回では、ソフトウェアエンジニアにとって最も重要な「リリース」について取り上げました。

登壇資料

speakerdeck.com

speakerdeck.com

伝えたかった狙い

 まずはエンジニアたるもの、リリースから始まるということでリリースをテーマにしました。 このセッションは例年やっています。

tech.classi.jp

 当日は新卒だけでなく、 id:lacolaco をはじめとしたClassiのエンジニアも参加して、リリースに対する考え方やリリースの重要性の議論も行いました。 2~3年も経てば、データベースの変更が必要な機能のリリースも必要になりますし、数ヶ月もかかるような大きなコードベースのプロジェクト単位のリリースも行うようになります。そういう時にこの話を思い出してほしいのです。そうすれば事前に事故を防ぐことができます。そうやって経験していく中で「これは、そーだいさんが言ってたやつだ」となってほしいなと思っています。

第2回:日々の仕事の中で成長する

 第2回では、エンジニアとしての成長と仕事のコツを紹介しました。 毎日8時間働いていくのですから、その中で成長し、仕事で成果を出し、評価を得ることが重要です。 そのために必要なスキルや考え方を伝えました。

登壇資料

speakerdeck.com

speakerdeck.com

伝えたかった狙い

 この回の資料は、まず知っていることがとても重要な内容を中心に構成しました。 早く知れば知るほど複利が効く内容で、出来なくてもまずは知っておいて出来るようになるまで繰り返すことが大切です。

 意識していればできるようになるスキルですし、逆に言えばこれができない場合はどこかで社会人として躓くことになるでしょう。 だからこそ早めに知識として知っておき、身につけてほしいということで紹介しました。

第3回:具体と抽象と現場

 最終回では、エンジニアにとって重要な思考法である「抽象化と具体化」について深く掘り下げ、それを具体的にどのように実践するかを紹介しました。

登壇資料

speakerdeck.com

speakerdeck.com

伝えたかった狙い

 この話は去年はしておらず、完全な新作です。 抽象化と具体化は、ソフトウェアエンジニアにとって非常に重要なスキルであり、これを身につけることでより良いソフトウェアを作ることができます。 無意識に行っていることも多いですが、意識的に行うことでより効果的に活用でき、再現性が上がります。

 抽象化と具体化の往復を仕事で行っていくうえで、現在の自分の抽象度がどの位置なのか把握することから始めましょう。ということを伝えました。

 そして最後に実際に仕事をするうえで、抽象化と具体化をどのように活用していくかを紹介しました。 顧客が求めているものを理解し、言われたことを作るのではなく、必要なものを作るためにも抽象化と具体化の往復が重要です。

終わりに

 Classiでは2021年から4年間にわたって新卒エンジニア向けの研修「そーだい塾」を実施しています。 もちろん新卒のメンバーがこの研修を受けることによって、すぐに仕事ができるようになるわけではありません。 ですが、2年後、3年後に振り返ったときに「そーだい塾で学んだことが役に立った」と思ってもらえるような内容を提供しているつもりです。

 そして実際に今の2年目、3年目のメンバーからは「改めて今年の新卒研修を眺めていると、そーだい塾で学んだことの解像度が上がっている」と言ってもらえています。 こういう若者の成長を感じられることも、そーだい塾をやっていてよかったなと思う瞬間ですね。

 今年の新卒のメンバーが実際の業務を通じて成長し、数年後に「そーだいさんの言ってたこと、今ならわかる!」と言ってもらえる日が来ることを楽しみにしています。


参考記事

NPS70超。社内AI議事録ツール「Turing」がClassiの"当たり前"になるまで

こんにちは、エンジニアの鳥山です。

Classiでは、2024年の12月ごろから当時最新であったGemini 1.5 Proを用いた議事録生成ツール「Turing」を開発、リリースし、社内のメンバーに使ってもらっています。

tech.classi.jp

本記事では、

  • リリースからおよそ半年経った今、Turingはどの程度普及したのか
  • 利便性や運用性の向上のためにどんな継続的改善をしたのか

の大きく2点に焦点を当てて紹介し、最後にTuringの成功要因についても考察します。

モデルのアップデートや新技術の発表が毎週のように起きる昨今、個人的にはAIをプロダクトに取り入れることのみならず、社内ツールとして使うことにも大きな可能性を感じています。

本記事は単体でもお読み頂けますが、Turingのアーキテクチャなどより詳細な部分にご興味をお持ちの方は、ぜひ前述のブログ記事も併せてお楽しみください。

  • Turingはどの程度普及したのか
  • 利便性や運用性の向上のための工夫
    • Slack任意チャンネルへの投稿
    • インスタンス起動時刻の最適化
  • 成功の要因、そして今後の展望
続きを読む

ライブラリの継続的アップグレードを支援する活動にQAメンバーとして参加した1年のふりかえり

こんにちは。プロダクト本部プラットフォーム部QAチームの牛木です。

弊社にはライブラリの継続的アップグレードを支援する活動があります。この活動にQAメンバーとして1年間参加しました。活動の内容や、活動を通じて感じたことをお伝えします。

ライブラリの継続的アップグレードを支援する活動とは

この活動は、EOL*1を迎えたライブラリやフレームワークを使わないように、” 継続的 ” にバージョンを ” アップグレードしよう ” という取り組みです。サポート状況の最新情報や、現時点での対応状況などを収集し見える化することにより、対応が遅れているチームに対しリマインドやバージョンアップのサポートなどを行う活動になります。

なぜこのような活動を行っているのでしょうか?

EOLを迎えたライブラリやフレームワークは、セキュリティパッチが提供されなくなるため、脆弱性が発見されても修正されることはありません。もし脆弱性が放置された場合、自社で対応する必要が生じ、対応が遅れるとプロダクト全体がセキュリティインシデントにつながるリスクが高まります。

Webサービスを提供する弊社にとって、セキュリティリスクへの対策は常に重要な課題であり、この活動はその一環として行われています。

QAメンバーとしてなぜ活動に参加することになったのか

QAチームはプロダクト品質の担保を重要な責務と捉えています。プロダクト品質は、機能要件のみならず、セキュリティ品質を含む非機能要件も含まれます。プロダクトの安全性を確保するセキュリティ品質は、プロダクト品質を語る上で不可欠です。QAチームとしても積極的に関与し、貢献したいと考えていました。

また、日々の開発におけるライブラリのアップグレードはプログラム変更の一環であり、本来QAプロセスを経てリリースされるべきです。多くのOSSに支えられている弊社のプロダクトにとって、常に最新の状態を維持するために、継続的なライブラリのアップグレードは避けられません。

QAチームは、このライブラリのアップグレードという一連のプロセスを、開発からリリース、そしてその後の安定稼働まで一貫して見据え、最適化していくことを重要な役割と捉え、上流工程から品質保証に積極的に関与する「シフトレフト」を実践しています。この活動にQAメンバーとして参加することで、要件定義や設計段階からセキュリティ品質の観点を取り入れることが期待できます。それは、セキュリティリスクを低減し、プロダクト全体の品質向上に貢献できる良い機会になると考えました。

1年間何をしたか

週1回の定例MTGを実施し、以下の内容を実施しました。 参加メンバーは、開発エンジニアと私です。

① 使っているライブラリやフレームワークのリリース情報をチェック

新しいバージョンがリリースされた際、リリース内容からSecurity Fixが含まれていないか確認します。新しいバージョンがリリースされたかどうかの確認は、endoflife.dateをよく利用しています。Security Fixが含まれていないかの確認は、CVE*2に関連する改修情報を重点的に確認します。

② Dependabot アラート*3をチェック

新規にCritical・High・Mediumのアラートが発生していないか確認します。 Dependabotアラートは、GitHub のSecurityから閲覧できます。

(Criticalアラートは即潰すをいうルールが定着し、現在ではCriticalアラートがありません!)

③ 自社の開発に影響を与える可能性があるかを判断(トリアージ)

上記①、②で確認されたSecurity FixやDependabotアラートが、自社の開発に影響を与える可能性があるか判断を行います。この判断は私では困難であり、開発エンジニアが判断します。緊急度が高いと判断された場合は、速やかに該当開発チームに連絡します。緊急度がそれほど高くないと判断された場合は、週次で開催される各チームのエンジニアがテックイシューを共有しあう定例のMTGで情報共有するに留めています。

①②どちらも毎週何かしら検知されるため、原則として全てのSecurity FixとDependabotアラートを週次の定例MTGで共有しています。なぜなら「影響しない」「対応不要」という判断はリスクを伴うからです。本当に影響がないのか、対応しなくて良いのかという根拠は、実際にはソースコードの調査が必要ですし、現時点では影響がなくても、将来的なコード修正によって影響が出る可能性もあります。したがって、この活動を通して上がってきたリスクを共有し、アップグレードの推奨は行いますが、最終的な影響確認と対応判断は開発チームに委ねています。つまり、ここでのトリアージは、①②の内容が実際に影響するかどうかを判断するよりも、対応を促進させるための追加情報を提供する場なのです。

④ 月末にEOLのバージョンを使っていないかチェック

リポジトリとバージョンのマトリックス表を使って可視化をしています。EOLを迎えているバージョンを使用しているリポジトリや、間もなくEOLを迎えるバージョンを使用しているリポジトリを塗りつぶして、月末の定例MTGで共有し、関係者へ啓蒙を行います。

①②④のチェックは私が担当しました。 ③の判断や、Security FixやDependabotアラートの読み解きは、開発エンジニアの知見やGeminiのDeep Research*4を活用して実施しています。

この4つの取り組みの中で最も優先度が高いのは「④月末にEOLのバージョンを使っていないかチェック」です。なぜならEOLを迎えたバージョンはSecurity Fixが行われないため、仮に脆弱性が混入していても攻撃されるまで被害に気づけないからです。また、攻撃された場合、すぐさまアップグレードや自社での脆弱性修正は困難です。

その上で、日々のSecurity FixやDependabotアラートへの対応(①、②)を定期的に促すことで、④のようなリスクの高い状況に陥るのを事前に防ぐことができます。これらの日々の対応がスムーズに進む開発チームは、ライブラリアップデートのサイクルが定着し、結果としてEOLを迎えたライブラリの使用を避ける仕組みが自然と構築されます。

この活動の重要な視点

この活動は、全てのライブラリやフレームワークを常に最新バージョンにすることや、Dependabotアラートを全て解消することが目的ではありません。

この活動の重要な視点は、「セキュリティリスク」と「事業リスク」を比較し、相対的な重要性を評価した上で、最適なコストバランスの下でセキュリティリスクを低減させることです。

先に述べた通り、EOLを迎えたライブラリやフレームワークは、セキュリティパッチが提供されなくなるため、もし脆弱性が放置された場合、自社で対応する必要があります。セキュリティリスクが顕在化した場合、開発を全面的に停止して脆弱性対応に追われることになるかもしれません。重要なリリースが控えている時期であれば、顧客に影響が出ますし、最悪の場合サービスの一時停止という判断を迫られる可能性があります。これは、「現時点では発生していないものの、発生すれば事業継続に重大な悪影響を及ぼす事象」です。

このような事態を未然に防ぐため、本活動は管理ではなく、あくまで情報提供と啓蒙活動に重点を置いています。

しかし、可能な限り迅速な対応を推奨しているのも事実です。Security Fixの多くはパッチバージョンとしてリリースされるため、影響範囲が比較的小さいと判断できます。影響範囲の小さい修正をこまめに適用することで、影響範囲を詳細に調査する手間を省くことができます。修正を長期間にわたって累積させると、バージョン間の差分が大きくなり、いざ適用する際に予期せぬ不具合が発生し、プロダクトを壊してしまうリスクが高まります。

QAメンバーとして参加して気づいたQA活動との接点

この活動を通じて、QAチームのテスト施策がセキュリティ品質の防止策としても有効的であることを見出すことができました。

QAチームが整備しているE2E自動テストは、ライブラリやフレームワークのアップグレード対応における迅速な対応を促進する上で重要な役割を果たしています。パッチバージョンの適用に伴う主なリスクは、意図しない変更によるプロダクトの予期せぬ動作です。QAチームでは、基本的な機能フローを網羅した自動テストを準備しており、バージョンアップに伴うリリースの際、この自動テストによるチェックのみで品質を担保できる体制を整えています。

詳しくは以前に書かれた記事をご覧ください。 tech.classi.jp

また、標準観点表やテストテンプレートは、XSSやSQLインジェクションといった脆弱性を検知するのに最適なテストパターンとなっています。 認可に関するテストでは、権限マトリクスを活用したテストテンプレートが定着しており、自動テストにも権限パターンやURL直接入力といった観点が、特定機能だけではなく全機能に対して標準整備され、定期的に自動実行されています。

QAチームが日頃行っている品質保証活動は、機能要件の確認にとどまらず、非機能要件であるセキュリティ品質の確保にも貢献していることを強く実感できました。

QAメンバーとして参加して直面した課題

しかしながら、現状の活動からさらに一歩踏み出し、活動を拡張していくことには、正直なところ難しさを感じています。

第一に、ライブラリやフレームワークに関する深い知識に加え、Webアプリケーションの脆弱性に関する専門的な知識を習得した上で、それが自社プロダクトにどのような影響を与えるかを「判断」するには、現状の活動だけでは不十分でした。この1年は知識や仕組みの理解に留まっていましたが、今後は攻撃の再現手順を理解した上で、実際のコードの状態を確認し、攻撃が成り立つかを確認することが必要だと感じます。実践を行うことで「判断」に繋げることができると考えています。

第二に、この活動が「管理」ではなく「啓蒙と推奨」を重視する以上、その啓蒙を裏付ける専門的な見解や、実施が遅れがちな開発チームへの働きかけは、技術負債の解消という大きな課題と密接に関連しており、QAチームとして直接的な成果を出すことは容易ではありません。例えば、EOLを迎えたライブラリのアップグレード対応は、開発チームが本来進めたい施策を一時中断させ、影響調査やプロダクトのコード修正に多くの工数を割く必要があります。こうした作業は、プロダクト全体の安定性にも関わるため、QAチームだけで推進するのは現実的ではありません。

以下は過去に実施したAngularアップデート対応に関する記事です。こちらにはアップグレード対応時に実際に遭遇した課題が記載されています。 tech.classi.jp

この活動の目指す場所

もし、利用中のライブラリやフレームワークに重大な脆弱性が報告された際、この活動が提供できる価値は2つあると考えています。

① 迅速な現状把握

この活動を通じて全体像を継続的に可視化・共有しているため、どのリポジトリで該当のライブラリやフレームワークが使われているか、また脆弱性のあるバージョンが利用されているかといった情報を即座に特定できます。これにより、緊急時の調査時間を大幅に短縮することが可能です。

② スムーズな対応体制の確立

脆弱性のあるバージョンが判明し、修正適用済みの新バージョンへアップグレードが必要となった場合でも、日々の開発を通してライブラリアップデートのサイクルが定着している開発チームであれば、すぐに作業に取りかかれます。

この活動が最終的に目指すのは、この活動がなくとも上記①、②の対応が開発チームで自律的に行える状態です。 そうなれば、この活動を切り出す必要はなく、適切なアップグレードが当たり前である状態と言えると思います。その状態こそがこの活動のゴールだと認識しています。

おわりに

社内では、これらの将来的なセキュリティリスクへの対策を「セキュリティコストの前払い」と呼んでいます。後々大きな負債として積み上がるだけでなく、実際に問題が発生した際の対応コストは計り知れません。日々の開発の中でどれだけ前払いできるかが重要となります。

この「前払い」をいかに促進できるかが、この活動の次の段階における重要なステップだと考えています。現在利用しているプラットフォームの機能を最大限に活用し、より自動的かつセキュアに開発できるような仕組みづくりが、今後取り組むべき内容だと感じています。

例えば、Content Security Policy*5を活用し脆弱性混入時にすぐ検知できる仕組みや、ライブラリのアップデートを最適化する仕組みなどです。詳しくは以前に書かれた記事をご覧ください。 tech.classi.jp tech.classi.jp

この活動に参加したことで、QAチームの施策がセキュリティ品質に貢献していることに気づけたことは嬉しい収穫でした。一方で、この活動を次の段階へ発展させるにあたり、QAチームの枠組みでどこまで実現できるかはまだ明確ではありません。自身のQA活動にこの経験をどう活かすべきか、模索段階であり、自身の視座の低さを痛感しています。 今後は、QAメンバーとして活動に参加する意義を明確にし、開発チームへの働きかけを強化することで、セキュリティ品質の向上に貢献できるQAチームを目指します。

*1:End of Lifeの略で、セキュリティの更新やバージョンアップの停止をはじめ、サポートの提供が終了することを意味します。

*2:Common Vulnerabilities and Exposuresの略で、公開されているソフトウェアの脆弱性やセキュリティリスクを識別するための共通の識別番号です。 CVE - CVE

*3:GitHubが提供する機能の一つで、プロジェクトが使用している依存関係(ライブラリやパッケージなど)に既知のセキュリティ上の脆弱性が発見された際に、開発者に通知するものです。 Dependabot アラートについて - GitHub Docs

*4:GoogleのAIモデルであるGeminiを活用した、詳細かつ包括的なリサーチレポートを自動的に生成する機能です。Gemini Deep Research — your personal research assistant

*5:ウェブサイトに組み込まれたセキュリティメカニズムであり、主にXSSやデータインジェクション攻撃などの、悪意のあるコンテンツの挿入によって引き起こされる攻撃を軽減するための機能です。コンテンツセキュリティポリシー (CSP) - HTTP | MDN

© 2020 Classi Corp.