valid,invalid

関心を持てる事柄について

Bootstrap3 要素の順番をレスポンシブに入れ替える

Bootstrap3 のグリッドシステムでは pull / push という要素を押し込む/引っ張るためのクラスが使える。これを使うことでレスポンシブに要素の順番を入れ替えることができる。

押し込む/引っ張ると言ってもわかりづらいので実例を見たい。

要素を入れ替える例

PC view

「戻る」が左、「すすむ」が右。一般的な構成。

f:id:ohbarye:20180225104646p:plain

Mobile view

モバイルで閲覧しているときには「すすむ」が上、「戻る」が下。これも一般的な構成。しかし要素の順番が PC と入れ替わっている。

f:id:ohbarye:20180225104654p:plain

コード

See the Pen push/pull with Bootstrap by Masato Ohba (@ohbarye) on CodePen.

PC view では右側にある「すすむ」が HTML では先に記述するのがポイント。この「すすむ」を col 6つぶん押し込む (push)。逆に後に記述する「戻る」を col 6つぶん引っ張る (pull)。

この組み合わせで順序が入れ替わる。また、おなじみの col-**- prefix でレスポンシブなマークアップができる。

TreasureData (Presto) で複数行をまとめて1行に集約

OracleLISTAGG, MySQLGROUP_CONCAT みたいなことを TreasureData (Presto) でやりたい。

答え

array_join と array_agg を組み合わせることで実現できる。

6.15. Array Functions and Operators — Presto 0.195 Documentation

  • employee : department = N : N
  • department_employee は中間テーブル

という前提で、素直に組み合わせをすべて選択すると以下のようになる。

SELECT
  e.id AS employee_id,
  e.name AS employee_name,
  d.name AS department_name
FROM
  department_employee de
     LEFT JOIN employee e ON de.employee_id = e.id
     LEFT JOIN department d ON de.department_id = d.id
ORDER BY 
  employee_id
;
   employee_id   employee_name          department_name
---------------- ---------------------- ---------------
         1       Rick                   Development
         1       Rick                   Sales
         2       Chris                  Development
         3       IOROI                  Sales
         3       IOROI                  Marketing
         3       IOROI                  HR

この結果を employee ごとにグループ化しつつ department_name も結合する形で select したい。

array_join と array_agg を組み合わせることで実現できる。

SELECT
  e.id AS employee_id,
  e.name AS employee_name,
  array_join(array_agg(d.name), ',') AS department_names
FROM
  department_employee de
     LEFT JOIN employee e ON de.employee_id = e.id
     LEFT JOIN department d ON de.department_id = d.id
GROUP BY
  employee_id,
  employee_name
ORDER BY 
  employee_id
;
   employee_id   employee_name          department_names
---------------- ---------------------- ---------------
         1       Rick                   Development,Sales
         2       Chris                  Development
         3       IOROI                  Sales,Marketing,HR

YAMLのAnchorとAliasを使ってconfigをDRYに書く

あらすじ

  • ふだん無意識に読み飛ばしているが使おうと思ったときに出てこなかった
  • YAML の anchor と alias を使うと色々 DRY に書ける
  • DRYに書いた

Anchor/Alias

YAML では &name (Anchor) で名前をつけて *name (Alias) で参照することができる*1

Example1: 重複排除

こんな感じの CircleCI 用の config.yml。

version: 2
jobs:
  bundle_npm_dependencies:
    docker:
      - image: circleci/node:8.7.0
    steps:
      - checkout
      - restore_cache: # <= 1つめ
          keys:
            - key-name-{{ arch }}-{{ .Branch }}-{{ checksum "yarn.lock" }}
            - key-name-{{ arch }}
      - run: yarn install --pure-lockfile
      - save_cache:
          key:  key-name-{{ arch }}-{{ .Branch }}-{{ checksum "yarn.lock" }}
          paths:
            - node_modules

  test:
    docker:
      - image: circleci/node:8.7.0
    steps:
      - checkout
      - restore_cache: # <= 2つめ
          keys:
            - key-name-{{ arch }}-{{ .Branch }}-{{ checksum "yarn.lock" }}
            - key-name-{{ arch }}

  deploy:
    docker:
      - image: circleci/node:8.7.0
    steps:
      - checkout
      - restore_cache: # <= 3つめ
          keys:
            - key-name-{{ arch }}-{{ .Branch }}-{{ checksum "yarn.lock" }}
            - key-name-{{ arch }}
      - deploy:
          command: ./scripts/${CIRCLE_JOB}.sh

