設定ファイルの一部値を修正漏れが発生したことで、障害が発生した 経験は無いでしょうか。また、タイムアウト値等の連携システムごとに大きく変わらない設定値を記載するのを面倒に感じたことは無いでしょうか。
今回の記事では、YAMLのアンカー、エイリアス、マージ機能を使って、YAMLの反映漏れや記載内容の削減を目指します。
ゴール
設定ファイルから、下記2つのURLを生成します。アンカー、エイリアス、マージ機能を使って、設定ファイルをリファクタリングします。
http://localhost:80/twitter
http://localhost:10080/facebook
※ポートやエンドポイントは例です。
副次効果
設定値を纏められるので、数値の単位を揃えることができます。設定ファイルと実装は異なるので、単位が違っていてもいいですが、少なくとも混乱はしなくなります。
(例)
twitter: timeout: 3 # 3ミリ秒?3秒? facebook: timeout: 3000 # 3000ミリ秒?3秒?
アンカーとエイリアスを使って共通化
アンカー(Anchor)は変数宣言、エイリアス(alias)は変数使用です。
&を付与するとアンカーとなります。&timeout 3
と使用すると、timeoutという変数に3が設定されています。
*を付与するとエイリアスとなります。*timeout
と使用すると、3と置換されます。
下記例では、host
、protocol
、port
とtimeout
の値を共通化しています。
# 置換前のYAMLファイル external: twitter: host: localhost protocol: http port: 80 timeout: 3 endpoint: twitter facebook: host: localhost protocol: http port: 10080 timeout: 3 endpoint: facebook
# アンカーとエイリアスを使用して共通化したファイル external: common: host: &host localhost protocol: &protocol http port: &port 80 timeout: &timeout 3 twitter: host: *host protocol: *protocol port: *port timeout: *timeout endpoint: twitter facebook: host: *host protocol: *protocol port: 10080 timeout: *timeout endpoint: facebook
マージを使って共通化
アンカーとエイリアスでは変数の値のみを共通化しました。マージ機能を使用すると、変数のキーと値の両方を共通化できます。
マージ機能を使用するには、<<
とエイリアスを組み合わせます。
ただし、YAMLの仕様としては、マージという機能は定義されていないようです。なので、使用するライブラリでマージ機能が実装されているかどうかを確認してください。
下記例では、host: localhost
とprotocol: http
とport: 80
とtimeout: 3
を共通化した&common
というアンカーをマージしています。
また、Facebookのportを10080でcommonを上書きしています。
external: common: &common host: localhost protocol: http port: 80 timeout: 3 twitter: <<: *common endpoint: twitter facebook: <<: *common port: 10080 # 上書き endpoint: facebook
ブロックのアンカーとエイリアス
ブロックで定義したアンカーを使用する方法を記載します。次の設定ではtwitter
とtwitter2
は同一の設定がされています。
OpenAPIやSwaggerではエラーレスポンス、同一のパスパラメータを何度も定義することがあるため、アンカーとエイリアスを使いこなすことで、記載量を減らせます。
external: common: &common host: localhost protocol: http port: 80 timeout: 3 twitter: &twitter <<: *common endpoint: twitter twitter2: *twtitter
GitHubソースコード
YAMLの定義
https://yaml.org/spec/1.2/spec.html
JSONの定義
今回の記事とは関係ないですが、JSONを設定ファイルとしている場合も同様に共通化できないか調べてみたので残しておきます。結論としてはできないようです。
なので、JSONとYAMLを選択できる場合に、YAMLに軍配が上がるかと考えています。
ただし、個人的には読みやすさだけでいうと、YAMLの配列記述とか分かりづらいのでJSONの方が好きです。
終わりに
動けばいい、ということで設定ファイルは雑に扱われがちのように感じます。設定ファイルを雑に扱った結果、設定ファイルを読み込んで実装するプログラムはもっと雑になります。
この記事を読んだことで、設定ファイルのリファクタリングという別観点を植え付けることができれば幸いです。
もしこの記事が役に立ったのであれば、はてぶ、Twitterでの記事の拡散、Twitterのフォローもよろしくお願いします。
私の励みになります。
参考記事
CircleCIの「YAMLの記述」 circleci.com
フューチャー技術ブログの「一周回って、人間が読み書きする設定ファイルはJSONが良いと思った」 future-architect.github.io
類似記事
Javaでプロパティのテストを書く方法(こちらで動作検証しながら、リファクタリングしていました) nainaistar.hatenablog.com