読書メモ:アーキテクトの審美眼

最近読んでいる本のメモ

アーキテクトの審美眼 (DBMagazine SELECTION)

アーキテクトの審美眼 (DBMagazine SELECTION)

  • 作者:萩原 正義
  • 発売日: 2009/03/03
  • メディア: 単行本(ソフトカバー)

本の概要

読んで印象に残ったこと

ソフトウェアは複数のアーキテクチャから成るレイヤ構造をしている

  • ソフトウェアを構成するアーキテクチャ
    • 概念モデル
    • クラス図
    • データモデル(ER図)
  • 各レイヤは隣接するレイヤと相互的な関係を持っている
    f:id:smatsuzaki:20200827235030p:plain
    『アーキテクトの審美眼』P5 図1をもとに作成

トランザクションスクリプト VS ドメインモデル

f:id:smatsuzaki:20200829103353p:plain
P138 図1を元に作成

トランザクションスクリプトという概念は以下の本が確か初出で、より詳細に語られています

その他、印象に残ったフレーズ

分割し再び複合化する

  • 開発とは、問題領域を「分類/分割し、再び複合化する」営み*1 (P28)
    • よく使われる分類学としては、「もの(名詞, 実体)」による分類、「こと(動詞, 出来事)」による分類など

責務の配置

  • OOPでは各オブジェクトが特定の役割、振る舞いのみを担当する
  • その結果として、全体で見ると役割や振る舞いの重複が無くなり無駄の少ない構成になる状態のことを 責務の配置 と呼ぶ(P55)

関心の分離の原則

  • 関心 とは「システム開発者が何に一番価値をおくのか」の基準
  • 関心に基づいてシステムを分割していくことを「 関心の分離の原則 」と呼ぶ (P61)

*1 分類というのは、クリティカルシンキングで言うところの「軸」のような概念のようです。系統樹などのように「どのようにグルーピングするか」が関心の中心にあると理解しました

読書メモ:Team Topologies 第1章

本の概要

  • 企業のソフトウェア開発能力を支える、チームの構造の在り方を議論する本
  • 同じ会社の方に、欧米のDDD Communityで最近よく言及されると聞いて興味を持った

読書メモ

第一章

基本的な問題意識

  • 冒頭で、ソフトウェアを内製している企業が検討の対象としてあげられる
  • かつては以下の2つの間に一定のトレードオフが許容されたが今は両方を達成しなければならない
    • (1)アプリケーションの安定性
    • (2)進化する速度の速さ
  • 上記のチャレンジングな要求を達成するためには、安定してパフォーマンスを出し続け、かつ、適応的に進化し続けるチームが求められるが、それらの課題に対し効果的に寄与しない組織管理手法が今も使われている

コミュニケーションをマネジメントする手法

  • 著者はソフトウェア開発を効率的に営むためには、コミュニケーションの在り方を最適化することが重要と考えている
  • コミュニケーションの在り方を最適化するためには、部門などの組織構成が最適化されている必要があるが、組織図ではその達成は難しい
    • 組織図は実際のコミュニケーションのあり方を反映していない
    • ピラミッド型組織をイメージしてツリー図を書くが、実際は、組織図に現れない横のコミュニケーションが組織を駆動させている [1]
    • また組織図は組織の構造を静的に表現しようとするが、実際の組織におけるコミュニケーションはもっと相互作用により振る舞いを変える動的なものである。そういった側面が組織図では扱うことができない

では、どのようなモデルが必要なのか?

  • もっと外部環境の変化に対して適応的に成長し、姿を変え続けるチームを表現できるモデルが欲しい
  • 別の言い方をすると、チーム内/チーム間のコミュニケーションによる動的な相互作業を扱えるモデル

