2020年振り返り

2020年も終わりなので雑に振り返ろうと思います。 気が向いたら加筆修正するかも。

振り返りブログを書くのは初めてで、特に今年の目標とか置いていなかったのでまずは時系列で振り返っていきます。

1-3月: 大学院生活

修論を書いてました。

手法が Deep 系だったので重みのお気持ちを感じながら心が折れつつも書き上げました。 扱っているデータ構造が木になっていて、そのままネストした構造を Tensor にはできないので、SparseTensor なんかに変換しながら頑張ってました。 TensorFlow 上のグラフが途切れないようにモデルを構築するのが大変でした。 (出たばかりの tf2 を使っていたというのもありますが)

修論が終わった後も研究所ではデータをまとめたりプログラムを改善したりしていました。

3月の中旬に東京に引っ越し、Wantedly で内定者インターンとして早めに働き始めました。 Wanteldy People 開発チームで機能開発や品質改善をしていましたが、この時 Rails はおろか、Ruby も1㍉も書けませんでした (なんで雇ってもらえたんだ)。 メンターに Python みたいなものだよと言われたので初めて出した PR で if 文に and を使ったらレビューで怒られました。 PythonRuby も許せん。

その後、Rubyhttps://www.ruby-lang.org/ja/documentation/ を、Railshttps://railsguides.jp/ を読んで大体雰囲気を掴み、メタプログラミングRubyを読んで Ruby の構造について勉強したりしました。

4-12月: 社会人生活

無事社会人になれました。

People と Profile 系の開発をしていて、いくつかプロダクトのリニューアルに携わりました。

www.wantedly.com

www.wantedly.com

いくつかの機能は丸投げ設計から任せてもらえて結構楽しかったです。

あとは、社内イベントの運営とか Go Conference 仙台で出した TechBook の編集とか、インターン生のメンターとか色々やった気がする。

この1年で新しく学んだこと/挑戦したこと

施策設計 / データ解析 ( BigQuery )

グロース系のタスクでは施策設計のために BigQuery で分析作業なんかもしていました。 入社当時は生の SQL 書くと蕁麻疹出ますって感じだったんですが、かなり慣れました。 最近は毎日ガリガリ書いてます。やっぱり場数ですね。

施策自体の提案なんかももちろんしますが、プロダクトの深い理解が必要なのでまだまだです。 情報設計能力・問題の構造化能力はもっと伸ばしていきたい。

考古学

多分このスキルが一番伸びました。 先輩に「よく見つけてきたね」って30回くらい言われた気がする。

なぜそのコードが入ったのか、当時の背景も含めて Git, GitHub, Slack から議論を探し当てる方法についてはどこかでまとめたほうがいいのかも知れない。 ですが大事なのはちゃんと commit message や PR のコメントを書くことです。 未来のチームのためにちゃんと議論は残しておきましょう。

他分野の読書

自分の専門分野の本しか読んだことが無かったので、知見を広めるために10月くらいから本を読み始めました。 内容の咀嚼に時間がかかったりするのでまだペースは遅いです。

特に面白かったのは以下の2冊。

発信系

普段からあまり Blog は書かないのですが、今年は特に書いてないですね。 良くない。

おわりに

「これやりたいです!」って言ったら100%通るどころか、もう勝手にやっちゃって良いような会社にいるので、のびのびと楽しんで開発しています。 来年も色々なものに手を出していきたいです。

具体的な OKR みたいなのは年が明けたら考えます。

ではー。

普段使ってるツールとか

たまにインターン生に「なんですかそれ?」とか言われるので、普段使っていて便利なツールやTipsについて軽くまとめてみる。 これは16日目。

adventar.org

使っているPCはMac Book ProなのでmacOSが前提。

アプリ系

Alfred

www.alfredapp.com

めちゃくちゃ強いSpotlightみたいなやつ。

