uokadaの見逃し三振は嫌いです

ここで述べられていることは私の個人的な意見に基づくものであり、私が所属する組織には一切の関係はありません。

Pixel 6a からPixel 10に乗り換えた

Googleブラックフライデー・セールでPixel 10に乗り換えたのでその備忘録です。

store.google.com

それまではPixel 6aを使っていましたが、9月頃にバッテリーの警告が出るようになり、その頃からこのセールのタイミングで買い替えを決めていました。

10月頃は同じaシリーズのPixel 9a一択だったのが、11月中旬になって実機を触ってみてPixel 10の方にも興味が出てきて、久しぶりにaシリーズじゃない機種を買おうと思った次第。

Pixel 6aは2023年の12/31に先代の端末が午前中に急に電源が入らなくなったため、急遽中古で購入したものでした。 もっと早く買い替えると思っていましたが、気に入った機種がなかなか出てこなかったので、結果的に2年近くもお世話になるとは思いもしませんでした。

機種変更直前に旅行に行っていて、Pixel 6aのカメラ性能に時々ガッカリすることがありました。そのこともあって、Pixel 10のカメラの進化がどれぐらいのものかこれから試していきたいと思っています。

画面フィルムとケースは下の2つを購入しました。ケースは背面側のカメラが傷つくのが多少心配だけれどSpigenは自分の中では安心できるメーカーなので今回はここを選択しました。

https://www.amazon.co.jp/dp/B0F9WMMLB9

https://www.amazon.co.jp/dp/B0F49GLLY8

2025-11-15 JJUG 2025 Fallに参加してきた

JJUG CCC 2025 Fall(現地開催のみ) - 日本Javaユーザーグループ/Japan Java User Group | Doorkeeper

jjug.doorkeeper.jp

午後からの参加だったので、いくつか参加出来たものとスライドだけ見たものについてメモを残しておく。

Quarkusで作るInteractive Stream Application

Quarkusで作るInteractive Stream Application - Speaker Deck

Quarkusを自分でも使っているのでReproではどういった使い方をしてるか知るために参加。Streamingアプリケーションでの実運用でのノウハウがチラホラ見えてその辺は参考になった。

はじめての OSS コントリビューション 〜小さな PR が世界を変える〜

はじめての OSS コントリビューション 〜小さな PR が世界を変える〜 - Speaker Deck

これはセッションには参加できてなくスライドしか見ていないのだが、 自分もOSSにいくらかコントリビュートしていて自分が意識できていない事など学びがあるスライドだった。

mvnコマンドに関するスライドはquarkusなどの大きめのプロジェクトだとビルドに10分以上掛かるようになるので

アーキテクチャと考える迷子にならない開発者テスト

アーキテクチャと考える迷子にならない開発者テスト - Speaker Deck

自分のテスト周りの理解について、改めて整理できた気がした。 テスト対象の範囲を描画することでこのテストでどこをテストするのかという認識することが出来たように思う。

バーチャルスレッドは実アプリでどこまで使えるか〜コンテナ環境での効果検証でわかった注意事項〜

バーチャルスレッドは実アプリでどこまで使えるか | ドクセル

WebFlux、VT、PTの3つを比較したセッション。パフォーマンスを比較するためのチューニングやメトリクス周りの話は実運用をする上で知りたかった知識だったので、実運用する際の目安としたいなと。

Virtual Thread Deep Dive

JJUG CCC 2025 Fall: Virtual Thread Deep Dive - Speaker Deck

個人的にこのセッションが一番仕事的にも役立つ内容だった。 近々Java 21でVirtual Thread を使ったアプリケーションを作ろうと思っていたので、 JEP 491で修正されたVTのissueなどまだ把握出来ていない情報を得られたので一番参加して良かったセッションだった。

喋りも早くて情報量は多かったが、すんなりと頭に入ってくるセッションだったので喋りとテンポがちょうど良いなと。 流石、Yahoo!のSWATの人でした。

その他資料

資料をまとめてくれている記事があったのでリンクを。 yujisoftware.hatenablog.com

まとめ

JJUGに1年ぶりぐらいに行ってみた。JDK 25を使うような話題をしていて、まだJDK 11残っているうちの環境随分遅れてるなと実感した1日だった。

2026年にMinimumをJDK 21まで引き上げて一部をJDK 25まで上げるための良い情報を出来た収穫の多い1日だった。

