About

このサイトについて (2022)

このサイトで扱うこと。

このサイトのテーマ

Githubのフロントページとして機能しています。現在Subsonic後継のJpsonicという日本人向けのミュージックストリーミングサーバを公開しています。

このサイトは熱心に記事数を増やしていくタイプではなく、節目節目で削除や更新が行われます。「このサイトについて」も2年おきくらいに書き換えており、これが3度目になります。地上波ではジブリの映画の再放送は2年周期なんだそうです。それと同じで、大体忘れた頃に更新されます。

過去の変遷

Subsonicという老舗のストリーミングサーバがあるのですが、2016年にクローズドソースに移行するという少し大きな変化がありました。その後オープンSubsonicを維持するためいくつかのプロダクトが生まれます。その中で最も有名なAirsonicを元に日本語用に機能を作り変えたものをJpsonicとして公開しています。

LibresonicやAirsonicの初期開発には関与せず、初期段階では日本語処理を組み込んだプロトを作っていました。日本語処理で遅くなるかなというのは、プロトを作らないと判断できないためです。結果、他の部分の速度向上で相殺しSubsonic以上の速度は出せると算段がついたので、2019頃にv100.0.0を公開し本格始動することになります。

Airsonicから派生したのですが特に敵対していたわけではなく、実装のお手伝いをしたり依頼があればレビューをしていました。

リブランディング

本流で一緒にやればいいのに、という考えもあります。できなかったため分派しています。

  • 日本語処理を組み込みたい場合、実装は大幅に変わるため本流へのプルリクは困難
  • 品質を向上させようと考えた場合、ほぼ全域に渡って更新が発生するので本流へのプルリクは困難

本流がこういった拡張を望まなければ「貢献」になりません。受け入れには一次的にレビューコストがかかりますが、貢献を取り込んだ後には二次的な維持コストも発生します。折り合いがつかなければ分派がベターになります。

Javaの場合ネームスペースの命名にはドメイン名の逆転または登録商標が使用されます。開発形式がオープンソースであろうが、ドメインないし登録商標はオーナーの所有物です。特にバイナリの再配布を行う場合、本流にご迷惑をおかけしないようにするため、プロダクト構成を自前のドメイン用に書き換え、ヘッダの著作権を書き換え、プロダクト名も別物にする場合があります。

機能や開発方針が本流とは異なる場合、明確に区別を設けなければユーザが混乱し、下流プロダクトの不具合報告や悪評が本流に逆流するリスクがあります。階層的なアセット管理が破壊されないように、LibresonicでもAirsonicでも、適切なブランドチェンジが行われています。セルフブランディングや自己顕示といった流行り言葉とは無縁の、技術的で調和的な事情です。

Web画面やDLNA、音声入力等の整備

ユーザ数を増やす目的があれば、Web画面に注力する戦略が正解の一つです。ファーストインプレッションに与える影響は大きいです。寄ってくる技術者もHTMLやDBを触りたい層が大半になるため、インターネット上の評価はそこに偏りがちです。

しかし一歩引いて客観的に見ますと。日本人が「音楽をいつ聴くか」という統計を取ると、トップにくるのが「通勤・通学中」次に「ドライブ中」です。もし音楽プレイヤを進化させたいのであれば、技術的制約の大きいHTMLやJavaScriptというよりも、ネイティプアプリや組み込み、Android Auto APIといった分野のアプリ開発の方が有益です。Jpsonicでは、Webページ上の無駄な機能はオプション化し、どちらかといえば簡素化する対応が行われています。演奏機能は維持されますが、拡張されていくのは主に管理機能や、既存のスマホアプリに恩恵がある機能になります。適切にスコープを削るということです。

そのかわりストリーミングの機能をフルに利用しやすいUPnP/DLNA周辺の実装は再実装されています。またWebページ、Subsonic API、UPnP検索の処理は統一化され、どれを利用しても同様の検索が可能となっています。

テスタビリティの改善、静的解析ツール

Subsonicの不具合で比較的有名なものに、特定のプレイヤでFLACが再生できないというものがあります。クライアント側では「データが壊れています」と通知されるため原因が特定しにくかったりします。業務での開発経験をお持ちの方であればS級の不具合と認識するでしょう。ストリーミングサーバでストリーミングできなければ、修正されるまで出荷判定が下りません。