中身はともかく restore_cache のステップが複数箇所存在する。キャッシュを invalidate するために key name を変える場合は3箇所漏れ無く更新しないといけない。

これを anchor & alias 使い、初出箇所で参照可能にする。

version: 2
jobs:
  bundle_npm_dependencies:
    docker:
      - image: circleci/node:8.7.0
    steps:
      - checkout
      - restore_cache: &restore_cache # <= anchor 作成
          keys:
            - key-name-{{ arch }}-{{ .Branch }}-{{ checksum "yarn.lock" }}
            - key-name-{{ arch }}
      - run: yarn install --pure-lockfile
      - save_cache:
          key:  key-name-{{ arch }}-{{ .Branch }}-{{ checksum "yarn.lock" }}
          paths:
            - node_modules

  test:
    docker:
      - image: circleci/node:8.7.0
    steps:
      - checkout
      - *restore_cache # <= 参照

  deploy:
    docker:
      - image: circleci/node:8.7.0
    steps:
      - checkout
      - *restore_cache # <= 参照
      - deploy:
          command: ./scripts/${CIRCLE_JOB}.sh

宣言箇所がわかりづらいのでファイルの先頭にまとめたりする。

version: 2
anchors:
  - cache_key: &cache_key key-name-{{ arch }}-{{ .Branch }}-{{ checksum "yarn.lock" }}
  - restore_cache: &restore_cache
      keys:
        - *cache_key
        - key-name-{{ arch }}
  - image_name: &image_name circleci/node:8.7.0

jobs:
  bundle_npm_dependencies:
    docker:
      - image: *image_name
    steps:
      - checkout
      - *restore_cache
      - run: yarn install --pure-lockfile
      - save_cache:
          key: *cache_key
          paths:
            - node_modules

  test:
    docker:
      - image: *image_name
    steps:
      - checkout
      - *restore_cache

  deploy:
    docker:
      - image: *image_name
    steps:
      - checkout
      - *restore_cache
      - deploy:
          command: ./scripts/${CIRCLE_JOB}.sh

Example2: 環境変数として定義した値を参照

CircleCI の environment で設定した環境変数を使いまわしたいとき。

# NG例
version: 2
jobs:
  test:
    docker:
      - image: image_name
        environment:
          ARTIFACT_PATH: "/tmp/artifacts"
    steps:
      - run: mkdir -p ${ARTIFACT_PATH}
      - store_artifacts:
          path: ${ARTIFACT_PATH}

shell command の中に書かれた値は変数展開されるが、そうでない箇所は当然ながらただの文字列として解釈されてしまう。JSON に parse するとわかる。

{
  "version": 2, 
  "jobs": {
    "test": {
      "docker": [
        {
          "environment": {
            "ARTIFACT_PATH": "/tmp/artifacts"
          }, 
          "image": "image_name"
        }
      ], 
      "steps": [
        {
          "run": "mkdir -p ${ARTIFACT_PATH}"
        }, 
        {
          "store_artifacts": {
            "path": "${ARTIFACT_PATH}" # <= ココ
          }
        }
      ]
    }
  }
}

こういうときにも anchor & alias は使える。

version: 2
jobs:
  test:
    docker:
      - image: image_name
        environment:
          ARTIFACT_PATH: &artifact_path "/tmp/artifacts"
    steps:
      - run: mkdir -p ${ARTIFACT_PATH}
      - store_artifacts:
          path: *artifact_path

値の一部として展開することはできないので run: mkdir -p *artifact_path はNG。

その他

  • Online YAML Parser 便利
  • そもそも YAML の仕様書ってどこにあるんだ => YAML™ Specification Index のようだが読む気が起きない
  • DRYに書いたからといって読みやすくなるわけではないことも多いので留意

*1:記号はC言語由来?

