Blog ブログ
拡張出来るソートを作った話
皆様、こんにちは。
プログラマの原です。
暑い日々が続いているので、熱中症には気をつけましょう。
さて、今回は拡張出来るソート機能を作った話を紹介しようと思います。
以前にランキング機能の開発を行っている時にランキングに使うユーザデータがあり、ランキングの機能としてユーザデータをソートする機能を作る必要がありました。
ランキングに登録しているユーザデータの中身は、以下の3つの要素で構成されています。
- ID:ランキングに登録された順番の番号
- ランク:ユーザのランキングのランク
- ポイント:ユーザが獲得したポイント
上記の要素を使ってソート機能を作るのですが、単純にランク順に並べるだけかと思ってたのですが、以下の条件を満たす必要がありました。
- ソートのキーは3つあり、3つのキーの組み合わせが違うソート条件が3種類あります
- ソートのキーの組み合わせは以下になります
ー>ID順→ランク順→ポイント順
ー>ランク順→ID順→ポイント順
ー>ポイント順→ID順→ランク順 - ソート条件の一覧のグループボタンの状態に応じて、ソート条件を切り替えることが出来ます
要するに複数条件でソート出来てかつソート条件は動的に変更が出来る処理を作らなければなりませんでした。
ソート処理を作る
今回は、C# の LINQ を利用するためソートの方法は「OrderBy」と「ThenBy」を選択しました。
また、ソート条件に応じてキーの組み合わせを切り替える方法はキーの組み合わせ毎にメソッドを用意して、外部から与えられた条件に応じて呼び出すメソッドを切り替える方法を考えました。
上記を踏まえて以下のコードを書きました。
ただ、このコードにはこんな問題があります。
「キーの組み合わせが増えたり、組み合わせが変わったらメソッドの追加や変更をしないといけないし、変更でバグが出る可能性がある」
書いていた時は「よし、このコードでいける!!」と思っていました。
しかし、後から考えるとこの方法では仕様変更に弱いコードとなってしまっています。
どうすればいいかとなっていたところ、社内の技術サポータの方からキーをパラメータ化してキーの組み合わせ毎にパラメータを変えるようすればいいのではと言われました。
キーをパラメータ化してしまえば、キーの組み合わせに追加や昇順・降順を変えたい場合でもパラメータを変えるだけで済むため、変更する箇所も少なくなります。
そこで、キーのパラメータを作成できるメソッドと複数条件ソートに対応するために作成したキーのパラメータを使って、LINQのThenByの代わりとメソッドを用意しました。
この機能をまとめたものとして「ComparerExtension」というクラスを作成しました。
このクラスの使い方としては、キーのパラメータを「compareBy」メソッドで作成して、「thenBy」メソッドでキーの組み合わせのパラメータを作成します。
後は、OrderByにキーの組み合わせのパラメータを渡して上げるだけで済みます。
キーをパラメータ化に書き換えたコードが下記になります。
キーをパラメータ化したことで、たいぶコードがすっきりしました。
キーをパラメータ化したことで、キーが増えた場合は、compareByメソッドを使えばすぐ作れ、キーの組み合わせもthenByに渡すIComparerの配列の要素の並び順を変えるだけで済みます。
また、ジェネリック型のメソッドで用意しているので、例えばキャラクターの使用率のパラメータを持つモデルがあって使用率順にランキングを作りたい場合もキャラクター使用率モデルの使用率のパラメータを渡せばキャラクターの使用率順にソートをすることも出来ます。
おわりに
こうすれば、もっと良くなると考えてコードを書かないといけないです。
今回作成したソート機能は、だいぶ汎用的に使えるものになったのではないかと思います。
汎用的に使えるように作っているのでライブラリ化すれば、結構便利に使えるものとして役立て貰えそうな気がします。