アプリの起動やファイル検索はもちろん、任意のWeb検索やClipboard Historyなど様々な機能が使える。 Hotkeyを登録しておけばいつでも起動できるので、Google検索とかは基本Alfred経由で行っている。

特に自分が特に便利だなと思っているのは以下の2つ。

  • Snippets
  • Workflow

Snippets

Snippets and Text Expansion - Alfred Help and Support

登録しておいたスニペットを貼り付けてくれる機能。
しかもただ登録した文字列を貼るだけでなく、Clipboardの内容を反映させたり貼り付けた後のカーソルの位置を指定できたりと、ちょっとした拡張性がある。

いつも同じようなもの書いてるなとか、このコマンド覚えるの面倒くさいなと思ったものは基本これに登録している。
ちなみに毎回書きたくないランキング堂々の1位はHTMLの折りたたみ表現。Markdown書いているときによく使う。

Workflow

Alfred Workflows - Extend Alfred and Boost Your Productivity

課金すると使えるようになる機能で、ユーザが定義した処理をAlfred上でコマンドを入力したり、割り当てたHotkeyを入力したりして起動することができる。
Workflowの中ではbashスクリプトが実行できるので本当になんでもできる。便利。

作ったWorkflowはimport/exportできるようになっているので、世の中には便利なWorkflowがたくさん公開されている。

自分がよく使うのは以下の3つ。

Display Menu

Display Menu

Display Menu

  • Milch im Gemüsefach
  • ユーティリティ
  • 無料
apps.apple.com

macOSの標準設定よりも色々な解像度が選べる。 限界を超えたいときにおすすめ。

見えねぇよって時はアクセシビリティのズーム機能を合わせて使うと幸せになれる。

Macでアクセシビリティの「ズーム機能」環境設定を変更する - Apple サポート

Moom などのウィンドウマネージャを入れておくともっと幸せになれるかもしれない。

Moom

Moom

  • Many Tricks
  • ユーティリティ
  • ¥1,220
apps.apple.com

Todoist

todoist.com

タスク管理ツール。

最初はTrelloを使っていたがApple Watchに対応していなかったのでこっちを使うようになった。

Getting Things Doneのお気持ちが大事。

Inkdrop

www.inkdrop.app

Markdown形式のノートアプリ。 プラグインVimキーバインドを使えるのがポイント高い。

自分は日々のタスクを雑にメモったりしているので、Active/Completedのステータスが標準機能で付けられるというのがとても良かった。

標準のメモ帳やBear, Evernote, Scrapboxなど、色々なものを試してみたがこれが一番しっくりきたので今の所ずっと使っている。

エディタ系

Vim

汎用エディタ。

気軽に使いたいのでプラグインとかはあまり入れていない。 カラースキーマ系とlsp系とfzf連携くらい。

Jetbrains IDE

専用エディタ。

色々試行錯誤しながらコードを書く時は基本的にこっちを使っている。 (なのでVimはなるべくシンプルにしている)

ここでもVimキーバインドを使いたいのでideavimプラグインを入れている。 たまーに使い勝手が悪いことがあるのでその時は.ideavimrcでちょこちょこいじっている。

GitHub - JetBrains/ideavim: Vim emulation plugin for IDEs based on the IntelliJ Platform

CLIツール系

ag

github.com

ファイル内の文字列をいい感じにgrepするツール。 便利。

ghq

github.com

リポジトリの取得・管理を便利にするツール。 便利。

使い方はこちら。

GitHub - Songmu/ghq-handbook

fzf

github.com

曖昧検索ツール。

など、何かしらの検索によく使う。便利。

他にも色々曖昧検索ツールは存在するが、僕はfzfのスコア計算が好きなのでこれを使っている。

tldr

github.com

「あのコマンドってどうやって使うんだっけ?」って思ったときに使い方のサマリを出してくれるツール。 ネットで調べたりmanを見たりしたくないときに便利。

❯ tldr curl

curl