社員は「会社のために」「いつまでも」働くという欺瞞を葬る本『ALLIANCE 人と企業が信頼で結ばれる新しい雇用』

同僚から「"退職"に関する本ですよ…(暗黒微笑)」とスッと渡された本、『ALLIANCE 人と企業が信頼で結ばれる新しい雇用』を読んだ。

ALLIANCE アライアンス

ALLIANCE アライアンス

著者の一人リード・ホフマンは、リンクトインの創業者であり、ベンチャーキャピタリストとして様々なスタートアップを支援しており、「シリコンバレーヨーダ」の異名を取る重鎮的な存在です。 (Amazon レビューより引用)

とのことで、随意雇用*1が慣例のアメリカ、その中でもシリコンバレーを前提にした議論が展開されている。特に環境変化・事業の栄枯盛衰・人材流動が激しいとされるシリコンバレーで成功企業が多く生まれる要因の一つとして、企業と個人は信頼関係で結ばれるべきという考え方が浸透していることを本書は指摘する。

『ALLIANCE』を読んで「よーし弊社でもシリコンバレー式を完全再現しちゃうぞー」というのは法も雇用慣習も異なる日本では難しいかもしれない。また、企業と社員間のありかたは一人の思い込みで変えられるものではなくトップダウンで示さなければいけないと本書にはある。そうしたハードルが現実には存在するものの、企業と個人がどう繋がっていくべきかを考える材料・指針としては良い題材だと思う。

以下の3点は印象深かった点。

社員はいつまでもいてくれるわけではないと思え

個人的にはこの主張が最も気に入っている。"存在しない終身雇用を信じているふり"という欺瞞を葬れるかどうかが会社と個人の信頼関係を作る上で決定的な要因だからだ。

同書が提案する「コミットメント期間」という考えに基づけば、社員はコミットメントしたミッションをこなす一定期間を終えたら次のステップに進む、その前提で採用すべきということになる。

従業員の次の数年のステップが自社の可能性も勿論あるのでそうなるよう信頼関係を築かなければならない。しかし多くの会社は「優れた社員にいつまでもいてほしい」と思いつつ、その結果の囲い込みが信頼関係を壊している

就職活動をしているときによく見たのが「自分の成長ばかり考えていて」「応募動機に自分のことばかり」という企業本位の意見たち。成長意欲がありキャリア形成を真剣に考える応募者に対して見合う仕事・ミッションを交渉の中で提案できるかは会社の責任だ。

信頼関係がないから社員は転職活動を秘密にする

社員のキャリアを正直に話し合える信頼関係があるなら、自社と他社どっちがいいですかね〜という相談もできる。むしろキャリアを考えればこそ他社を推薦することもある。