コンウェイの法則を活用すると、組織構造とソフトウェアアーキテクチャの関係性を扱うことが可能になる

  • コンウェイの法則は1968年にMel Conwayの論文にて提唱された

  • Microservice Architectureの流行により、コンウェイの法則の復権(復活)のようなことが現在進行形で起きている
  • 著者は、ソフトウェアーキテクチャとチームのアーキテクチャは相互に影響を与え合う不可分な要素と考える
    • コンウェイの法則はこれらの問題に対して重要な洞察を与えてくれる
  • ThoughworksのJames Lewisは コンウェイ・マヌーバ( Inverse Conway Manoeuvre ) という概念を発案した

認知負荷とコミュニケーション

  • 1人の人間が頭の中に保持・展開できる情報の量には限界がある。また頻繁にコンテキストをスイッチするとこれらの能力は短期的に消耗・劣化する。これらの能力を認知負荷と呼ぶ
  • 認知負荷は一般に広く知られた現象であるが、チームが処理可能な仕事の総量/キャパシティを計画する際にはなぜか考慮されない
    • チームの認知負荷のキャパを超えるまで、種々の複数の異なるコンテキストの仕事がアサインされ続ける。そして最終的にチームが機能不全に陥る
  • 上記を防ぐために何ができるのか?
    • 認知負荷をマネジメントの管理対象とし、チームにかかる認知負荷が一定レベルを超えないよう状態を維持する
    • また、コンウェイの法則を踏まえると、チームのアーキテクチャ→コミュケーションの流れ→ソフトウェアのアーキテクチャという依存関係がなりたつ

[1] こちらの本でも類似のテーマが扱われています
ワンミッション 米軍発、世界最先端の組織活性化メソッド

No data sources configure to run this SQLが消えない

環境

Intellij IDEA (Ultimate) 2020.1.3

問題1

  • IntelliJ内でSQLを書くと、 No data sources configure to run this SQL とのメッセージが表示される

原因

IntelliJからlocalのDBに接続する機能を設定していなかったために、メッセージが表示されていた。 localでMySQLを起動し、以下に従い View -> Tool Windows -> Database から接続設定を入力&Applyすることでメッセージの解消を確認。

問題2

  • 問題1の対処完了後に再びSQL文を見るとメッセージが、 Unable to resolve <table name> に変わっている
  • 実際に存在するテーブルにもかかわらずIntelliJに認識されていない

原因と対処

localのMySQLに接続しているのにもかかわらず、SQL DialectsがMySQLではなく、H2になっていたために、 テーブルの取得に失敗していた。

https://intellij-support.jetbrains.com/hc/en-us/community/posts/360007103039--Solved-Unable-to-resolve-table-name

File -> Settings > Languages & Frameworks > SQL Dialects にて、DialectsをMySQLに修正し、エラーメッセージが消えたことを確認。

UML:クラス図についてのメモ

前提

  • Javaで実装する前提で考える

クラス図

基本的な考え方

  • 1つの概念 = 1つのクラスと考える
  • 概念間の 関係(Relatioships) を明示的に記述することで、概念が指し示す意味をより明確にする

関係(Relatioships) の類型

  • インスタンスレベルのものとクラスレベルのものが存在する [1]
  • インスタンスレベル
  • クラスレベル
    • 汎化( Generalization / Inheritance ) : 継承, extends を使う時はこちら
    • 実現( Realization / Implementation ) : interface, implements を使う時はこちら

関係(Relatioships) の図での記述ルール

図1: 関係の図での表現ルール

関連(Association)

  • 1つの型のインスタンスともう一方の型のインスタンスをつなぐ線をリンクと呼ぶ
  • 2つの概念を線( Link ) で結びその関係性を関連名として記述する
    図2:関連名

SourceとTarget

  • 左側のクラス - 関連名 - 右側のクラスには、英語の 「主語(S) - 動詞(V) - 目的語(O)」 の関係がなりたつ
    • 例えば以下の図は、 「購読者は/雑誌を/購読する」 と読み替えることができる
    • 主語になる側を ソース (Source) , 目的語になる側をターゲット(target)と呼ぶ
      図3:SourceとTargetと関連名の関係性