n月刊ラムダノート Vol.5の「実用Raft」特集を読んだ

n月刊ラムダノート Vol.5, No.1(2025) – 技術書出版と販売のラムダノート

きっかけは「実用Raft」の特集に惹かれたことでした。 オフィスに行くようになって、フリーアドレスの机に誰かのn月刊ラムダノート Vol.5がずっと置いてあってペラペラとめくっていたらRaftの特集が気になったので自分でちゃんと買ってこの夏読みました。

raft.github.io

Raftの名前は時々耳にするけれど、詳細を全く知らなかったのでこの特集で概要を押さえてその後はNotebookLMを使って元の論文を読んだり、ChatGPTにRaftを使ったプロダクトについて教えてもらったりしてRaftとその周辺知識をアップデートできました。 Paxosよりも後発で出てきただけあって、シンプルな実装であったりと特集内で実装を紹介していることもあり短時間程度で読むことができました。

また、Kafkaがいつの間にかZookeeperへの依存をやめて独自のRaftに切り替えていることや、Apache RatisやMyRaftといった実装の存在を知ることができたのも収穫でした。

自分のプロダクトでのRaft活用の可能性を探る意味でも、ChatGPT / NotebookLMを活用しつつ、手を動かしてRaftのサーバーを書いてみようかなというのが今日この頃です。

uvを試している

www.oreilly.co.jp

オライリーのハイパーモダンPythonをチラ見して、uvが気になったので2025年はpoetryの代わりに使っていこうと思い、プライベートとか小さいところから使い始めている。

uvの進化が早いので日本語版のハイパーモダンPython でも、補足で「v0.3.0では〜」の補足が入っていて仮想環境の作成やpipxの代わりとして使えるようになっているなど少し古い情報にとどまっているし、uvはメインでは触れられてないので今は公式ドキュメントを読みながら使い方を学んでいる。

github.com Working on projects | uv

poetry run よりも uv run/uv tool runがかなり早くて色々と捗るなあという印象。

2月末ぐらいまでに時間を取って置き換えるかの結論を出せればなと思っている。

2025年4月追記

新規プロジェクトではuvを採用にするようにした。

GithubのDependabotもuv.lockをサポートしたので、仕事でも使うことに支障はほぼ無いのではないと思っている。 github.com

uv scriptの対応についいてはまだされていなさそうだけど、書き捨てのスクリプトなどであればバージョンアップに神経質にならなくて良いと思うので、uv採用のブロッカーではないでしょう。 docs.astral.sh

今後既存のプロジェクトも適宜置き換えていきたいと思っている。

SONY Linkbuds Sを買った

SONY WI-SP510が壊れたので同じSONYのLinkBuds sに買い替えた。

www.sony.jp

www.sony.jp

WI-SP510を2020年に買って主にジムでトレーニング用に使ってきたんだけど、先週突然右側だけ聞こえなくなってしまいました。4年近く使って来たのでこれは寿命かなと思い、週末ヨドバシカメラで色々と比較していました。 少し前から、WI-SP510の後継機が無いことに気づいていたので次をどうしようか悩んでいたんですが目的から考えてジムで使ってる時にズレにくいものに重点を置いて見ていった結果、最終的にLinkBuds Sに行き着きました。

LinkBuds Sは2022年6月発売で発売から2年の時が経過しているのにヨドバシカメラの価格で26,000円がちょっと高いなと感じて色々と見て廻って、最終的に秋葉原のeイヤホンで中古品を1万そこらで買いました。 ヤフオクなどのオークションサイトなら8千円前後でもう少し安く買えるみたいですがすぐ使いたかったので今回初めてeイヤホンにお世話になりました。 kakaku.com

これを今週ジムで使ってみて運動中にも問題なく使えることが確認できたら、LinkBudsの後継機が出た時に乗り換えれたらなと考えてます。

[9/21 追記] ジムでランニングする際に使ってみて、全然耳からずり落ちないことを確認できた。 Google Pixel Budsで試したときは直ぐに外れるって印象だったからLinkBuds Sの方が全然エクササイズ向きって印象です。(もしかしたら、サイズが合ってないだけかもしれないけど)

Pixel Budsも併用して使っていたんだけど1年ぐらい前から右側だけ直ぐに充電が切れるのでずっと買い替え時を探っていたので今回良いイヤホンに出会えて良かった。 やっぱり、自分の中ではSONYのオーディオ・デバイスは安心感がある。

[追記ここまで]


