$30 off During Our Annual Pro Sale. View Details »

Try creating your own orderedmap

Try creating your own orderedmap

Kyoto.go #50 オフラインLT会
https://kyotogo.connpass.com/event/313309/

kazamori

April 28, 2024
Tweet

More Decks by kazamori

Other Decks in Programming

Transcript

  1. 2 © Kazamori LLC • 森本 哲也 (もりもと てつや) •

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

    言語と encoding/json の仕様 2. OSS な orderedmap 3. 実装の話し 4.
  3. 5 © Kazamori LLC • LDAP の属性項目の並び替え • 意味的に似た属性をまとめたい ◦

    例) 名前に関する属性 ▪ cn(common name): (氏名) ▪ sn(sur name): (姓名) ▪ givenName: (名前) ▪ displayName: (表示名) • よく似た属性のグルーピングをすると 人間にとってわかりやすい (要件)フォーム設定の項目の順序を並び替えたい
  4. 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"] } } このキーバリューの 順序を制御したい
  5. 7 © Kazamori LLC • ロジックは API サーバーに寄せたいため、 ソートはサーバーサイドで行って制御したい •

    既存データは map で作られていて影響範囲が大きい • 2つの対応案 a. JSON データ構造の変更 => object の array にする b. JSON データ生成の変更 => object の順序を保持して JSON を生成する 現状の背景や制約など お前はどうする
  6. 8 © Kazamori LLC • Ordered Map があればいいんでしょ? ◦ Go

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

    順序に依存するコードを (誤って) 書いてしまったときに たまたま意図した振る舞いで動いてしまう懸念を払拭する ▪ テストがあればすぐエラーを検出できる • リファレンス ◦ Go 1 Release Notes ◦ Go maps in action Go 言語の map データ構造
  8. 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 ライブラリ
  9. 13 © Kazamori LLC • https://pkg.go.dev/search?limit=100&m=package&q=orderedmap ◦ パッケージ名に orderedmap という

    名前を付けているモジュールだけでも 80個ぐらい ある ◦ 誰かどころか、多くの開発者が自分で作っている • pkg.go.dev でもっともインポート数が多いのは次のモジュール ◦ GitHub - iancoleman/orderedmap ◦ 軽く触ってみて私の意図する要件は満たしていた、だがしかし • 既存のアプリケーションコードと組み合わせて使うには ユーティリティ (アダプター) を実装しなければならなかった だれか作っているよね?
  10. 14 © Kazamori LLC • github.com/iancoleman/orderedmap ◦ 2018年から開発されていて実績がある (一番人気?) ◦

    ジェネリクス未対応 • github.com/elliotchance/orderedmap ◦ シンプルな設計で私たちの用途にあう ◦ JSON のシリアライズ/デシリアライズ未対応 • github.com/mroth/orderedmap ◦ シンプルな API 設計、且つジェネリクス対応 ◦ JSON のシリアライズ/デシリアライズ未対応 いくつか orderedmap の実装を読んでみる 一長一短 JSON パーサーを 実装しないといけない
  11. 15 © Kazamori LLC • github.com/kazamori/orderedmap • 特徴 ◦ キーバリューを

    Set したときの順序を保持するデータ型 ◦ JSON にシリアライズ/デシリアライズしたときに順序を保持 ◦ ジェネリクス対応 • おまけ ◦ (うちらの既存アプリケーションコード) と ぴったり相性のよいユーティリティ完備! 自分で作ったらええんやね?作りました! 後発のよさ ジェネリクス対応
  12. 17 © Kazamori LLC • map の key は comparable

    という特殊な組み込み型 ◦ 歴史的経緯でこの型は普通に実装できない => 組み込み型 ◦ go は == で比較可能な型と、比較すると panic を起こす型がある ▪ key に any を指定すると実行時に panic してしまう懸念がある ◦ go の型システムに例外的なルールを追加せざるを得なかった • リファレンス ◦ 社内勉強会向けに作った資料とサンプルコード ジェネリクスの勉強にちょうどよい課題
  13. 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 }
  14. 21 © Kazamori LLC • ordredmap は Go プログラミングの勉強にちょうどよい課題 ◦

    encoding/json の振る舞いを理解する ◦ ジェネリクスの用途にも合致して勉強になる ◦ 他者が作ったライブラリを学習して、 それを使うコード (アダプター) を書く時間で実装できる • Go の パッケージドキュメント は自動生成される ◦ github リポジトリにソースコードを push する ◦ それをアプリケーションからインポートするだけでよい orderedmap 自作のススメ パッケージング メタデータ不要
  15. 23 © Kazamori LLC OSSTech 社のパッケージ開発の現場で使っている • Unicorn Cloud ID

    Manager という ID 連携プロダクトを開発している • OSSTechブログ で技術情報を発信している ◦ go-ldap へのコントリビューション もよかったらどうぞ このスライドで紹介した内容の関連情報