実装パターン

  • 関連を実装する際は、 source 側のインスタンスtarget 側のインスタンスへのリンクを保持する、つまり参照型のフィールドを持つようパターンが多い [3]
    • とのことなので以下のようになる??
    • このように、あるインスタンスが別のインスタンスに対し参照を持つことを navigatable である、 navigtability がある、という
public class Source{
  private Target target;
  ...
}

多重度(Multiplicity)

定義

多重度の記載方法

下限値の考え方

脚注/参考

[1] Wkipedia上は、他にGeneralレベルのものがあるが割愛 https://en.wikipedia.org/wiki/Class_diagram#Realization/Implementation
[2] 『UMLモデリング入門』P60
[3] 『UMLモデリング入門』P61
[4] 『ダイアグラム別UML徹底活用 第2版』P59

JSONの仕様メモ

理解が怪しいので復習。

基本的な仕様

  • 正式名称はJavaScript Object Notation
  • 名前( name ) と値( value ) から構成されるメンバー(member)のコレクションであり、階層的なツリー構造を表現できる

メンバー(member)

オブジェクト( JSON Object )

  • オブジェクトは 順序のない key:valueペアの集まり
  • 波括弧 ( { ) で始まる 波括弧 ( } ) で終わる
  • 同じくsample data中の object_list の子要素の、 { "name": "Nick", "age": 18 } 及び { "name": "Andrew", "age": 49 } はオブジェクト形式

配列( JSON Array )

  • 配列は順序付けされた値の集まりであり、インデックスによるfetchが可能
  • [ で始まる ] で終わる
  • 以下のsample data中の要素は全て配列形式

sample data

{
  "country_list": [ "japan", "china", "us" ],
  "num_list": [ 123, 456, 789 ],
  "mix_list": [ "red", 456, null, true ],
  "array_list": [ [ 89, 89 ], [ 46, 49 ], [ 91, 22 ] ],
  "object_list": [
    { "name": "Nick", "age": 18 },
    { "name": "Andrew", "age": 49 }
  ]
}

sample dataの構造

参考資料

innodb誕生までの歴史的な流れと内部仕様

業務の中でMySQLのバックエンドとして動くinnodbについて集中して調べる機会がありました。 innodbの歴史的な背景と、innodbの内部的な仕様についてメモを残しておこうと思います。

ANSI SQL 92の話と、innodb独自の話は将来的に分けたい。

1. 前提条件

以下で解説の話は、 MySQL (innodb) かつトランザクション分離レベルが REPEATABLE_READ であることを前提にしています。 他のRDBMS、及びトランザクション分離レベルについてはスコープ外とします。

2. innodb誕生までの歴史

SQL92にてトランザクション分離レベルと Anomary が定義された。 その後、 論文 "A Critique of ANSI SQL Isolation Levels"*1 にて、新しいトランザクション分離レベルであるスナップショット分離が提唱された。

1981 MVCC

Philip A. Bermstein と Nathan Goodman による論文にて、Multiversion Concurrency Control (MVCC) のアイデアが提案された。*2

1992 SQL 92

トランザクション分離レベル及びそれと対となる Anomary の概念が ANSI/ISO standard SQL 92 で定義された。*3

1995 Snapshot Isolation

論文 A Critique of ANSI SQL Isolation Levels の中で、新しいトランザクション分離レベルである スナップショット分離(Snapshot Isolation) が提唱された。

参考 :A Critique of ANSI SQL Isolation Levels読んだ

2010 MySQL 5.5, Innodb

(スナップショット分離方式の実装として?)Multiversion Concurrency Control (MVCC) システムが搭載された、innodb 1.1が MySQL 5.5 のデフォルトのストレージエンジンとして採用された。*4

3. 主要な概念

innodbを理解するためのキー概念は3つある。

  • Anomary
  • トランザクション分離レベル (Transaction isolation level)
  • スナップショット分離 (Snapshot Isolation)

