Slide 1

Slide 1 text

2024-04-28 (Sun.) Tetsuya Morimoto orderedmap 自作のススメ Kyoto.go #50 オフラインLT会

Slide 2

Slide 2 text

2 © Kazamori LLC ● 森本 哲也 (もりもと てつや) ● 神戸市在住 ●   カザモリ合同会社 ○ フルリモートワークで他社の開発のお手伝いをしている ■ 直近の事例: OSSTech株式会社様 システム開発 ● 課題管理 (課題管理システム) という分野に関心がある ● 言語歴は Python → Java → Go をそれぞれ5年ほどの実務経験 ● プログラミングや OSS 文化が好き 自己紹介

Slide 3

Slide 3 text

3 © Kazamori LLC 目次 Ordered Map 開発の背景 1. Go 言語と encoding/json の仕様 2. OSS な orderedmap 3. 実装の話し 4.

Slide 4

Slide 4 text

4 © Kazamori LLC Ordered Map 開発の背景

Slide 5

Slide 5 text

5 © Kazamori LLC ● LDAP の属性項目の並び替え ● 意味的に似た属性をまとめたい ○ 例) 名前に関する属性 ■ cn(common name): (氏名) ■ sn(sur name): (姓名) ■ givenName: (名前) ■ displayName: (表示名) ● よく似た属性のグルーピングをすると 人間にとってわかりやすい (要件)フォーム設定の項目の順序を並び替えたい

Slide 6

Slide 6 text

6 © Kazamori LLC ● サーバーサイドから返している JSON データのサンプル JSON データのサンプル { "dn": "uid=t2y,ou=users,dc=kazamori,dc=jp", "attributes": { "objectClass": [ "top", "person", "posixAccount" ], "cn": ["Tetsuya Morimoto"], "sn": ["Morimoto"], "givenName": ["Tetsuya"], "displayName": ["t2y"] } } このキーバリューの 順序を制御したい

Slide 7

Slide 7 text

7 © Kazamori LLC ● ロジックは API サーバーに寄せたいため、 ソートはサーバーサイドで行って制御したい ● 既存データは map で作られていて影響範囲が大きい ● 2つの対応案 a. JSON データ構造の変更 => object の array にする b. JSON データ生成の変更 => object の順序を保持して JSON を生成する 現状の背景や制約など お前はどうする

Slide 8

Slide 8 text

8 © Kazamori LLC ● Ordered Map があればいいんでしょ? ○ Go 言語で map っぽいデータ構造の順序を制御できるようにする ○ JSON のシリアライズ/デシリアライズを object 要素の並び順を保持して行う ● リファレンス ○ RFC 7159 - The JavaScript Object Notation (JSON) Data Interchange Format 日本語訳 ○ オブジェクトは、0個以上の名前と値のペアの順序付けられていないコレクションです。 ぼくのかんがえたさいきょうのじっそうあん 実装依存

Slide 9

Slide 9 text

9 © Kazamori LLC Go 言語と encoding/json の 仕様

Slide 10

Slide 10 text

10 © Kazamori LLC ● map をイテレートするときに意図的に順序をランダムにしている ○ 設計の意図 ■ 順序に依存するコードを (誤って) 書いてしまったときに たまたま意図した振る舞いで動いてしまう懸念を払拭する ■ テストがあればすぐエラーを検出できる ● リファレンス ○ Go 1 Release Notes ○ Go maps in action Go 言語の map データ構造

Slide 11

Slide 11 text

11 © Kazamori LLC ● JSON の object を go の map にマッピングしたら順序を保証できない ○ map ではない、カスタムデータ型を定義 ○ MarshalJSON/UnmarshalJSON メソッドを実装 ● リファレンス ○ encoding/json - Go Packages ○ encoding/json: no way to preserve the order of map keys · Issue #27179 encoding/json ライブラリ

Slide 12

Slide 12 text

12 © Kazamori LLC OSS な orderedmap

Slide 13

