なにもわからない

気分で技術系の雑記を書きます

macOSX 向け dotfiles を Github Actions でテストする

macOS 環境が無料で CI が回せる時代になりましたね。16インチ MacBook Pro を買ったこともあって GitHub Actions で macOS 向け dotfiles をテスト&見直ししてみました。 案の定動かない処理もあったりして、やはりテストを定常的に回すのは効くなと思い知らされましたが、それにもいくつかハマりどころがあったので書いておこうと思います。

環境構築スクリプトを育てていると、どうしても今のPCの環境には適用できるけれど実は新規PCには適用できなくなっているということは起きてしまいます。まっさらな状態からセットアップすることはめったにありませんからね。具体的にはディレクトリのないところにsymlinkを貼るとか、セットアップの前の方で入れているツールを後の方で使っているのだけどPATHが通っていないとか、そういうケースです。

そこでCIを回しましょうという話です。最近、GitHub Actionsのmacos-latestでCIを回すようになりました。実際にCIを回したら、必要なディレクトリを作るのを忘れていたり、諸々通らないことが発覚しました。

itchyny.hatenablog.com

現状の設定ファイルを先に貼っておくと、こうなりました。

リポジトリと作業の様子はこちらです。

1. GitHub 上で YAML ファイルを initialize する

f:id:tamakiii:20191121211312p:plain

画面上から YAML ファイルが作れて PR も作れます。とりあえず PR を作ればテンションが上がるのでとりあえず作るといいと思います。 自分は Set up a workflow yourself から始めました。

help.github.com

2. デフォルトで HomeBrew やいくつかのパッケージがインストールされている