近年のスマホ事情、ネットワーク/ディスク容量/LDACといった伝送規格を考慮しますと、むしろトランスコードの重要性は徐々に薄れつつあります。すべてMP3に変換すればOKという時代ではなく、一周回って生データ直送、ハイレゾやDSD形式までビットパーフェクト送出できるのが当たり前品質です。Jpsonicではこれら一見分かりにくい不具合も多数修正しています。

こういった修正にはテストが必須ですが、そこまで手が回っているOSSプロダクトはなかなかありません。そもそもテストを念頭に置いておらずテストしづらい実装がされている場合もあります。Jpsonicはこれを解消するためほぼ全クラスの実装に改修を加え、静的解析ツールを多数使用し一般的なコードチェックは通過するよう書き換えられています。

日本語処理も特徴の一つですが、基礎機能や不具合改修を重視しているという点が他のプロダクトと異なります。

品質向上への取り組み

「新しい機能の追加だけすれば?」と考える方もいらっしゃるかと思います。もちろん元の品質が良ければそれが可能ですが、そうではない場合、次に作業精度の低い人間がそれを真似して破綻する、ジェンガ末期のようになります。アートの世界では「粗削りながら新進気鋭」みたいな評価もありえますが、ITでは原因を無視したトライアルアンドエラーはチャレンジになりません。

品質を犠牲にすることでソフトウェア開発のスピードは上がるのか?
システム開発の品質とスピードはトレードオフなのか?

和田卓人さんのセッションのダイジェスト。「テスト書いてないとかお前それ@t_wadaの前でも同じ事言えんの?」の方。

  • 品質を犠牲にすると短期的なスピードを得て、中期的に逆効果、長期的には致命傷になる
  • 「品質とスピードはトレードオフの関係にある」は大きな誤解。どちらか捨てるともう片方も死ぬ
  • スピードおよび質とトレードオフなのは、教育、成長、多様性への投資

Airsonicクローズ時点で中期には来ていると思います。リセットしなければ早晩致命傷になるでしょう。そのためAirsonicクローズ前後から2年程は、内部品質の向上が重視されていました。技術者向けですが、行った対策を書いてみます。割と基本。

テストをしやすくする

SubsonicやAirsonicの実装で致命的なのは、@Autowiredでフィールドインジェクションしている点です。Springが推奨しているコンストラクタインジェクションを使えというのは、好みの問題でも可読性の問題でもありません。フィールド定義の場合モックを使った単体テストが行いづらいです。モックの単体テストができなければアジャイル開発はできません。

コンストラクタを書き換えたら、次に取り出すのがPMDです。解析ツールって「文字列は==じゃなくてequalsで比較」みたいなのでしょ、という程度の認識であれば改めた方が良いかもしれません。この状況で最初に利用するのは複雑度でしょう。PMDは三種の複雑度計算に対応していますが、Jpsonicでは開発時にそのうち2種使用しています(1つはCodacyで監視可能)。

具体的には、長くて複雑なメソッドではPMDの警告が出るので細分化することになります。このときのコツは、人間の感覚をあてにせずツールの指摘通りに分割することです。細かすぎるとか、メソッドとは意味の塊なのである、とかいう詩人の意見はゴミ箱にダンクシュートします。ミスがあっては本末転倒ですので、適当にテストを付け加えながら進めます。

なぜ複雑度で定量化して分割していく必要があるのかというと、メソッド毎のテストケースを膨れにくくするために有効であり、主観を排除できるからです。テストドリプンの開発では、生産性への影響は可読性よりも大きいでしょう。可読性を向上してもバグは減りません。バグはバグの原因を潰したときになくなります。テストさえあれば可読性の向上はいつでもできます。

モックを活用する

ウォーターフォールの大規模プロジェクトの場合、機能を確認できるような典型的なデータパターンを先に用意して、それを使ってテストをするようなやり方がよく行われます。もちろんそれも必要なことなのですが、統合テスト用のデータで個別機能の開発や動作確認を行うのはおそろしく時間がかかります。

どんなやり方のテストでも、カバレッジ60%くらいは比較的簡単に到達してしまうものです。騙されてはいけない。より細かくアジャイルチックな開発を実現するには、モックを活用した単体テストにシフトしていく必要があります。

カバレッジ60%くらいになれば、テスト効率が悪い箇所は自明だったりします。そういった場合、クラスごとの単体テストに記述するモックとは別に、どこでも使える共通のモックオブジェクトを作っておきます。あるいは機能の上位に位置するクラス(設定を読んだり書いたりするようなクラス)は最初からモックを作っておきます。