3.1. Anomary

SERIALIZABLE以外のトランザクション分離レベルを採用した場合に発生するconsistency的に問題のある状態を Anomary と呼ぶ。 SQL92では以下の3種類の Anomary が定義された。

  • Dirty Read
  • Non-repeatable Read
  • Phantom

その後、Fuzzy Read, Lost Update などが追加された。

上記で定義の Anomary はいずれも、「同一トランザクション内にてSELECT文を2回実行した結果に同じ結果が返されることを保証可能か?」という問題を扱っている。以下に具体例を示す。

  • 1回目と2回目でSELECTで得られるレコードの値が異なる
  • 1回目と2回目でSELECTで得られるレコードの行数が異なる

3.2. トランザクション分離レベル (Transaction isolation level)

wikipedia:トランザクション分離レベル

トランザクションは必ずしも安全に並列化できるとは限らない。そのためデータベース管理システムは各並行トランザクションが互いに影響を受けず分離された安全な範囲内でトランザクションを並行化する。あるいは、異常な振る舞い(anomalies)を起こしうる分離レベルが低い並行化を許容し、代わりに並行性を高めてトランザクション処理性能を上昇させる。 この安全性・一貫性と性能のトレードオフを生む、並行性トランザクションの分離具合がトランザクション分離レベルである

論文 : A Critique of ANSI SQL Isolation Levels

"(意訳) トランザクションを異なる分離レベルで実行することで、アプリケーション設計者は正確性とスループットトレードオフに対し複数の選択肢を持つことができます。 トランザクション分離レベルを低くすると、トランザクションの同時実行性能は高まりますが、トランザクションの実行結果が曖昧(fuzzy)になったり、データの整合性が失われるリスクがあります。"

3.3. スナップショット分離 (Snapshot Isolation)

スナップショット分離は "A Critique of ANSI SQL Isolation Levels" にて提案の新たなトランザクション分離レベルである。レコードの情報をバージョン管理し、各トランザクションで別個に保持することでロックの取得を回避しつつ複数SQLの同時実行を可能にする。いくつかの実装が存在あるが、innodbではMVCCが採用されている。詳細は後述する。

4. Innodbの仕様

innodb の内部的な仕様について話を進めていく。

  • REPEATABLE READ 時の Anomary 特性
  • B+Tree周りのデータ構造
  • トランザクションの実行エンジン
  • システムバージョン番号 (System version number)
  • ロック制御
  • 一貫性非ロック読み取りとロック読み取り

4.1. REPEATABLE READ時のAnomary特性

  • 一貫性非ロック読み取り実行時
    • スナップショット分離により、ファジーリード及びファントムリードを回避
  • ロック読み取り実行時

参考:Innodb 中 RR 隔离级别能否防止幻读?

4.2. B+Tree周りのデータ構造

innodb は B+Treeを採用している。*5 Primaryキーはクラスタ化インデックスとして構成される。Primaryキー以外にインデックスを持つカラムがある場合セカンダリインデックスとして構成される。*6

物理ページのデータ構造は下図のようになっている。*7

InnoDBの物理ページのデータ構造

InnoDB Lock Monitorでの同様のデータ構造を確認できる。

InnoDB Lock Monitorでの物理ページの表示結果
UPDATE が実行されると、更新対象の行をコピーした新しい行が作成される。更新前のレコードはロールバックセグメントに Undo log として格納され、新しく作成されたレコード内の db_roll_ptr カラムからポインタが張られる。そして、この機構によりMVCC / Snapshot Isolationが実現される。*8

INSERTしたレコードを2回UPDATEした時のデータ構造

ロールバックセグメント, Undo log周りの実装レベルの詳細なデータ構造はこちらのスライドで解説されているDELETE は一度論理削除として実行され、その後パージされる。 論理削除を実現するために削除済みフラグ的な特殊なビットが用いられる