他に、買わなかったけどAnkerのSoundcore Sport X20の装着感が良かったのでLinkBuds Sに出会ってなかったら予算的にもこれを買ってたと思います。 イヤホン上部についているフックが伸び縮みや回転して調節が出来るのでしっかりと自分の耳にフィットする感がありランニング中でも外れなさそうだなという印象でした。

Soundcore Sport X20www.ankerjapan.com https://www.yodobashi.com/product-detail/100000001008561488/www.yodobashi.com

quarkus-smallrye-openapi とInstancioを使って手軽にOpenAPI.yamlとスタブサーバーを作る

ja.quarkus.io

www.instancio.org

quarkus-smallrye-openapi はJavaのクラスからOpenAPI のYAML/JSONを生成出来るQuarkusの拡張で、InstancioはJavaのクラスから手早くダミーのオブジェクトを生成するライブラリです。

自分はこれらを2つの目的で使用しています。

1つ目はOpenAPI YAMLの生成・提供です。OpenAPI YAMLを直接書いても良いのかもしれませんが、修正作業が入ったときに手作業だと修正漏れなどのミスが発生する可能性が高いです。Javaファイルの修正の場合IDEに修正を任せらることやCompilerでエラーの検出が可能となります。

2つ目はスタブサーバーの提供です。ダミーデータの生成をするライブラリはdatafakerなどいくつかありますが、自分はInstancioが一番手軽に利用できるライブラリだと思います。 よりリアルなスタブサーバーを作成したい場合には、datafakerを使ってリアルなデータを生成して使っています。

次からは、どうやって今回の目的のquarkusアプリケーションを生成するか手順を紹介します。

まず、quarkusコマンド*1を使ってアプリケーションを生成します。

# quarkus create app --java <java version> --maven -P <quarkus version> --wrapper --extension <Quarkus extensionのリスト(カンマ区切り)> -o <出力先ディレクトリ> <Javaアプリケーション>
$ quarkus create app --java 17 --maven -P 3.11.3 --wrapper --extension io.quarkus:quarkus-smallrye-openapi,rest-jackson -o . io.github.yuokada.sample:quarkus-openapi-app
-----------
selected extensions:
- io.quarkus:quarkus-rest-jackson
- io.quarkus:quarkus-smallrye-openapi


applying codestarts...
📚 java
🔨 maven
📦 quarkus
📝 config-properties
🔧 tooling-dockerfiles
🔧 tooling-maven-wrapper
🚀 rest-codestart

-----------
[SUCCESS] ✅  quarkus project has been successfully generated in:
--> /path/to/quarkus-openapi-app
-----------
Navigate into this directory and get started: quarkus dev

次に、ダミーデータを生成するためにpom.xmlに次のコードを追加してinstancio-coreを導入します。

    <dependency>
      <groupId>org.instancio</groupId>
      <artifactId>instancio-core</artifactId>
      <version>4.8.0</version>
    </dependency>

そして、APIの実装をInterfaceを使って定義していきます。Interfaceを作成せずClassに直接アノテーションを付与してもOpenAPI yamlの生成は出来ますが、OpenAPIの複数のアノテーションを付与すると見通しが悪くなるので自分はInterfaceとClassに分けるスタイルを採用しています。

メソッドに@GET, @Path, @APIResponses などのAPIエンドポイントの定義をアノテーションで付与していきます。*2

必須なアノテーションとしては @(GET|POST|PUT|DELETE), @Path をぐらいを定義していればスタブサーバーの生成には十分です。あとは、必要に応じてクエリパラメータ・パスパラメータなどを定義します。

@Produces(MediaType.APPLICATION_JSON)
public interface SampleApiIf {

    @GET
    @Path("/")
    @Operation(
        summary = "Return a list of players",
        description = "Return a list of players"
    )
    @APIResponses({
        @APIResponse(
            responseCode = "200",
            description = "Returns a list of players",
            content = @Content(
                mediaType = "application/json",
                schema = @Schema(type = SchemaType.ARRAY, implementation = Player.class)
            )
        ),
    })
    Response getPlayers();

    @GET
    @Path("/{id}")
    @Operation(
        summary = "Return the detail of a player",
        description = "Return the detail of a player"
    )
    @APIResponses({
        @APIResponse(
            responseCode = "200",
            description = "Returns the detail of a player",
            content = @Content(
                mediaType = "application/json",
                schema = @Schema(type = SchemaType.OBJECT, implementation = Player.class)
            )
        ),
    })
    Response getPlayer(@PathParam("id") Long userId);
}