「採用して研修して育ったと思ったらすぐ転職してしまう(#^ω^)」という不満もまた企業側の怠慢に思える。転職を止められないのも同様に、次のステップとして自社がふさわしくないと判断されていることを真摯に受け止めないといけない。

ネットワークに価値を置く

社員のネットワークは会社の事業にとっても採用にとっても価値となるということを示すべき。

  • 会社は信頼関係に基づく「卒業生」ネットワークを構築しよう
  • リファラル採用は現職員だけでなく卒業生からも見込める
  • 消費者でなく従業員目線での会社のブランドが存在する。これを高めよう

社内だけで問題を解決しようとするといずれ頭打ちになる。社内の合理性は社会の非合理ということはよくある。


以下、読書メモ。

「アライアンス」とは?

会社と個人の間のフラットで互恵的な信頼に基づくパートナーシップを指す。

互恵的というところが重要で、両者が相互に投資し合うことで事業の変革と個人の成長が同時に達成でき、会社も社員も満足度が高まる。

多くの会社の現状

  • 終身雇用は終わった
  • 個人に対して永遠に雇用を保障しようという誠実さを持った会社はほとんどいない
  • 社員を大事にするとか言っていても会社の本音は「優れた人だけに」「いつまでも」いてほしい
  • このあいまいな態度こそが信頼関係を壊す。社員側に忠誠を求めながら会社は何も約束しない
  • 社員もこのことを知っているからリスクヘッジをする。忠誠を疑われないように影で転職活動をする。チャンスがあればとびつく。転職したら現職との関係は終わり

処方箋

会社と個人は信頼関係に基づく「アライアンス」関係におく。

  • 個人は能力を提供し、会社は機会を提供する。自立したプレーヤー同士が互いにメリットを得るために結ぶ期間限定の提携関係。
  • 従業員が永久的に働くことを前提としていない、かつそれを両者が合意している。すなわち会社に閉じたキャリアプランやスキルを伸ばすことを強いられることもなければ、個人の市場価値を高めるための活動に制限や背徳がない。むしろ会社はそうした機会を提供する
  • 「ある程度長くいてくれるんですよね」「え、ああ、はい(^-^)」みたいな欺瞞がないからこそ個々人の「やりたいこと・やりたくないこと・なりたい姿・なりたくない姿」について忌憚なく意見を交わせる。誠実さは信頼関係をつくる

限定のこの期間を「コミットメント期間」と呼ぶ。

コミットメント期間

コミットメント期間には以下の3型が存在しする。期間の終了に伴い別の型へと移行する、またはキャリアの転向(転職)が発生する。

  1. ローテーション型:比較的代替可能なジョブに適用。会社との相性を見極めるのが目的。新卒の研修・OJTもここに含む。この期間終了後、変革型へ移行するのが通例だが、ミスマッチ解消のために転職してもまったく問題ない。
  2. 変革型:会社にとっては事業の、社員にとってはキャリアの変革をもたらすことが期待される。ミッションを完了する前に次のコミットメント期間のあり方を会社と相談する。まとまらなければ転職する。
  3. 基盤型:3種の中では特殊。個人のキャリアや人生と会社が密接に結びついているケースなので通常、期間は定められない。創業者、10年選手の経営層が代表的だが、組織の末端(CSリーダー、インフラ担当)でもありえる。

ミッションに応じて給与や具体的な職務内容が決まるので「マネージャーにならないと給料があがらない」はありえないし、高い給与に値するミッションを提供できないのは会社の責任となる。

ネットワーク情報収集力

社員が持つネットワークは会社に大きな力をもたらす。なぜなら社外には社内に存在するより遥かに多くの優れた頭脳が存在するからだ。

ペイパルはなぜビルポイントに圧勝したか

ペイパルは競合だったイーベイ+ビルポイント陣営に勝利できたのはこのためだと考えられている。ペイパルは営業からエンジニアに至るまで多くの社員のネットワーク情報収集力を最大限に用いたが、ビルポイントはこうした活動を行わなかったため顧客が本当に欲しかったものを見抜くことができなかった。彼らはそれが「銀行との提携による不正防止と安心感」だと考えていたがそれは衛生要因*2でしかなく、イーベイのプラットフォームを利用する企業とエンドユーザーはEメールでの簡易なやりとりといったUI/UXを重視していた。

ネットワーク情報収集力を強化する4つの手段

信頼関係を築けている社員はこれを最大限に活用してくれる。この能力を活性化・最大化させるには以下のような手段がある。

  1. ソーシャルメディアの活用を会社は社員に進めよう
  2. 業務中のTwitterを諌めない
  3. 無理に強要するとすぐばれる。社員が結託して「弊社に遊びに来ませんか?」などと一時に言い始めると「そういうのを強要される会社なのか」と怪しまれる
  4. ネットワーキング予算を設ける
  5. 社外の面白い人とランチをする場合は会社が費用負担する。ただしレポート必須
  6. 社員による講演会を設ける
  7. 自社オフィスでイベントを開催する

これらはいずれも有効だが活用されなければ意味がない。マネージャーたちが積極的にこの制度を活用するとともに、面談を通じて社員に重要性を説く必要がある。「この活動はあなたのキャリアにとっても非常に有益なものですよ」と。

「卒業生」ネットワークに投資すべき4つの理由

生涯続くアライアンス関係を作る。LinkedIn, Tesla, YouTube, Yammer, Yep, Space X…これらは皆ペイパルの「卒業生」が設立した。

残念がら辞めた社員との関係構築に注目している企業は驚くほど少ない。対称的に辞めた社員も過去の勤務先がどれほど自分のキャリアに影響しうるかをわかっていない。調査によれば64%の卒業生グループは自主的に結成され、卒業生同士での人脈づくりに使われる。これは会社にとってはメリットがほとんどないのだが、一歩はたらきかけるだけでとてつもないROIを生み出す。

  1. 人材獲得に有益。卒業生は社内のルールや文化を熟知しつつも社外の眼で会社を評価できる

    • 出戻り社員になる。卒業生の次のコミットメント期間は一度離れた会社で過ごすべきかもしれない
    • 採用候補者を紹介してくれる。文化に合う人間を卒業生が見極めてくれる
    • 紹介してくれた卒業生には謝礼を支払う
  2. 有力な情報を得られる

    • 同業他社に転職した元従業員からは業界のトレンドやニュースのみならず人材情報を得られる。
    • 卒業生を対象にしたアンケートを定期的に行うのもよい
    • 自社製品に対する批評をお願いするのもよい。社内の人間だと身内びいきのバイアスがかかってしまうが卒業生からは忌憚ない意見がもらえることがある
  3. 顧客を紹介してくれる

  4. ブランド・アンバサダーになってくれる

    • ブランドイメージを企業が完全にコントロールするのは不可能になっている。「あの会社はブラック企業だ」と一度名指しされればなかなか汚名は晴らせない
    • 反対に褒めてもらうことがあれば、いち消費者でなく従業員目線での会社のブランドを高まる

卒業生ネットワークにを活かすには「紹介ボーナス」「卒業生優待・割引」「自社開催イベントへの招待」「定期的な情報交換(メールでもよい)」などが挙げられる。

卒業生との信頼関係は在職中に作られるが、決定的となるのは退職時の面談だ。これを活かさない企業はダメ。

直近だとgrooves社の話が好例かもしれない。

*1:期間の定めのない雇用契約は雇用者・被用者のどちらからでも・いつでも・いかなる理由でも・理由がなくても自由に解約できるという原則のこと

*2:無いと不満だがあってもプラスにはならない要素

Bower は deprecated なので Yarn へ移行した

一度もまともに使ったことなかったけど bower って死んでたんだね…。正確にいうと "maintained, but deprecated" か。

github.com

snyk.io

自分には関係ない話かと思っていた…が、普段まったく触らないがひっそりと稼働を続けるレポジトリに2014年来の bower が残っているのを見つけてしまったので葬った。

構成

こんな感じの bower.json に依存性がガーッと書いてあって

# bower.json
{
  "dependencies": {
    "jquery": "~2.1.1",
    "backbone": "~1.1.2", # そう、backbone です…
    "marionette": "~2.0.2",
    "backbone.stickit": "~0.8.0",
    ...
  },
  "overrides": {
    "backbone.stickit": {
      "main": "backbone.stickit.js"
    },
    ...
  },
  "devDependencies": {
    ...
  }
}

dependencies のライブラリ群をまとめて concat して特定のパスに出力していた。

# gulpfile.coffee
gulp       = require 'gulp'
concat     = require 'gulp-concat'
bowerFiles = require "main-bower-files"

gulp.task 'vendor', ->
  gulp
    .src bowerFiles()
    .pipe concat('vendor.js')
    .pipe gulp.dest('./app/assets/javascripts/vendor')

migration

依存性管理を yarn へ

まず依存性管理を yarn に移す。

bower.jsondependenciesdevDependencies を package.json に移動する。一個一個 yarn add してもいいのだが、version はなるべくキープしたかったのでそのまま。

bower.json は削除する。

# package.json
{
  "dependencies": {
    "jquery": "~2.1.1",
    "backbone": "~1.1.2",
    "backbone.marionette": "~2.0.2",
    "backbone.stickit": "~0.8.0",
    ...
  },
  },
  "devDependencies": {
    ...
  }
}