Transfers data from or to a server.
Supports most protocols, including HTTP, FTP, and POP3.
More information: <https://curl.haxx.se>.

- Download the contents of an URL to a file:
    curl http://example.com -o filename

- Download a file, saving the output under the filename indicated by the URL:
    curl -O http://example.com/filename

- Download a file, following [L]ocation redirects, and automatically [C]ontinuing (resuming) a previous file transfer:
    curl -O -L -C - http://example.com/filename

- Send form-encoded data (POST request of type `application/x-www-form-urlencoded`). Use `-d @file_name` or `-d @'-'` to read from STDIN:
    curl -d 'name=bob' http://example.com/form

- Send a request with an extra header, using a custom HTTP method:
    curl -H 'X-My-Header: 123' -X PUT http://example.com

- Send data in JSON format, specifying the appropriate content-type header:
    curl -d '{"name":"bob"}' -H 'Content-Type: application/json' http://example.com/users/1234

- Pass a user name and password for server authentication:
    curl -u myusername:mypassword http://example.com

- Pass client certificate and key for a resource, skipping certificate validation:
    curl --cert client.pem --key key.pem --insecure https://example.com

gh

github.com

GitHubの公式CLIツール。 gh apiでv3, v4の任意のAPIが叩けるので何でもできる。 超便利。

その他

GitHubのファイル曖昧検索

docs.github.com

リポジトリのTopページでtを押すと使える。 便利。

GitHubでmentionするときにアイコン出してくれるやつ

chrome.google.com

基本的にアイコンで人を覚えているのでこれが無いと厳しい。

git log -S

差分の検索ができる。 便利。

終わりに

ペアプロ・ペアオペとかすると相手が使ってる便利ツールが知れて良いですよね。
自分がみんな知ってるでしょって思ってたツールも意外と知られてないことがあったりして驚くので、よく使うやつを書き出してみました。

でも流石にここらへんは知ってそう。

unexportedなmethodを持つGoのinterfaceとsum type

何か書けと後輩に詰められたので、寝る前に雑に調べごとをしてメモを残しておくことにする。 これは8日目。

adventar.org

Goのinterfaceに書けるメソッド名にはidentifierが指定されているだけで特に制限が無い。 つまり、unexportedなメソッドを定義することができる。

InterfaceType      = "interface" "{" { ( MethodSpec | InterfaceTypeName ) ";" } "}" .
MethodSpec         = MethodName Signature .
MethodName         = identifier .
InterfaceTypeName  = TypeName .