Interfaceの定義が完了したら次はその実装を作ります。今回はInstancioを使ってダミーデータを生成しそれをAPIのレスポンスとします。

Instancioでは完全にランダムな値を生成する以外にもset()で値を指定したり、generate()で範囲を決めたランダムな値を付与することが出来ます。

@Path("/v1/api/stub/players")
@Tag(name = "Demo App stub API", description = "Demo App Common APIs for development")
@Deprecated
public class StubApiImpl implements SampleApiIf {

    @Override
    public Response getPlayers() {
        List<Player> players = Instancio.ofList(Player.class).size(10)
            .generate(field(Player.class, "age"), gen -> gen.ints().range(15, 85))
            .create();
        return Response.ok(players).build();
    }

    @Override
    public Response getPlayer(Long userId) {
        Player player = Instancio.of(Player.class)
            .set(field("userId"), userId)
            .generate(field("age"), gen -> gen.ints().range(15, 85))
            .create();
        return Response.ok(player).build();
    }
}

ここまで実装が出来たらmavenからquarkus サーバーを立ち上げます。デフォルトだと http://localhost:8080 でサーバーが立ち上がります。 また、http://localhost:8080/q/swagger-ui/#/ でSwagger UIが利用できるので実装したAPIに手軽にリクエストを投げて検証出来ます。

$ ./mvnw quarkus:dev

openapi.yamlの出力先はquarkus.smallrye-openapi.store-schema-directoryで変更することが出来ます。次の例だとプロジェクト直下にopenapi-definitionが作成されてそこに出力されます。

# OpenApi
quarkus.smallrye-openapi.enable=true
quarkus.smallrye-openapi.store-schema-directory=openapi-definition

実装に迷った場合はこちらのリポジトリが参考になります。 github.com

まとめです。

quarkus-smallrye-openapi を使えばOpenAPIの仕様をあまり知らなくてもOpenAPI yamlの生成が簡単に出来ることが伝わったかと思います。 自分も昔OpenAPI yamlを手書きしていましたが、仕様をある程度知らないと書くのも難しいし修正も大変だった経験があるのでJavaのコードから自動的に生成出来るというのは作成・修正するハードルが下がるので良い手法だなと思いました。

今回のコードのリポジトリはこちらです。 github.com

*1: インストールはこちらから。ja.quarkus.io

*2:詳しい仕様はこちらを参照してください。 download.eclipse.org

blackをruffで置き換えてる - Replacement black with ruff

最近、プライベートなpythonプロジェクトでblackをruffで置き換えたのでそのメモ。

ここ数ヶ月の間にblackとruffを導入したんですが、ruff v0.1.2でformatterが導入されたのでblackへの置き換えを小さめなプロジェクトで実施しました。

astral.sh

blackとruff formatのdiff check/formatのコマンド体系はほぼ同じで機械的に置換しただけで動かすことが可能でした。

# 差分チェック
$ poetry run black           --check --diff  **/*.py

$ poetry run ruff format --check --diff **/*.py

----
# ファイルのフォーマット
$ poetry run black **/*.py

$ poetry run ruff format  **/*.py

ただ、設定でまだ移行出来ないものがあります。

自プロジェクトのblackの設定はあまりカスタマイズせずで設定で使っていました。

[tool.black]
target-version = ["py39"]
line-length = 120
skip-string-normalization = true

ですが、移行を検討開始した当初skip-string-normalization = true に相当する設定がまだ存在しませんでした。 issueは上がっていたのですが、議論が続いていて解決するまでruffへの移行のブロッカーとなっていました。 v0.1.18で quote-style = "preserve" が設定できるようになりました。これが入った事で、自分のプロジェクトではpyproject.tomlとCIの設定変更だけでblackを置き換えることが出来ました。

github.com

docs.astral.sh

ruffに置き換えたことで良かったこととしては、依存関係が減ったのが一つ。それと、パフォーマンスに関してはあんまり改善された実感はありません。自分は poetry run ruff で呼び出しているのでpoetryの処理のオーバーヘッドが体感できない一因かと思います。

ruffは開発のスピードが早いので自分がこのエントリーを数ヶ月放置しているあいだにバージョン0.3までリリースされていました。 2024年はrust製のツールがこれまで以上に流行っていくのでは無いかなと思っております。