InnoDB は内部的に、データベース内に格納された各行に 3 つのフィールドを追加します。6 バイトの DB_TRX_ID フィールドは、行を挿入または更新した最後のトランザクションに対して、トランザクション識別子を指示します。また、 行内の特別ビットが削除されたとマークするように設定されている場合、削除は内部的に更新として処理されます。 https://dev.mysql.com/doc/refman/5.6/ja/innodb-multi-versioning.html

4.3. トランザクションの実行エンジン

全てのトランザクションは、最終的に COMMIT または ROLLBACK される。

またinnodbでは、トランザクションの実行に際し Undo logロールバックセグメント(ロールポインタ)が利用されるレコード更新型アーキテクチャを採用している。

  • トラザクションID

4.4. システムバージョン番号 (System version number)

  • Innodbにおいて内部的に保持&トランザクション実行の度に採番されるトランザクションIDのことを システムバージョン番号(System version number) と呼ぶ
  • (恐らく)各レコードの trx_id 欄に格納される
    • 削除ビットが立っていない時は、「最後にINSERT または UPDATEを実行したトランザクション」を示す
    • 削除ビットが立っている時は、「最後にDELETEを実行したトランザクション」を示す
  • 単調増加する方式なので、システムバージョンの大小を比較することで、複数のトランザクション間の時系列的な前後関係を判定することができる

4.5. ロック制御

4.6. 一貫性非ロック読み取りとロック読み取り

  • SELECT 実行に際し、2種類の動作モードが存在する。いずれのモードが採用されるかにより SELECT にて読み取れるレコードの範囲(対象)が変わる
  • トランザクション内にてSELECT実行時に
    • FOR UPDATE LOCK IN SHARE MODE を使用の場合:ロック読み取り( Locking Reads ) が実行される
      • 共有(S) ロックを取得のレコードに対し、排他(X) ロックを取ろうとすると衝突したレコードのみ 排他(X) ロックに変わる?
    • 上記以外: 一貫性非ロック読み取り( Consistent Nonlocking Reads ) が実行される

4.6.1. 一貫性非ロック読み取り (Consistent Nonlocking Reads) / スナップショット読み取り(snapshot reading)

4.6.1.1 スナップショット

4.6.2. ロック読み取り (Locking Reads) / 最新レコード読み取り (current reading)

  • ロック読み取り (Locking Reads)の際は、MVCCは使われず従ってスナップショットも参照されない
    • 常に、最新レコードのみが取得される。そのために、current readingと呼称されることもある。
  • ロック読み取り (Locking Reads)を利用することで、LostUpdate Anomaryを回避することができる。(反面ロックを取るので並行処理の性能は犠牲となる)

*1:A Critique of ANSI SQL Isolation Levels

*2:Concurrency Control in Distributed Database Systems

*3:ANSI/ISO standard SQL 92

*4:"InnoDBMySQL 5.1が最初にリリースされたときから、2回アップデートが行われている。MySQL 5.1がGAになった後でいったんInnoDB Pluginバージョン1.0がリリースされたのだが、その名が示す通り既存の(ビルトインの)InnoDBと置き換えて利用するプラグイン形式のストレージエンジンであった。MySQL 5.5ではInnoDBのバージョンがInnoDB 1.1となり、ビルトインのストレージエンジンとなっている。" MySQL 5.5新機能徹底解説

*5:B+Tree index structures in InnoDB

*6:ソシャゲエンジニアの自分が開発に必須だなと思った知識(MySQL編)

*7: The physical structure of records in InnoDB

*8:MVCCとInnoDBでの実装について

*9:実践ハイパフォーマンスMySQL 第2版

図:TCP通信時のパケットの構造

  • 勉強会用に作成の資料より転載
  • 『基礎からわかるTCP/IPネットワーク実験プログラミング 第2版』P32の図を元に作成

f:id:smatsuzaki:20200717230846p:plain