単にコピーした状態で yarn install を走らせると失敗した。主に以下の理由による。

  1. パッケージ名が bower と npm で異なる
    • npm で調べて置換する
    • importrequire を使っていたらそのパッケージ名も要編集
  2. 指定の version が存在しない
    • version 差異を少なくするため、最低の version を選んでおいた

ビルド周りの整理

gulpfile を修正する。

まず main-bower-files のような packege は yarn remove する。

gulp の src として、dependencies に含まれるライブラリのパスをちまちま書いていく。package.json 中の dependencies をうまく引っ張ってくるとか、もっと冴えたやり方がありそうだけど一旦これで。

# gulpfile.coffee
gulp       = require 'gulp'
concat     = require 'gulp-concat'

gulp.task 'vendor', ->
  libs = [
    "node_modules/jquery/dist/jquery.min.js"
    "node_modules/backbone/backbone-min.js "
    "node_modules/backbone.marionette/lib/backbone.marionette.min.js"
    "node_modules/backbone.stickit/backbone.stickit.js"
    ...
  ]

  gulp
    .src libs
    .pipe concat('vendor.js')
    .pipe gulp.dest('./app/assets/javascripts/vendor')

他にも "bower_components/..." 配下を参照しているパスがある箇所は全部 "node_modules/..." を参照するように置換した。