Jpsonicでこれが行われたのもカバレッジ60%の頃です。レガシーサーバのサルベージ開発ではあらゆる手順が逆転します。

静的解析ツールを活用する

JpsonicではJavaのコード解析にPMD, SpotBugs, Findsecbugs, CodeQL, Facebook Infer, Google Error Prone等を利用しています。これらをひたすら修正します。修正する箇所はカバレッジを確保するようにし、難しい処理はデシジョンテーブルを書いて、分岐網羅なり入力網羅しておきます。テストは正常動作を証明するためのものですが、完璧を目指すと終わらないのでまずは「デグレート検知」程度を目標にします。あとでその機能を改修するようなことがあればさらに詰めればよいだけです。

モックが使えなかったり複雑度を考慮していない場合、この作業がとてもリスキーなものになります。恐ろしいのは、それだけ手を尽くしてもこの作業の最終的な工数は読みづらいという点です。

  • 品質の低いプロダクトであれば、エラーが数千件出ると思います。解析ツールはエラーがあればそこで解析を停止する仕組みになっていることが多いので、修正すると新たなエラーが出現します。最終的には修正と抑制を駆使して0件近くに持っていく必要があります。実際には初期に目にする警告の、倍掛け程度の問題が潜んでいることが多いです。
  • ユーザがついているサービスなので、看過できない実装バグや設計バグがあれば都度修正します。工数は膨れますが悲観することはありません。それが目的のひとつだからです
  • バグを超越して害をなす機能や、デフォルトでは無効化しておくべき機能は別途対処します。WikiのSuppressed or Removed Featuresのように
  • 作業しつつもライブラリも解析ツールも常に最新化していくという条件であれば、エラー数は増えたり減ったりするはずです。なぜかというと、案外と解析ツールも日々進化しているため、新たに検知できるバッドケースが増えるからです

所感ですが、これらを潰してCIに載せるまで、相応の方がフルタイムでやって国産高級車一台分くらいです。あらお安い。他の作業も並行していればすぐに数年経つでしょう。ちなみに開発現場でこういった業務が発生することは滅多にありません。お金にならないし終わりが見えないからです。先進国最低賃金の感覚でそれなので、大国での感覚はなおさらです。

これらの工数を半分以下に抑えるテクニックがあります。最初からそういう設計と実装をすればよいです。というか普通はそうしますしPMDくらいはどこでも使われると思います。それだけでも全然救いがあります。

Airsonicの開発にはプロジェクト方針が設定されており、期間内で一定以上の成果を出しています。ですのでAirsonicのやり方がまずかったとかそういう話ではありません。当時の最適解ですし、よりよい結果を出したプロジェクトは皆無です。ただしこれをさらに発展させるとなると、客観的に見て積み残しの必須作業が明確なので解消しましょう、というだけの話です。

こういったことを単騎でこなす仕事のやり方は、敬遠される場合もあります。作業は属人化するなとか、コミュニケーション重視とか。それは正解ではありますが、情報共有が重要なのは特に外部品質の改善フェーズの話です。

[外部品質]人の目があった方がよい
一方内部品質の改善は単騎でできないこともありません。例えば静的解析ツールには

  • 大規模コミュニティで開発されたもの
  • 大企業が資本投下して開発したもの
  • 天才が作り上げたものを大企業が買収して公開しているもの

など様々な形態があります。それぞれ得意分野が異なり内部品質のノウハウも集積されています(… 資産が豊富なC系/Javaでは)。多大なコミュニケーションや資本を投入して作成された有能なツールで、しばしば品質定量化の指標に利用されます。


[内部品質]セオリーによる解決が多い

外部品質と内部品質はどちらを優先すべきでしょうか。和田さんのセッションにあるように内部品質が先です。内部品質にもいろいろありますが、最優先すべきはTestabilityかと思います。テストができなければ処理を置き換えることができないので、他の***bilityも改善しにくくなります。それらを放置した場合、新規機能の追加どころかバグが滞留し、やがて開発は停止します。

今後の予定

テストはしやすくなっていますし、解析ツールでエラーはほぼゼロ(一件残し)になっています。内部品質に関しては完璧と言わずとも、小さい山を一つは越えたと言えます。今後行われる修正、あるいはまったくの新規コードについても同水準の品質が担保されます。負の遺産の整理とも言えますが、ゴールが先に存在するのであれば投資になります。

以下、これから行われるであろう一部を記述します。

外部品質の向上(ボチボチ)