Slide 13 text

13 © Kazamori LLC ● https://pkg.go.dev/search?limit=100&m=package&q=orderedmap ○ パッケージ名に orderedmap という 名前を付けているモジュールだけでも 80個ぐらい ある ○ 誰かどころか、多くの開発者が自分で作っている ● pkg.go.dev でもっともインポート数が多いのは次のモジュール ○ GitHub - iancoleman/orderedmap ○ 軽く触ってみて私の意図する要件は満たしていた、だがしかし ● 既存のアプリケーションコードと組み合わせて使うには ユーティリティ (アダプター) を実装しなければならなかった だれか作っているよね?

Slide 14

Slide 14 text

14 © Kazamori LLC ● github.com/iancoleman/orderedmap ○ 2018年から開発されていて実績がある (一番人気?) ○ ジェネリクス未対応 ● github.com/elliotchance/orderedmap ○ シンプルな設計で私たちの用途にあう ○ JSON のシリアライズ/デシリアライズ未対応 ● github.com/mroth/orderedmap ○ シンプルな API 設計、且つジェネリクス対応 ○ JSON のシリアライズ/デシリアライズ未対応 いくつか orderedmap の実装を読んでみる 一長一短 JSON パーサーを 実装しないといけない

Slide 15

Slide 15 text

15 © Kazamori LLC ● github.com/kazamori/orderedmap ● 特徴 ○ キーバリューを Set したときの順序を保持するデータ型 ○ JSON にシリアライズ/デシリアライズしたときに順序を保持 ○ ジェネリクス対応 ● おまけ ○ (うちらの既存アプリケーションコード) と ぴったり相性のよいユーティリティ完備! 自分で作ったらええんやね?作りました! 後発のよさ ジェネリクス対応

Slide 16

Slide 16 text

16 © Kazamori LLC ジェネリクス対応の orderedmap

Slide 17

Slide 17 text

17 © Kazamori LLC ● map の key は comparable という特殊な組み込み型 ○ 歴史的経緯でこの型は普通に実装できない => 組み込み型 ○ go は == で比較可能な型と、比較すると panic を起こす型がある ■ key に any を指定すると実行時に panic してしまう懸念がある ○ go の型システムに例外的なルールを追加せざるを得なかった ● リファレンス ○ 社内勉強会向けに作った資料とサンプルコード ジェネリクスの勉強にちょうどよい課題

Slide 18

Slide 18 text

18 © Kazamori LLC 実装の話し

Slide 19

Slide 19 text

19 © Kazamori LLC ● キーバリューを Pair 型として定義 ● OrderedMap の実装 ● UnmarshalJSON メソッドの実装 コードリーディング type Pair[K comparable, V any] struct { Key K Value V } type OrderedMap[K comparable, V any] struct { pairs []Pair[K, V] index map[K]int pos int }

Slide 20

Slide 20 text

20 © Kazamori LLC まとめ

Slide 21

Slide 21 text

21 © Kazamori LLC ● ordredmap は Go プログラミングの勉強にちょうどよい課題 ○ encoding/json の振る舞いを理解する ○ ジェネリクスの用途にも合致して勉強になる ○ 他者が作ったライブラリを学習して、 それを使うコード (アダプター) を書く時間で実装できる ● Go の パッケージドキュメント は自動生成される ○ github リポジトリにソースコードを push する ○ それをアプリケーションからインポートするだけでよい orderedmap 自作のススメ パッケージング メタデータ不要

Slide 22

Slide 22 text

22 © Kazamori LLC リファレンス

Slide 23

Slide 23 text

23 © Kazamori LLC OSSTech 社のパッケージ開発の現場で使っている ● Unicorn Cloud ID Manager という ID 連携プロダクトを開発している ● OSSTechブログ で技術情報を発信している ○ go-ldap へのコントリビューション もよかったらどうぞ このスライドで紹介した内容の関連情報

Slide 24

Slide 24 text

ありがとうございました!