ビルド

この状態で gulp を走らせる。

アプリケーションは dest ('./app/assets/javascripts/vendor') の中身を読んでいるだけなので特に変更は必要なかった。

ここまでで CI に push したらテストも通った 😇 ということで即マージしてもらえた。

余談

終わった後に気付いたが yarn を使いつつ "bower_components./" を使い続けるソフトマイグレーションもできるようだ。

How to migrate away from Bower? · Bower blog

# 
{
  "dependencies": {
    "@bower_components/almond" : "jrburke/almond#~0.2.9",
    "@bower_components/angular" : "angular/bower-angular#^1.0.8",
    "@bower_components/d3" : "mbostock-bower/d3-bower#~3.3.10"
  }
}

可能ならまとめて葬った方が良いと思うが…。


しかしながら、bower ってなんで必要だったんだろうか…。2014年頃 npm にはフロントエンド周りのアセットがあんまり揃っていなかった、ということなんだろうか?

OSSに貢献してお金を得る

OSSに貢献して¥6,000ぐらい貰えたのでその話をする。OSSがお金になった話 · Dとはちょっと違う。

tip4commit

Tip4Commit — Contribute to Open Source というサイトがある。 このサイトに登録しているOSSプロジェクトそれぞれのビットコインアドレスに応援という名目で寄付 (donation) ができる。

これだけだといわゆる"投げ銭"サイトなのだが、面白いことに、OSSへの contributor に対して蓄積されたコインの一部が報酬として支払われるのだ。

支払われる額は積まれた投げ銭残高のN%。この割合はOSSの管理者が決定できる。例えば bitcoin-ruby*1 を見てみる。

f:id:ohbarye:20180114181055p:plain

現在の残高は 0.10365790 Ƀ、 支払った総額は 0.32204210 Ƀ、次回に支払われる額は 0.00103658 Ƀ とのことだ。

同サイトは4,5年前からあるらしく、2013年頃に数十円の気持ちで投げられたコインたちが今になっては何倍もの価値になり、報酬として支払われると思うと夢がある。しかし少し見渡してもそこまで高額の報酬を設定しているプロジェクトはなさそうなのでお小遣い稼ぎぐらいの気持ちでやるのがよさそう。

実際に報酬を得た話

まずこのサイトに sign up し、自分の bitcoin アドレスを登録した。

tip4commit 本体もこのサイトに登録していて報酬もまずまずだったのでバグか何かないかサイトを巡回していたが特にめぼしい物は見つからなかった。なので開発上の課題や直近の修正からチャンスを得るべく GitHub ページ https://github.com/tip4commit/tip4commit/pulls を見てみると、最近になって Korean, Spanish, Indonesian ロケール対応をしており localization を歓迎している雰囲気があった。

余談だが、localization は最もとっつきやすいOSSコントリビューションチャンスだと思う。日本語・英語ともに多少の言語力が求められるものの高い技術力や対象プロジェクトのコンテキストへの深い理解が要求されることはあまりないからだ。

tip4commit は日本では全く話題にならなかったのだろうか、日本語対応がされていなかったので en.yml を見ながらガーッと翻訳を書きなぐって pull request を送ってみた。