( https://golang.org/ref/spec#Interface_types より )

周りのコードを見渡してみると、例えば reflect.Type なんかはこれに該当する。

type Type interface {
  ...
  common() *rtype
  uncommon() *uncommonType
}

( https://github.com/golang/go/blob/ac0ba6707c1655ea4316b41d06571a0303cc60eb/src/reflect/type.go#L27-L214 より )

ちなみにgo docは通常exportedな情報しか表示してくれないが、-uをつけるとちゃんとunexportedの情報も見える。

こういったinterfaceはunexportedなmethodを持つため、(もちろんunexportedな型を返り値に持っているというのもあるが)パッケージの外でこれを満たす型を定義することはできない。

package foo

type A interface {
    Hoge() int
}

type B interface {
    Hoge() int
    piyo() int
}
package main

import (
    "fmt"

    "github.com/taxio/playground/foo"
)

type X struct{}

func (x *X) Hoge() int { return 0 }

func NewA() foo.A { return &X{} }

type Y struct{}

func (y *Y) Hoge() int { return 0 }
func (y *Y) piyo() int { return 0 }

func NewB() foo.B { return &Y{} }

func main() {
    fmt.Println(NewA())
    fmt.Println(NewB())
}
❯ go build
# github.com/taxio/playground
./main.go:20:28: cannot use &Y literal (type *Y) as type foo.B in return argument:
        *Y does not implement foo.B (missing foo.piyo method)
                have piyo() int
                want foo.piyo() int

調べてみるとこういうのをSealed Interfaceというらしい。 続けて「sum typeをエミュレートするのにも使える」と記述されている。

-- https://blog.chewxy.com/2018/03/18/golang-interfaces/
Sealed interfaces can only be discussed in the context of having multiple packages. A sealed interface is an interface with unexported methods. This means users outside the package is unable to create types that fulfil the interface. This is useful for emulating a sum type as an exhaustive search for the types that fulfil the interface can be done.

sum typeというのはどうやら代数的データ型というトピックの中で出てくるものらしく1、Tagged Unionなど様々な呼ばれ方があるらしい2 (wikipedia調べ)。

Tagged Unionで適当にggってると、TypeScriptの記事がよく目につく。

これはTypeScript 2.0で入った機能らしく、これを応用することでそれぞれのメンバが条件的に網羅されているかを検証できるらしい3。 確かに言われてみれば、switch文のdefault節の中にneverで網羅性をチェックするコードを書いた記憶がある。

凄い、知らない間に代数的データ型の恩恵を受けていたのか。 数学的なバックグラウンドは全く分からないので、今度会社の人に優しそうな型の入門書を聞いてみよう4

さて、こんな便利な機能がGoでも使える可能性があると分かったのであれば試すほかない。 先の記事で紹介されていたgo-sumtypeのREADMEを眺めながら手元で動かしてみる。

github.com

❯ go get -u github.com/BurntSushi/go-sumtype

サンプルのコードを少しいじって以下のようにしてみた。 構造体A,BはインターフェースXを満たす。

package main

import "fmt"

//go-sumtype:decl X
type X interface {
    sealed()
}

type A struct{}

func (a *A) sealed() {}

type B struct{}

func (b *B) sealed() {}

func NewXA() X {
    return &A{}
}

func main() {
    x := NewXA()
    switch x.(type) {
    case *A:
        fmt.Println("A!")
    case *B:
        fmt.Println("A!")
    default:
        panic("unreachable")
    }
}

この状態ではgo-sumtypeは怒らない。

❯ go-sumtype main.go

しかし*Aのcaseを除くと、

...
    switch x.(type) {
    // case *A:
    //     fmt.Println("A!")
    case *B:
        fmt.Println("A!")
    default:
        panic("unreachable")
    }
...
❯ go-sumtype main.go
~/go/src/github.com/taxio/playground/main.go:24:2: exhaustiveness check failed for sum type 'X': missing cases for A

しっかり条件が網羅されていないことを報告してくれた。

これを応用すればもしかして網羅的なerrorチェックみたいな面白いことができる...??? ( 眠い頭で適当なことを言っています。)

おわりに

パッと調べただけだったが、思ったより面白い話が見つかった。 もうちょっとちゃんと調べて年末の技術書典で記事を出そうかな。知らんけど。

ではおやすみなさい。

Goのiotaの正体

今までよく考えずに使っていのでメモ.

先日,会社のslackで以下のplaygroundがshareされた.

play.golang.org

雑に(0, 2, 4)かなぁと思いつつも(1, 5, 9)で無い確信もなかった. 実行してみると正解は,

A = 0
B = 2
C = 4

なるほど.

そもそもiotaってなんだっけ?とGoの仕様書を読みにいく.

golang.org

Its value is the index of the respective ConstSpec in that constant declaration, starting at zero.

なるほど,これって定数宣言の中の定数リストのindexだったのか. 今まで雑にiota使えばインクリメントされて〜みたいな意識だったので理解を改めた.

その上でさっきのコードや仕様に載ってるサンプルコードを読んでみるとなるほど確かに. そりゃそうなるわ.

const (
    bit0, mask0 = 1 << iota, 1<<iota - 1  // bit0 == 1, mask0 == 0  (iota == 0)
    bit1, mask1                           // bit1 == 2, mask1 == 1  (iota == 1)
    _, _                                  //                        (iota == 2, unused)
    bit3, mask3                           // bit3 == 8, mask3 == 7  (iota == 3)
)

改めて,他の言語仕様で培われた色メガネでGoの仕様を捉えてはいけないなと思った.

自戒を込めて.

味付け煮玉子を作る

あくあたん工房 Advent Calendar 2019 19日目

僕はラーメンが大好きだ.

大学の近くにはラーメン街1があり,友人に「ご飯行こうぜ」と言ったときに「ご飯」が示すものは99%くらいでラーメンである2

また,僕はラーメンだけでなく卵も大好きである.

ラーメンは麺,スープ,具材,そしてそれらの調和から美味しさが決まるが,そういえばこの具材の中に味付け煮玉子というものがいる.

ラーメンにのっている味付け煮玉子は最高だ.

天天有3のラーメンを食べる時なんて,まるでショートケーキのイチゴのようにいつ食べようかと悩んでいるものである.

ということで,この味付け煮玉子を自宅でも楽しみたいと思うのは必然である.

これはその備忘録.

調査

味玉の構成要素は大きく分けて,

  • ゆで時間
  • タレ
  • 漬け込み時間

の3つであると考える.これのいい感じの組み合わせを模索したい.

といっても普段自炊をしない僕は,美味しい味付け煮玉子の作り方なんて分からないので適当にggってレシピを見繕っていく.

ゆで時間

このサイトの早見表を参考に決定する.

kumiko-jp.com

半熟が好きなので7分でいいだろう.

タレ

適当にggって以下の2つを採用.

www.sirogohan.com

cookpad.com

また,色々なところで言及されていためんつゆも採用. この3種類で作っていく.

漬け込み時間

雑にggった感じ6時間くらいが良さそう.


以上の条件を決定した.

ところで僕は今(12/19)この記事を東京へ向かう新幹線の中で書いている.ぶっちゃけるとアドカレの準備をするのを忘れたまま京都を発ってしまったのである.

苦肉の策だが東京駅からの道すがらスーパーで卵と調味料を買って友人宅へと向かおう.

~ LINE ~

僕「君の家で味玉作っていい?」

友「え,なんで?」

調理

無事友人の家に付いたので「こいつ東京まで来て何してんの?」という視線を無視しながらさっそく調理を開始していく.

タレ作成

めんつゆ

使うのはこれ.

f:id:taxio:20191219200422j:plain
めんつゆ

3倍濃縮だがとくに薄めずこのまま使う.

和風ダレ

f:id:taxio:20191219200544j:plain
和風ダレ

醤油4,水3,みりん2,砂糖1の割合で混ぜる.参考記事では沸騰させていたが面倒くさいのでパス.

ちなみにこのレンゲは友人に「大さじ測るものない?」って聞いた時に渡されたやつ.

中華ダレ

f:id:taxio:20191219200750j:plain
中華ダレ

  • 醤油: 大さじ3
  • 砂糖: 大さじ1
  • ゴマ油: 小さじ1
  • ラー油: 適量
  • ニンニクチューブ: 適量
  • 生姜チューブ: 適量
  • お酢: 大さじ2
  • 鶏ガラ: 小さじ1

他にも白ゴマとか鷹の爪とか長ネギとかあったけど揃えるのが面倒だったのでパス

茹でる

f:id:taxio:20191219201131j:plain
茹でる

沸騰したお湯にそれぞれのタレに漬ける卵を投入. 1個割れちゃったので4つ入ってる.

7分経ったら冷水で冷やしながら殻を向いていく.

最後にジップロックにタレと茹で卵を入れて終了.

f:id:taxio:20191219201130j:plain
漬ける

6時間後へ...

...

...

...

完成・実食

6時間経った.さてどうなってるかな...

f:id:taxio:20191219201553j:plain
めんつゆ

f:id:taxio:20191219201621j:plain
和風ダレ

f:id:taxio:20191219201700j:plain
中華ダレ

見た目に差は無いが香りは中華ダレがとても良い.というか見た目に差が無さすぎて「これってめんつゆだったっけ?」って言いながら貼り付けてる.間違ってたらごめんなさい.

そんなことは置いといて,さて,味はどうだろうか.実食!!

f:id:taxio:20191219201828j:plain
味玉味噌ラーメン

先の通り,僕はあまり自炊しないので見かねた友人がササッと作ってくれた.マジありがてぇ.

味玉は左からめんつゆ,和風ダレ,中華ダレ.

以下食べてみた感想

めんつゆ

安定した味.いつだったか,金沢の友人の家に遊びに行った時に出してもらった味玉の味がする. 味が濃くてこれ単体で十分美味しい.

和風ダレ

めんつゆの後だと少し物足りない感じがする. しかしラーメンと一緒に食べるならこれくらいの濃さが良いのかもしれない.他の具材・スープの味を邪魔していない. ただ,水はもう少し少なくても良かったかもしれない.

中華ダレ

そこはかとない餃子感. 口に入れた瞬間の香りがいい. 濃すぎないのでこれもまたラーメンに合う.美味しい.

総評

めんつゆは濃くて美味しかったが,それ単体で完結していた. 何かの料理と合わせるなら薄くするか他の2つにした方が良さそう. 和風ダレと中華ダレは好みや状況で変わりそう.

自分が次ラーメンのためにつくるならちょっと濃い目の和風ダレかな.

感想

味玉美味しかったし,いきなり押しかけてきた人間にラーメン作ってくれる友人を持って僕は幸せ.

GC本を読む ~第2章 マークスイープGC~

ガベージコレクションのアルゴリズムと実装を読んだメモ第2弾.

この章から具体的なGCアルゴリズムの話に入っていきます.

マークスイープGC

1960年にJohn McCartyによって発表された最初のGCアルゴリズム1

基本動作

次の2つのステップによって死んだオブジェクトを再利用可能な状態にする.

  1. マークフェーズ
    • ミューテータのルートから辿れるオブジェクト(のヘッダ)全てに生きていると示すためのマークを付ける.
  2. スイープフェーズ
    • ヒープ全体をスキャンしてマークのついていないオブジェクトを回収する.

処理は至ってシンプル. スイープフェーズでは,$heap_startから$heap_endまで全てのオブジェクトのヘッダを確認している.

ゴミオブジェクトをどうやって回収するのかというと,使われていないオブジェクトの連結リストを作って,そこに追加していっている. p21の擬似コードでは,

sweeping.next = $free_list
$free_list = sweeping

と書かれており,単純に後ろに追加していっているのではなく,追加したオブジェクトがリストの先頭になるように追加していっている.(こうすることで連結リストの末尾を指すポインタが必要無くなるし,$free_listがNULLを指しているときの条件分岐も要らなくなる)

スイープフェーズ時にはただゴミオブジェクトをフリーリストに追加するのではなく,もし前に追加したゴミオブジェクト(既に開放された状態なのでチャンク)とメモリ空間上で連続しているなら,これらを1つのチャンクと見なすという処理をする.こうすることでチャンクが細切れになってしまうのを防ぐ.これを合体(Coalescing)と呼ぶ.

アロケーション時は,このフリーリストを探索して,必要なサイズ以上のチャンクを見つけ次第それを返す. この方式はFirst-fitと呼ばれ,他にはBest-fitやWorst-fitなどがある.

メリット・デメリット

メリットとしては以下の2つが挙げられている.

  • 実装が簡単
  • 保守的GCとの相性が良い

実装が簡単であるから,他のGCアルゴリズムと組み合わせやすいらしい.他のGCアルゴリズムは後の章で紹介されるので,この時点ではまだこのメリット達がどの程度良いのかは分からない.

デメリットとしては以下の3つが挙げられている.

  • フラグメンテーション(断片化)
    • GCを繰り返すうちにチャンクが細分化される
  • アロケーション速度
  • コピーオンライト(Copy-On-Write)との相性
    • ヘッダにmark情報を置いているため,GC時に書き換えが発生することで,そのプロセス用メモリへの全コピーが発生してしまう.

デメリットを解決するためのアプローチ

複数フリーリスト (Multiple free-list)

チャンクのサイズごとにフリーリストを分けておく.(本のリスト2.7のコードで指定のフリーリストにチャンクが余ってなかったときに上位のフリーリストを見に行かないようになっているのはバグかな?). これによって,基本 O(1)でチャンクが見つかるようになる.

BiBOP法 (Big Bag Of Pages)

ヒープ領域を分割し,特定のブロックに特定のサイズのチャンクを集中させる. これである程度フラグメンテーションが緩和される (完全に解決はしない).

ビットマップマーキング (Bitmap Marking)

オブジェクトのヘッダではなく,別のデータにそれぞれのオブジェクトのマークビットをテーブル形式でまとめる. これによってGC時にオブジェクトへの書き込みがなくなるのでCoWが働く.

遅延スイープ法

スイープ操作にかかる時間はヒープ領域のサイズに比例して大きくなる. これが大きくなるということは,ミューテータの最大停止時間が増えるということ.

遅延スイープ法は,アロケーションのときに欲しいサイズのチャンクが作れたところでスイープ操作をやめる.これによってミューテータの停止時間を減らしている.(次スイープ処理をするときは続きから見ていくのか?)

しかし,もしスイープ操作時に見ているオブジェクトが連続して生きているオブジェクトだった場合,そのサイズ分だけ停止時間が発生するため,一概にこれで解決するとは言えない.(むしろ生存オブジェクトが固まっているのは局所性の面で良いはず.) このスイープ処理で扱うヒープ領域のサイズを一定に保つ手法は8章で説明されるようだ.

次回

読んでる途中


GoのCLI勉強会を開催しました

先日,「GoでCLIツールを作る」というハンズオンを開催しました.

studioaquatan.connpass.com

参加してくださった皆さん,ありがとうございました.

経緯

  • 大学のコミュニティでGoを流行らせたかった
  • Go Conference Spring 2019などでいい感じの話を聞いた
  • CLIツールを作る知見がある程度溜まっていたのでどこかでアウトプットしたかった

などの理由で開催しました.

内容

資料はこれ.

完成形のリポジトリは用意していたのですが,ハンズオンを進めていくうちにちょっと違った記述に行き着いてしまいました. それぞれのステップを友人がcommitレベルでまとめてくれていたので,気になる人はこれを見てください.

github.com

反省・感想

適当に枠は8人,時間は5時間と決めたのですが,みんなで議論しながら置いてけぼりの人があまり出ないような感じで進めれたのでちょうどよかったです.

「Live Coding」と書いたスライドが多くなってしまったのですが,これは書く量が多くてスライドに内容が収まらなかったのとそれをまとめるのがめんどくさかった(主にこっち)のが理由です. ハンズオンを進めながら,「別にerrは_で無視すればいいやん」ってことに気が付き,割と本質のコードだけ眺められるように書けたので,次回からは意識していきたいです.

やはりハンズオンなので,エディタを映す画面と資料を映す画面の2つが必要だなという点と,上記に紹介したとおり,全部の手順をcommitレベルで残しておき,参加者が詰まったときに確認できるリポジトリを作っておくべきだなという点が今回の反省点です. ただ,一度全体の流れを作った後に,それを1つずつ再現してcommitしていくのは面倒です.何かいいサービスは無いのでしょうか...?

ともあれ,無事に終わって良かったです.

内容に不備がある場合は随時資料とこの記事をアップデートしていきます.