バニラAirsonicにあるユーザからのバグ報告をすべてさらって解決していくのがよいかと。一種の資産なので再利用できます。私の記憶では、それほど深刻なものはなかったように思いますし、Jpsonicでは既に改善されているものも多数あります。情報整理や調査が必要になるのでボチボチ進行です。

優先して修正して欲しい不具合がございましたらご報告いただければ、いつまでとは言いませんが優先して対処します。Airsonicで既知のバグの場合リンクを頂ければ幸いです。純粋にJpsonicのバグであってもご報告ください。プルリクは歓迎です。

スキャンの改善(直近)

スキャンにまつわるいくつかの改良が行われる予定です。

v111では本来スキャンを改修する予定でした。先に内部品質あげときたいよね、Before/Afterが計測できるようにDockerも整備しときたいよね、といった理由で後ろにずれこんでいるだけです。

速度改善

個人レベルのストリーミングサーバにとって極端なレスポンス速度が必要なものかというと、そうでもありません。速度に規定があるDLNAが機能するのであれば十分速いです。どちらかといえば速度改善と称して動作に必要なリソースを跳ね上げてしまうようなフェイク改善が嫌いです。環境によっては動かなくなったり遅くなる恐れがあるので。

特に速度改善の必要があるのは、スキャンと索引生成、動画の解析くらいだと考えています。機能以外の部分で言えば、不足しているDBインデクスを手入れする等。曲数に対して指数関数的に速度が落ちるような箇所は、速度改善の対象になります。

それ以外は大したことじゃないので、困ったときに考えれば良いんじゃないかと思います。多分困らないので。

Podcastの再実装

近年Podcastの配信はApple/Amazonに集約されるようになってきています。日本でもJ-Waveなんかは早くからAppleに引っ越ししました。文化放送やNHKのようにRSSのURLをモロだしするのではなく、Webページで視聴は完結させて、後はAPI経由という作りです。この場合URLが簡単に調べられないので、時代遅れの機能を更新する必要があるということです。URL入力は残りますが、チャンネル名で検索して追加、みたいになるのだと思います(API見てないのでテキトーに言ってみた)。

Subsonic/AirsonicでもPodcastに対するリクエストはしばしばありました。そりゃー私だって使いづらいぞなんじゃこりゃーと思っています。全面改装が必要。

スマートリスト

詳細検索あたりをリプレースして、スマートリストを作れるようにすればいいんじゃないかと思っています。Subsonic/Airsonicでリクエストをよく見かけました。ちなみに私はアルバムごと聴く派なので、スマートリストは使ったことがありません。今はアルバムごと聴くという文化が下火に向かいつつあるので、必要な機能になっていくのかもしれません。

タグチェッカー

Jpsonicはタグ抜けを補完するダーティデータ対策が施されており内部では「このデータ良くないね!」というのは把握していたりします。ですので簡単なタグチェッカーを作れたりします。SQL叩けば済む問題だったりもするので優先度は低め。

画面側の変更

Web画面が「あたりまえ品質」に入るか入らないかといえば、微妙なラインだと思います。合理的に言えば、極論Web画面は無しでも用が足ります。人気取りに走るのであればWeb画面に全力投球すべきでしょう。

現状こんなところを理由に、Webページ側は後回しにしています。

  • (ハイブリッドのWeb画面を作ることは可能ですが)特にスマホ上では、できないことだらけになります。この分野でスマホのネイティブアプリの性能をWebアプリが凌駕することはありません。PC上での利用は一定のニーズがありますが、純粋に音楽を聴くという視点から言えばパイは小さくなります。人類が音楽を聴くときにWeb画面が目の前にある必要はありません
  • Web画面を使いやすくしていくこと自体は有用であり必須な部分はあります。主に設定画面や、リストの編集です
  • サーバがちゃんと動くのが最優先です。画面に時間を割いているプロダクトのissuesを見ると、大体大きなバグだらけです

ただし上記「今後の予定」の大部分が片付けば、あるいは途中で、Webページ側に何らかのフレームワークを入れてデザイン改修に着手していくのもありかと思います。

具体的に言えば、CSSやスクリプト関連の何らかのフレームワークを利用していくことになるでしょう。特にこだわりはなく何でもいいんじゃん?と考えているので、そこそこ有名なものを使うと思います。「これから使うならこれがいいと思うよ」というご意見があれば参考にします。CSSまわりのマイナーチェンジレベルの想定です。Vue.jsみたいなもので画面全体を作り変えたい … という方がいらっしゃればモックを作ってみてください。

コメントはまだありません

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です