github.com

これが27 days*2を経てようやくマージされ 0.00357757 Ƀ がマイページの残高として現れた!!!

f:id:ohbarye:20180114182459p:plain


雑感

どこであったか忘れたが、OSSへのコントリビューションに報酬が必要だろうか?という提言を思い出した。記憶が曖昧だが、「OSSは善意で回ってるんや〜」的観念、内発的動機づけ至上主義の立場からすると報酬は常に支払うべきでないという意見だった。ロウソク問題よろしく報酬に目がくらんだ低質な pull request が大量に飛びかい、結果としてOSS総体が悪い方向に向かうという危惧もわかる*3

このサイトの作者の真意は不明だが、上述のように報酬がバッドノウハウとして働くのを危惧するなら使わなければ良いし、選択機会を提供しているだけでも尊いと思う。報酬がなければ見向きもメンテナンスもされなかったプロジェクトが蘇るとか、OSSメンテナとしてコントリビュータに感謝ができるとか、そういう綺麗な話がもっと出てきて欲しい。

*1:bitcoin utils and protocol in ruby.

*2:OSS fatigue だろうか…

*3:実際、tip4commit に登録されたもののメンテナからのクレームで掲載落ちしたOSSプロジェクトもあるようだ。

『高い城の男』

もしドイツと日本が戦争に勝っていたら世界はこうなっていただろうか…という思考実験、平行世界もの。序盤を読み進める中で、第二次世界大戦前後の歴史に関する基礎的な知識がないと楽しみが半減してしまうと思って少しおさらいしてから読み始めた。

「もしも連合国が枢軸国に勝利していたら*1という歴史改変小説『イナゴ身重く横たわる』の著者、高い城の男に会いに行く」という終焉に向けて収束するメインストーリーはあるものの、無関係に言える登場人物が多く登場する群像劇になっている。人物の内面描写は多めだが行動原理や規範がずいぶんかけ離れた人ばかりで感情移入しにくく、幾分読みづらかった。物事がうまく進んでいそうなのになんだか結局ダメになってしまう…みたいな不能感の描写がバッドトリップぽくてそのあたりにそこはかとないSF感を見出すとやや楽しくなってくる。

Amazon Prime のドラマ版)も見てみようかな。

主題

本作の主題は"本物と偽物"、"選択と結果"というところにあると思った。「なんだか結局ダメになってしまう」とか「選択を間違えた」というようなネガティブマインドはこれと大きく関わっているし、展開される各々のストーリーに共通している。選択をするのにいちいち易経に頼る人物たち、自分の人生が自分のものではない、または世界が偽物であるような違和感…メタフィクションの感覚(ジュリアナは最後には易経を通して『イナゴ身重く横たわる』に描かれた世界こそが真実の世界だと知るわけだが)。

戦争観

『高い城の男』を読んで「やっぱり連合国が戦争に負けてよかったね〜〜〜」みたいな感想も見るがそれは違う気がするんだよな…。日本はそれほどひどくないものの、たしかに作中のドイツも扱いは結構ひどい。反ナチ派は粛清されているし、ナチズムが広がった世界はある種のディストピアだ。とはいえ必ずしもこうなりえただろうか?「勝たなければこうなっていたんだ」と現状肯定するのは戦勝国側の論理であって、敗戦やそれに伴う艱難辛苦の正当化や納得にはならないのでは。(まぁそこは主題ではなさそうなので読中はあまり気にならなかったがそういう感想を見かけたので)

ハイライト

あまりない


われわれの人生という、この恐ろしいジレンマ。なにが起こるにしても、それは比類のない悪にちがいない。では、なぜじたばたあがく? なぜ選択する? もし、どの道を選んでも、結果はおなじだとすれば……。

Read more at location 5606


どこか別の世界では、たぶん様子がちがっているだろう。もっとましだろう。善と悪の選択の道がはっきりしているはずだ。こんな曖昧な灰色の混合物ではないはずだ。しかも、もつれあった要素をほぐそうとしても、まともな道具さえない。

Read more at location 5613

*1:すなわち我々の現実世界