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