innodbのインテンションロックとは何か

  • 複数粒度ロック( Multiple Granularity Locking ) というLocking手法をベースにした処理がinnodbに独自実装されている?
    • テーブルロック、行ロックなどのロックをかける対象の粒度のことを ロック粒度( locking granuality ) と呼ぶ事がある。複数粒度ロッキングでは、複数の粒度を使い分けることができる ※1
    • 要するにロックをかける範囲をできるだけ狭くしたい。テーブルロックなどは避けたい
  • こちらの資料が比較的わかりやすい
  • RDBMS解剖学』P118 に記載のツリープロトコルの同じ方式を指している?

※1 『RDBMS解剖学』P110

innodb lock monitor

InnoDB lock monitorの有効化方法 (mysql 5.7以降??)

  • 以下を実行後、 SHOW ENGINE INNODB STATUS\G
set GLOBAL innodb_status_output=ON;
set GLOBAL innodb_status_output_locks=ON;

ロック種別の一覧

InnnoDB Lock Monitor上の表記 ロック種別
lock mode S ネクスキーロック(共有)
lock mode S locks gap before rec ギャップロック(共有)
lock mode S locks rec but not gap レコードロック(共有)
lock mode X ネクスキーロック(排他)
lock mode X locks gap before rec ギャップロック(排他)
lock mode X locks rec but not gap レコードロック(排他)
lock mode X insert intention インテンションギャップロック(排他)

Innodb Lock Monitorの読み方 [1]

  • innodbにおいて、クラスタ化インデックスを構成する各リーフノードは、以下から構成される。[2]
  • 上記の点を押さえておくと、ロックされたレコード一覧に表示されるデータ構造の意味が読み取りやすい。
  • supremum については、こちらの記事 が詳しい

f:id:smatsuzaki:20200717224941p:plain

参考文献

[1] トランザクション分離レベルの勉強記録(3) innodb_lock_monitorのTRANSACTIONS部分の読み方
[2] 『実践ハイパフォーマンスMySQL 第2版』P118-119

トラブルシュート:Codecovにjacoco.xmlをuploadしてもTestCoverageが表示されない