これは dotfiles をテストする目的ではあまり嬉しくないことですが、デフォルトで HomeBrew や git, node などがインストールされていました。 ちょっと困ったのが、Brewfile で brew node をインストールさせたい場合、brew node@12brew @node13 が衝突してコケてしまいました。 これはメインのスクリプトを動かす前にデフォルトでインストールされている node をアンインストールすることで回避しました。(brew uninstall node@12

==> Downloading https://homebrew.bintray.com/bottles/node-13.1.0.catalina.bottle.tar.gz
==> Downloading from https://akamai.bintray.com/58/5863d08b039c44d35a8343179cf93d495e1288efe2c669ccb77704a236e0e17b?__gda__=exp=1574272109~hmac=9967f775a1b5093bc37183b749e04921790fe0894fdec9d213efacd13b9c6ac8&response-content-disposition=attachment%3Bfilename%3D%22node-13.1.0.catalina.bottle.tar.gz%22&response-content-type=application%2Fgzip&requestInfo=U2FsdGVkX1-HgyW49y3C7roMUH2e6Ay__vYCfMAjNkaXbnNPwYSBlYuywDo6KSDP77-xzhgl2poWSbWyOqlhQXdPRm-Heaa85s3o5DAWzDspCV12Yu3lCCUO08p1ocfNZMtoImL1AsiYZ7xjt1rbgQ&response-X-Checksum-Sha1=7352019f912696f10f9cf7feaaad9c0e2666894f&response-X-Checksum-Sha2=5863d08b039c44d35a8343179cf93d495e1288efe2c669ccb77704a236e0e17b
==> Pouring node-13.1.0.catalina.bottle.tar.gz
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink bin/node
Target /usr/local/bin/node
is a symlink belonging to node@12. You can unlink it:
  brew unlink node@12

To force the link and overwrite all conflicting files:
  brew link --overwrite node

To list all files that would be deleted:
  brew link --overwrite --dry-run node

Possible conflicting files are:
/usr/local/bin/node -> /usr/local/Cellar/node@12/12.13.0/bin/node

3. キャッシュの有効サイズは 400MB

ライフサイクルはこのようになっているので、Workflow が成功するまではキャッシュが有効になりません。

  • ロックファイルからキャッシュキーを生成する(今回は ${{ hashFiles('Brewfile') }}
  • キャッシュキーからキャッシュの有無を探す
  • Workflow が成功したらポストプロセスが動いてキャッシュを圧縮して保存する

またキャッシュされる最大サイズは 400MB で、これを超えるとポストプロセスでキャッシュが保存されなくなります。

/usr/bin/tar -cz -f /Users/runner/runners/2.160.2/work/_temp/430ca3b6-c547-4cda-ae16-a5e6e998894c/cache.tgz -C /usr/local/Cellar .
##[warning]Cache size of ~722 MB (757155145 B) is over the 400MB limit, not saving cache.

HomeBrew の場合、キャッシュ対象はざっと見た感じ2つあり、ひとつが $(brew --cache)/downloads = ~/Library/Caches/Homebrew/downloads、もうひとつが /usr/local/Cellar です。 前者は install プロセスはスキップできませんが、download プロセスがスキップできます。ただし、40行ほどの内容でも 900MB 近くなってしまったため、post プロセスで保存される前にファイルサイズの大きいものから10件ほど削除することでキャッシュを効かせました。

gist.github.com

後者の /usr/local/Cellar なら 400MB を下回ってくれるのでは、と思いましたがこれも 700MB 超えでそのままではキャッシュに乗りませんでした。 キャッシュを効かせても Workflow ごとに5分ほどの実行時間を要しているので、あまりキャッシュは有効に使えなそうな雰囲気があります。

4. brew install が Host key verification failed. で死ぬ

main.yml から make -f brew.mk を叩き、brew.mk 内で brew install している場合は問題なく動くのですが、main.ymlmake -f brew.mk の間にひとつシェルスクリプトMakefile を挟むだけで Host key verification failed. fatal: Could not read from remote repository. で死ぬようになりました。 具体的なドキュメントは出てきませんでしたが、おそらくセキュリティ上の都合だと思われます。 解決策はなかったので諦めて間に何も挟まない形にしました。ci.mk と実機で叩くセットアップスクリプトを近い形にしておきたかったんですが、まぁ致し方ないです。

github.com

Selenium IDE は for each したりできるよ

ウェブブラウザのオートメーションツール Selenium には、Google Chrome / Mozilla Firefoxプラグインとして動く、最近開発が活発な Selenium IDE というものがあります。

その Selenium IDE には conditional logic and looping を実現する Control Flow と呼ばれる機能があります。

Selenium IDE comes with commands that enable you to add conditional logic and looping to your tests. This enables you to execute commands (or a set of commands) only when certain conditions in your application are met, or execute command(s) repeatedly based on pre-defined criteria.

docs.seleniumhq.org

何かと言うと if とか for each とか書けるよって話なんですが、まぁ当然 JavaScript の実行結果をイテレートできます。

JavaScript Expressions Conditions in your application are checked by using JavaScript expressions. You can use the execute script or execute async script commands to run a snippet of JavaScript at any point during your test and store the result in a variable. These variables can be used in a control flow command. You can also use JavaScript expressions directly in the control flow commands.

コツは execute script の、 Target には return 式を、Value には格納先変数を書き、変数を ${} で展開すること、くらいでしょうか。

f:id:tamakiii:20191121002629p:plain
Selenium IDE なるほどですね

もっとリッチなエディタがあれば RPA できそうですが(=Microsoft Power Automate に期待してます)、これだけでも人間が学習すればある程度使えそうです。実行環境を用意するのだけ面倒くさそう。

jq で特定条件にマッチする要素を置換する

こういった JSON.name == "Michel".attributes だけを置換して全体を出力したい。

/tmp
$ cat test.json
{
  "elements": [
    {
      "name": "John",
      "attributes": {
        "private": true,
        "last_login": "2019-11-01 00:00:00"
      }
    },
    {
      "name": "Michel",
      "attributes": {
        "private": false,
        "last_login": "2019-11-02 00:00:00"
      }
    },
    {
      "name": "Paul",
      "attributes": {
        "private": false,
        "last_login": "2019-11-31 00:00:00"
      }
    }
  ]
}

map(), select(), |=, //, . を駆使して実現できる。すごく雑に書くと

  • map() => .elements[] のような配列を map() する
  • select() => 条件に一致するものだけフィルタする
  • // => a // ba ? a : b と評価される演算子
  • . => イテレートしている要素

キモは //

A filter of the form a // b produces the same results as a, if a produces results other than false and null. Otherwise, a // b produces the same results as b.

This is useful for providing defaults: .foo // 1 will evaluate to 1 if there’s no .foo element in the input. It’s similar to how or is sometimes used in Python (jq’s or operator is reserved for strictly Boolean operations).

stedolan.github.io


これらは以下の様に組み合わせて使う。

# 条件にマッチしない場合 `.` (=`.attributes`) に置換する(≒何もしない)
/tmp
$ cat test.json | jq '.elements |= map((select(0)) // .)'
{
  "elements": [
    {
      "name": "John",
      "attributes": {
        "private": true,
        "last_login": "2019-11-01 00:00:00"
      }
    },
    {
      "name": "Michel",
      "attributes": {
        "private": false,
        "last_login": "2019-11-02 00:00:00"
      }
    },
    {
      "name": "Paul",
      "attributes": {
        "private": false,
        "last_login": "2019-11-31 00:00:00"
      }
    }
  ]
}

# 条件にマッチする場合 `elements[].attributes` を `[]` に置換する
/tmp
$ cat test.json | jq '.elements |= map((select(1).attributes |= []) // .)'
{
  "elements": [
    {
      "name": "John",
      "attributes": []
    },
    {
      "name": "Michel",
      "attributes": []
    },
    {
      "name": "Paul",
      "attributes": []
    }
  ]
}

そして特定条件時のみ .attributes を置換する

/tmp
$ cat test.json | jq '.elements |= map((select(.name == "Michel").attributes |= { private: true, last_login: "2222-22-22 22:22:22"}) // .)'
{
  "elements": [
    {
      "name": "John",
      "attributes": {
        "private": true,
        "last_login": "2019-11-01 00:00:00"
      }
    },
    {
      "name": "Michel",
      "attributes": {
        "private": true,
        "last_login": "2222-22-22 22:22:22"
      }
    },
    {
      "name": "Paul",
      "attributes": {
        "private": false,
        "last_login": "2019-11-31 00:00:00"
      }
    }
  ]
}

202X年もシェル芸は身を助けてくれそうです

man したい alpine ワンライナー

macOSLinux を跨って使うような Shell Script や Makefile を書く際に、オプションなど挙動の差をどう解決するか考えることがよくある。 そんなときにサクっと alpine を Docker で立ち上げて man を見るのに使えるワンライナーのメモです。

docker run --rm -it alpine ash -c 'apk add --update --no-cache man man-pages coreutils-doc && ash'

PAGER=less の方が慣れてるのであれば

docker run --rm -it -e PAGER=less alpine ash -c 'apk add --update --no-cache man man-pages coreutils-doc && ash'

alpine も他 Linuix ディストリビューションとちょいちょい動き違ったりするんですが、最近 alpine びいきなので(まぁ)。

linuxcommand.sourceforge.net

wiki.alpinelinux.org

linuxjm.osdn.jp

pkgs.alpinelinux.org

MySQL on Docker で MySQL init process failed.

$ docker-compose up
...
mysql_1  | MySQL init process in progress...
mysql_1  | MySQL init process in progress...
mysql_1  | MySQL init process in progress...
mysql_1  | MySQL init process in progress...
mysql_1  | MySQL init process in progress...
mysql_1  | MySQL init process failed.

以前、環境変数 MYSQL_HOST が悪さをするバグがあったらしいけど既に解消済みらしい。

開発時にいちいちホストOS からパスワードを入力してログインするのが面倒で /etc/mysql/conf.d/mylogin.cnf にこんな設定を書いていた

[client]
password="pass"

MySQL コンテナの初期化時に [client] が書かれていると init process filad. で落ちるのは既知の問題らしい(まぁそりゃそうだ)

パスワードを簡単にするのでもいいけど、~/.my.cnf は初期化プロセスに関係しないらしいので置き場所を変えてやればいい。root なのはご愛嬌

$ git diff docker-compose.yml
diff --git a/docker-compose.yml b/docker-compose.yml
index 1d974da..b09d973 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -32,7 +32,7 @@ services:
       TZ: Asia/Tokyo
     volumes:
       - .:/project:delegated
-      - ./docker/mysql/conf.d/mylogin.cnf:/etc/mysql/conf.d/mylogin.cnf
+      - ./docker/mysql/my.cnf:/root/.my.cnf
       - ./docker/mysql/initdb.d:/docker-entrypoint-initdb.d
       - mysql:/var/lib/mysql
     security_opt:

データボリュームの初期化はこう

docker-compose down --volumes mysql

init process するスクリプトの本体はこの辺 github.com

他にもタイムアウト伸ばしたら?とか、メモリ足りないんじゃない?とかいう話もある

Amazon Linux 2 on Amazon Workspaces

手順は classmethod の記事を見つつポチポチと。 メールが届くまで20分ほどかかるのと、パスワードポリシーに合っていないと気づきにくい点だけアレ dev.classmethod.jp

動いたの図 f:id:tamakiii:20180627224015p:plain

Google Chrome のインストールは yumintoli.com

まだ全然手に馴染んでないけどキーボードの設定 f:id:tamakiii:20180627224004p:plain f:id:tamakiii:20180627224023p:plain f:id:tamakiii:20180627224201p:plain

ajito.fm/23 を聴いて:「学びの話」「講演の話」

ajito.fmVOYAGE GROUP の社内バー AJITO の名を冠したテック系 Podcast です。

今週公開された最新話の23回では、テストの伝道師で講演者としても知られる @t_wada さんが、プレゼンテーションや講演の作り方などについて話されていました。 こんなに価値のある情報を開けっ広げにしていいのか?!と思える内容だったので、個人的にその内容を文字起こししてみました。

(t_wada さんは既に何度かご登場されていて、金言がバンバン出るのは毎回なのですが。ぜひ過去回も聴いてみてください)

ajito.fm


目次

  • 学びの話
    • 新入社員研修
    • t_wada さんの学び方の変化
    • 「教える」ことから得られる学びは多い
    • 「教える」を避けるのはもったいない
    • 類似の情報であっても情報発信には価値がある
    • 「ゴミエントリー」にしない工夫
  • 講演の話
    • 「技術選定の審美眼」
    • 講演の準備/資料の作り方とコツ
    • プレゼンテーションの基本
    • 聴く人の明日がどう変わるかに力を込めろ
    • 「PHP7 で堅牢なコードを書く」
    • 「PHP7 で堅牢なコードを書く」の作り方
    • 講演のコツ
    • 資料が独り歩きを始めても講演の目標が達成できるかまで考えたい
    • 「技術力の審美眼」は直前まで名前や構成を練ることに時間を使った
  • 過去回
    • リンク

学びの話

新入社員向研修

  • 春は新人研修の公演依頼をされることが多い
  • 「勉強の学び方を学ぶ」みたいなメタな話
  • プログラマ・エンジニアとして生きる=「ずっと勉強し続ける」ということ
    • 自由になる時間は年々減って行く
    • 学習自体を効率化できないと自分が積んでしまう時がやってくる
  • どうやって効率的に学びを続けて行くか?
    • メタな視点だと「勉強の仕方を勉強する」
    • 教育学とかにヒントがある

t_wada さんの学び方の変化

  • 「フィードバックサイクルをうまく構築して回せれば学びは上手く行く」 と経験的に気づいた
    • アウトプットするとインプットがよりやってくる
    • ブログ記事を書くとインプットがやってくる
    • 勉強会で発表すると、次のインプットやアウトプットに繋がって回って行く
  • 世の中に出て発表とかを始めたら、それが自分の勉強になることに気づいた
  • 経験的に学んだことを整理して「こうするとうまく学びが回るかもしれないよ」ということをやっている

「教える」ことから得られる学びは多い

  • WEB+DB PRESS Vol.102 でペアプロの記事を書いた
  • ペアプロで経験や技能の差があるとき、上の人にメリットはあるか?
    • すごくある。 教えてる側の方がずっと学んでる
    • 「教えることは最大の学びである」色んな人が言っている(ファインマンさんとか)
  • 再整理してリフレーズしないと教えられない
    • 自分の知識の整理になる
  • 大学受験のテクニックの一つ=「塾の講師のアルバイトをする」
    • 知識が体系化されて再整理される

gihyo.jp

ご冗談でしょう、ファインマンさん〈上〉 (岩波現代文庫)

ご冗談でしょう、ファインマンさん〈上〉 (岩波現代文庫)

「教える」を避けるのはもったいない

  • "教える" と言うと「上から目線になっちゃう」と考えちゃいがち
    • 自分が分かること/知ってることを、話すとか、伝えるとかでいい
    • ブログエントリーでもいいし、Qiitaのエントリーでもいいし
    • 自分の言葉でアウトプットしてみる
  • 「自分は教える立場にないレベルにない」という感情をセーブしたり捨てるのが大事
    • 実は自分が一番勉強になってるじゃん、というのを体験してほしい
  • 自己評価の不思議な低さみたいなものは、アウトプットとインプットのループが回らないので勿体無いなぁと思っている

類似の情報であっても情報発信には価値がある

  • 類似の情報があっても今日情報発信することには価値がある
    • ある OSS の作者が ver.1.0 のリリース時にブログ記事を書いたとする
    • 「何故作ったのか」「何を解こうとしているのか」とか、"なぜなに" は当人しか書けないかもしれない
    • もしそれが4年前のブログエントリーだったりとかしたら、いまこれ動くのか?
  • 現代のソフトウェアを構成しているコンポーネントの数は多いので端々から壊れて行く
    • 皆が再体験するのではなく、小さな地雷みたいなのを除去してゆくエントリーには価値がある
  • 論文の世界ではやっぱり新規性が大事。工学や実学の世界では実用性が大事。
    • もちろん、エンジニアリングの世界であっても一番先に情報を出すのは尊い
  • 「今日では別の要素が出てきたので有用ではありません」という内容も有用
  • なので 類似の情報であっても、それを世に出すことに後ろ向きにならないで欲しい

「ゴミエントリー」にしない工夫

  • エントリーの信頼性を高めるには情報の抑え方が重要
  • 例えば
    • 詳細はむしろ省略しないで記す
    • バージョン情報を明記する
    • ひとつひとつの再現可能性を意識する
    • 再現可能なステップを意識する

講演の話

「技術選定の審美眼」

  • t_wada さんは、講演者としては再演の多い講演者
    • コミュニティでやったものの再演依頼が多い
  • 新作の題材の決め方
    • どんなテーマのイベントかとか、ある程度の方向性がある
    • 自分の持ってること、話したいこと、テーマの整合性を付けつつ作って行く
  • 講演していると再利用可能なページが増える
  • 「技術選定の審美眼」は完全新作
    • 実際にかかった期間は年末から本番まで3ヶ月くらい
    • スライドの組み立て大変だったのでは?
      • 難産だったし、プレッシャーが高かった
    • 時々、新人研修で技術の進化の歴史は振り子のように見えて螺旋なんだよという話をする
      • これについてフォーカスして話してほしいという依頼を承った
      • ヤバい、テーマがとても大きい、失敗したときもリスクも高いなぁと
    • 螺旋の話と、devsumi 2018テーマ「変わるもの×変わらないもの」を主軸に
      • 技術の歴史というのはある周期で繰り返しているように見えても完全な繰り返しではなく、決定的な技術の変化とかを経て進化しているもので、ベテランには揺り戻しがあるように見える、という話
  • 経験として、 やや背伸びした講演から得られる成長機会はとても大きい

speakerdeck.com event.shoeisha.jp

講演の準備/資料の作り方とコツ

  • 完成品としての講演の中身は、本番直前のテンションでまとまって行くもの
    • 資料が出来上がるのは直前
    • 体感的には時間の8割はメモしている時間
      • 本番の3ヶ月前に依頼をもらったとして、ネタ集めの期間が2ヶ月半
  • 公演資料を作るコツ=「講演資料を作り始めないこと」
    • スライド作りに着手するのは早すぎても遅すぎてもいけない
    • 特に大きめの舞台で講演するときは、いきなりプレゼン資料を作り始めないのが大事
    • 考えるべきはテーマ設定とかメッセージ
  • 発散フェーズが続く
    • simplenote に「デブサミ2018」みたいなノートを作って、何か思いついたものを全てそこに書いている
    • こんなことを喋れる、こんなことを喋りたい
    • 散歩してるときとか、本屋行ったときとかに思いつく
    • 体験として大きかったのは「大きめの本屋の技術書コーナー」
      • 古い本から新しい本まである、背表紙に技術の歴史が見える
      • イメージが湧く → ただひたすらメモを取る
  • 発散からだんだん収縮させて行く
    • ネタをひたすら集めると同時に、構成・骨組みを考える
      • 大事なメッセージは何だろうか?
      • 聞いて下さるお客さんに一番伝えたいのは?
      • 持って帰って貰えるものは?
  • 骨組みに合わせてパーツを当てはめて行く
  • 自分に合った道具を使う
    • 最近はスマホでメモしているけど、以前はスケッチブックでマインドマップでメモを書いていた
      • ふとしたときに思いついたときに、スケッチブックが手元になかったりした
      • とにかくメモを収集できるデバイス
      • すぐ忘れちゃう、基本的に単語だけ

simplenote.com atom.io

プレゼンテーションの基本

  • 参考にしてる本=『スティーブ・ジョブズ驚異のプレゼン』
    • タイトルも表紙も信者くさくて人に勧めづらいけど、中身はとってもよい
  • プレゼンテーションの基本=「ストーリーを作る、一番大事な問いに答える」
    • 抑えていないとどんな綺麗な資料でも外れだし、抑えていれば文字だけでもいい
    • そういった抑えるべきところを抑えている本
  • ディレクターズノートをいつでも見れるように書き出してあって、毎回穴埋めをする
    • ⇒ 各章の最後にあるその章のまとめみたいなもの
    • 第一章
      • 「構想はアナログでまとめろ」
      • 「プレゼンテーションソフトを開く前によく考えて流れを作ること」
      • 「アイディアは紙やホワイトボードに書く」
      • 「生き生きとしたプレゼンテーションとするため、以下の9要素からなるべく多くを取り入れること」
        • "ヘッドライン"
        • "ファッションステートメント"
        • "3つのキーメッセージ"
        • などなど
      • 「どのプレゼンテーションソフトを使うかではなく、どういうストーリーを作ってどう発表するかが一番大事だ」
    • 第二章
      • 「一番大事な問いに答える」
      • 「聞き手はなぜアイディアや情報・製品に注視を払うべきなのか自問する」
      • 「何故皆さんは自分の話を聞きに来る意味があるのかに集中しよう」
      • 「その選んだポイントを明快に伝えよう」

スティーブ・ジョブズ 驚異のプレゼン

スティーブ・ジョブズ 驚異のプレゼン

聴く人の明日からがどう変わるのかに力を込めろ

  • 技術の話をするのではなく、話を通じて聴く人の日々がどう良くなるか、どう改善されるか、何が大事なのか、何が嬉しいのか、といった立場に立って話をしよう
  • 講演の度に毎回考え直す
    • 話せそうなことを羅列すると、ただ自分が知ってることが羅列された資料になってしまう
  • 聞いた人がどうするのかが踏み込み不足になりがち
    • 聞いてもらえることによって、行動が変わるとか考えが変わるとか、何らかの影響をどう持って返ってもらうかに集中しよう
    • そういう観点で自分のメモ書きや資料を見直すと、ちょっと視点が違うとか足りないことに気づく
      • ディレクターズノートの穴埋めに立ち戻る
  • 意識しないとどうしても忘れがち
    • 自分ができていることを整理して資料にまとめる、というのは魅力的で引力を伴うのだけど、もう一歩踏み込んで
  • 何を伝えたいのかをよりシャープにするために、毎回穴埋めして作り直している
    • 今回の講演はキーメッセージができているかな?
    • この講演で明日は変わるだろうか?

「PHP7 で堅牢なコードを書く」

  • 実際の「防御的プログラミング」とか「表明プログラミング」とか「制約による設計」という概念を対応付けて説明したい
  • 「実例としてのコード」と「理論やテクニック・プラクティス」が分けて書かれてしまっている事が多い
    • 「制約による設計」というのはこういう考え方である、は書いてあるけど、実際にはどう書くの?
  • コードも合わせて読めるようにしたい
    • そこで、コードを十分に登場させながら、かつ書籍の引用を出典も含めて示しながら、全体を構成して行きたい

speakerdeck.com phpcon.php.gr.jp

「PHP7 で堅牢なコードを書く」の作り方

  • 「PHP7 で堅牢なコードを書く」の説明の仕方は、普段の雑誌とかの原稿の書き方と同じ
  • 最初にテーマ設定がある
    • 「(賢明なソフトウェア技術者になるための第一歩は)動くプログラムを書くことと、正しいプログラムを適切に作成することの違いを認識すること」(M.A. Jackson)
    • これをグランドテーマとした
  • 説明したい概念が多い
    • 「防御的プログラミング」「表明プログラミング」「制約による設計」
    • ある程度、説得力のあるサンプルコードが必要
      • サンプルがないと具体例として伝えにくい
    • サンプルコードは画面内に収めなければならない、という大きな制約がある
    • 時間的な制約もある
  • 言えることはたくさんある
    • 喋らなきゃいけないことは古典から引用できるので多い
      • どうやって説得力のある形でパッケージングするかが大事だった
    • サンプルコードを何パターンも作って、どれが無理なく流れを説明できるか、枝刈りをして行った
      • 「サンプルコードが成長して行く」を講演の骨組みにして、それに説明を散りばめて行くことにした
  • 結果的には SQL アンチパターンのより悪い形から始まってゴールに向かって行く構成になった
    • 「サンプルコードがだんだん良くなって行く様を追体験して、多くの人に理解してもらう」という方法が得意でよく用いる

Code Craft ~エクセレントなコードを書くための実践的技法~

Code Craft ~エクセレントなコードを書くための実践的技法~

講演のコツ

  • オープニングは重要
  • 聴く人に自分事だと認識してもらうのが大事
    • 自分のことであるとか、持って帰れるものがあるとか、"あるある" と思ってもらう
  • 一番最初に「なぜこの講演を聴く必要があるのか」を印象付けたい
    • 痛みを追体験してもらう/痛みを仮想的に体験してもらう
  • PHPカンファレンスでは、いきなりクイズを出した
    • ひどいコードを見せて「実行時例外の原因になる可能性があるのはどの行でしょうか?」「制限時間は10秒です」
    • 強制的に目の前の問題に皆さんに集中してもらう効果
  • 防御的プログラミングとかエラー処理がなされていないコードというのは、どんなコードでどういった痛みを伴うのか?
    • 経験のある人には分かるが、経験のない人は分からない
    • 最初の数分で「このひどいコードからこんなにエラーの可能性があるのか」を強制的に追体験してもらう
    • 一気に同じ船に乗ってもらう構成
  • 感情面での揺さぶりというか、共感とか一種の強迫観念とか、そういったものを喚起することで自分のスライドに乗っかってもらう
    • あるあるとか、これはつらいとか
    • そういったいろんな感情がでてくる
  • プレゼンの作り方ってあまり話さないし、あんまり自覚的にならない

プレゼンテーションZEN 第2版

プレゼンテーションZEN 第2版

資料が独り歩きを始めても講演の目標が達成できるかまで考えたい

  • 大舞台で話す場合、演者のパフォーマンスも含めてプレゼンテーション
    • プレゼンテーションを印象付けるのがとても大事
    • 大きな写真だけとか、文字だけとかのスタイルもある(ex. プレゼンテーションzen)
    • それは大舞台のその場にいる人に全ての価値を集中する、という講演と資料の設計
    • 今日のエンジニア・プログラマの講演/発表は本番だけじゃない
  • 資料は基本的にオープンに公開されるもので、公開されたものは喋りと切り離されて資料だけが独り歩きする
    • 画像1個だけだと詰んでしまう
    • 「印象のよくわからない資料だな」と思われてしまう
  • 勝負のときは少なくとも2つある
    • 「本番の壇上」と「後の資料公開」
  • 資料が独り歩きを始めても講演の目標が達成できるかまで考えたい
    • きちんと情報を伝えられるか
    • 多くの人にとって考える切っ掛けになるか
    • 行動を変えるか
  • 画や文字だけの資料は、場と演者が伴わないと情報が伝えられないので、公開資料には向かない
    • そういう資料を作りたいなら公開用資料は別途作りましょうという話になる

「技術選定の審美眼」は直前まで内容や構成を練ることに時間を使った

  • 「技術選定の審美眼」はまだ「喋りがなくても」の段階まで達していない
    • 再演を経て改善されて行くもので、まだ発展途上
  • 今回は普段使っている Keynote を使っていない
    • Keynote をバリバリ使ってるものと比べると、というのはある
  • Markdown からプレゼンテーションを生成するツールを使っている
    • 直前まで難産したのもあって、ギリギリまで作り込まずに文字情報としての内容や構成を練ることに時間を使いたかった
    • Keynote を最後まで開かずに、メモ書きをだんだんまとめていってツリー構造にして
    • それをプレゼンとして生成して、ちょっと CSS を書いて
    • みたいな感じで本番に至った

過去回

ajito.fm ajito.fm ajito.fm