問題

  • local環境で mvn test を実行し生成されたjacoco.xmlbash <(curl -s https://codecov.io/bash) によりuploadしても、Codecov上にTestCoverageが出力されない
  • Codecov上でuploadの結果画面を見ると以下のようにエラーとなっている

f:id:smatsuzaki:20200612011835p:plain
uploadの結果画面(エラーが出ている状態)

対処

SQL: CASE式の練習

以下の本を読んでいて、CASE文/式というものがあるのを知ったので試してみます。

対象となるテーブル

mysqlがEXAMPLE DATABASEとして提供しているWorld Database を使用します。

mysql> select * from city where CountryCode='USA' limit 5;
+------+--------------+-------------+--------------+------------+
| ID   | Name         | CountryCode | District     | Population |
+------+--------------+-------------+--------------+------------+
| 3793 | New York     | USA         | New York     |    8008278 |
| 3794 | Los Angeles  | USA         | California   |    3694820 |
| 3795 | Chicago      | USA         | Illinois     |    2896016 |
| 3796 | Houston      | USA         | Texas        |    1953631 |
| 3797 | Philadelphia | USA         | Pennsylvania |    1517550 |
+------+--------------+-------------+--------------+------------+
5 rows in set (0.01 sec)

CASE文による串刺し集計

↑のテーブルに対し、CASE式を使うことで、国ごとの串刺し集計ができます。 以下の例では、 CountryCode フィールドの値が USA のものは「アメリカ」、 IND のものは「インド」、それ以外の値をもつ地域は「その他」として Population フィールドの合計値を集計しています。

SELECT
    -- CASE式
    CASE CountryCode    
        WHEN 'USA' THEN 'アメリカ'
        WHEN 'IND' THEN 'インド'
        ELSE 'その他'
    -- ENDで終了する
    END AS country,
    SUM(Population)
FROM
    city
GROUP BY
    country
;

実行結果

mysql> SELECT CASE CountryCode WHEN 'USA' THEN 'アメリカ' WHEN 'IND' THEN 'インド' ELSE 'その他' END AS country, SUM(Population) FROM city GROUP BY country ;
+--------------+-----------------+
| country      | SUM(Population) |
+--------------+-----------------+
| その他       |      1227635584 |
| アメリカ     |        78625774 |
| インド       |       123298526 |
+--------------+-----------------+
3 rows in set (0.02 sec)

余談

SQL文を整形したい時は、 SQLフォーマッターFor WEBが便利です。

f:id:smatsuzaki:20200607131719p:plain
SQL文をいい感じに整形してくれます

関連: SQLスタイルガイド

"predicate" とは何か

時々目にする、 predicate() という名称のメソッドの名前の意味が気になったので調べてみました。

概要

  • predicate は何らかの引数を取りbooleanを返す関数を意味する *1
  • predicate 関数は、典型的には、isEqualTo() , isBiggerTahn() のように与えられた引数が特定の状態を満たすか否かを判定し、満たす場合 True を返す

*1 プログラミングの世界において使われる場合の話。語学の世界では、主語(subject)に対しての述語(predicate)

具体例

参考

IntelliJ IDEAでブレークポイント実行しようとするとjdk8のライブラリにHITする

問題

f:id:smatsuzaki:20200605191033p:plain
java.util.zipにHITしている

原因

Java Exception Breakpoints の Suspend設定が有効になってしまっている。

f:id:smatsuzaki:20200605191207p:plain
Run -> View Breakpoints...(Ctrl + Shift +F8)で出せるブレークポイント一覧画面

対処方法

上記キャプチャの赤枠部分(Suspend)のチェックボックスを外したら、事象が解消されました。

小ネタ : Dockerfile内でARGをクォートで囲むと展開ができない

問題

Dockerfile内で以下のように、 ENV 内で呼び出しの ARG が展開されない。

Dockerfile

FROM centos:latest

ARG FOO=foo
ENV OPTS='foo=${FOO} \
 bar=bar \
 hoge=hoge'

環境変数の確認結果

# env | grep ^OPTS
OPTS=foo=${FOO}  bar=bar  hoge=hoge

原因と対処方法

  • Bashでは変数をシングルクォートで囲むと文字列として認識される
  • 変数を展開させたい場合は、代わりにダブルクォートを使用する

Dockerfile

$ cat Dockerfile 
FROM centos:latest

ARG FOO=foo
ENV OPTS="foo=${FOO} \
 bar=bar \
 hoge=hoge"

環境変数の確認結果

# env | grep ^OPTS
OPTS=foo=foo  bar=bar  hoge=hoge

参考:

Hello Dart

以下の記事を見て、Dartに興味をもったので入門してみました。

インストールは公式ページの手順通りに、brewで実施しました。

Hello World

$ cat helloWorld.dart 
main() {
  print('Hello World');
}

dart には、Optional parameters という引数の一部をオプショナル化 *1する機能も有るようです。試してみました。

$ cat hello.dart 
main() {

  // オブジェクトを初期化
  Hello hello = new Hello();

  // 引数を渡さないパターン
  hello.sayHello();

  // 引数を渡すパターン
  hello.sayHello("matsuzaki");

}

class Hello {

  // 引数を [] で囲むと、 optional positional parameters
  // という特殊なフィールドとしてマークされる
  // メソッド呼び出し時にoptional positional parametersが渡されない場、代わりにnullが入る
  void sayHello([String msg]){
    // ?? 演算子は左辺がnullの場合、右辺を返す
    print( 'Hello ' + '${msg ?? 'world'}');
  }

}

実行結果です。

$ dart hello.dart 
Hello world
Hello matsuzaki
/* https://sunrise033.com/entry/hatena-blog-how-to-hierarchicalize-categories */