Magnolia Tech

いつもコードのことばかり考えている人のために。

技術書の原著と和訳を両方揃えて読むという英語の勉強法

YAPC::Tokyo 2019でコアスタッフとして、前夜祭LTソンと、本編オープニングをやってきた

f:id:magnoliak:20190127153127j:plain
YAPC::Tokyo 2019のロゴ

YAPC::Asia 2015のLTで、当時丁度「吉祥寺.pm」を始めたタイミングだったのと、YAPC::Asia最後の年ということもあり、「好きなイベントが終わるなら自分でイベントをやればいいんだ」という、まったくプレゼンとして何も成立していない酷いLTをやった。前後のLTのあまりの技術的かつ、エンターテイメント感溢れる内容に比べて、あまりに落差が激しかったので、終わった後しばらく一人で落ち込んでいたのを覚えている。


幸いにもその後吉祥寺.pmはずっと定期開催を崩すこと無く続き、今年5年目に突入した。都内のpmとしては五反田.pmと並んで定期開催できている数少ないpmイベントとして続いている。

参加者も50人を超え、毎回適度に入れ替わり、毎回初めての登壇者も出てくるという、割と良い流れができているのではないかと、自分でも思っている。

そんな縁から、五反田.pm運営の id:kfly8 さんからお誘いを受けて、YAPC::Tokyo 2019にコアスタッフとして参加した。

yapcjapan.org

主に、あまり事前の準備などには参加できなかったけど(ミーティングも直前の一回しか参加していない)、当日に向けて自分だったら主体的に、独立して回せそうなところを相談して引き取っていった。

YAPC::Tokyo 2019 前夜祭

connpass.com

前夜祭ではLTソンをやった。一応「presented by 吉祥寺.pm」とは名付けているが、食事をしながらLTを聴くスタイルなので実はあんまり関係ない。

計13人が集まり、Perlも有れば、イベントグッズの作成まで色んなネタが揃っていて、お祭り感が充分出たかなと。

id:mameco0417 さんの素晴らしい調達力により、テックイベントらしからぬ(?)カラフルな食事と、美味しいビールが揃っていた。

途中休憩を挟んで、食事や飲み物を取る時間を確保したのも幸いしてか、食べ物も飲み物もきっちり消費し切って終わったのが良かった。

ちょっと詰め込み過ぎて、参加者同士の交流の時間があまり取れなかったのは少し反省している。

オープニングトーク

オープニングトークは主に周知事項の案内、ということもあって、ホールの運営担当にアサインされた自分がそのまま担当した。

本当は周知だけでも良かったんだけど、元々のYAPC::Tokyo 2019のテーマである「報恩謝徳」と、最近気に入っている「恩送り」という言葉を組み合わせて、「恩に報いる方法は人それぞれ」というメッセージだけは喋ることにした。

これは自分が、これまでテックイベントに参加して得られたマインドセットみたいなものがもっと広がっていくといいな、と思って吉祥寺.pmというイベントを続けている理由の一つだったりするので。

ホール運営

オープニングトークの後は終日ホール運営に専念。ホールのトークは全部聴いたけど、ホール以外の部屋のトークに興味深いものも多く、後でスライドをチェックしないと…と思っている。

ホール運営については特に事故もなく、つつがなく運営できて良かったと思っているんだけど、もし何か気になることが有ったら、フィードバックをお願いします。

トークについて

色々と挙げだすとキリが無いんだけど、一つこれだけは触れておかないといけないことが有るとすれば、今回ベストトーク賞を取った id:songmu さんのスライドの中に自分の名前が出ていたのが最高に嬉しかった。

色々な人に会った

まさに「Perl界隈の同窓会」という雰囲気で、色々な方々が一堂に会していた。

久しぶりに会う方もいらっしゃれば、一方的にこちらが知っている人にご挨拶ができたり、まったく知らなかった方とも知り合うきっかけにもなった。

次回YAPC::Japan

当然YAPCだけがテックイベントではないけれど、やはり何か一つ独特な雰囲気が有るんじゃないかと思っている。この雰囲気作りに協力が少しでもできた…かもしれない。

次回のYAPC::Japanの開催地はまだ決まっていないのが実情だけど、「我こそは!」と手を挙げる方がいらっしゃったらJPA(Japan Perl Association)に相談すると良いと思う。

誰だってテックカンファレンスを最初からやれるわけでは無いので。

おわりに

というわけで、それぞれの「報恩謝徳」が感じられた最高のイベントだった。

これをスタートに、更に人それぞれの「報恩謝徳」になればいいんじゃないかな。

あと、運営統括の id:kfly8 さんはじめ、最高のスタッフにお疲れ様とありがとうを言いたい。

そして、スポンサーの皆様、参加者の皆様、ありがとうございました。


ちなみに、冒頭のYAPC::Asia 2015でのLTが酷かった件については、順番的に自分の後にLTをやった id:yoku_0825 さんが、2年越しで吉祥寺.pmに来て下さって「あの時のLTを覚えていたので、来た」と言って頂けたので、今では良い思い出になっています。

ajitofmに出演した

ajito.fm

憧れのpodcastデビュー!

最初、もの凄い緊張してて全然喋れなかった。

色々話そうと思ったけど、あっという間の1時間でおそらく半分も喋れていない印象

もっと設計ナイトで喋ったようなことを喋ろうと思ったのに…

とはいえ、最後にYAPC::Tokyo 2019の告知ができたので、良かった

憧れの告知!

ただの飲み会でもshow noteを書くと良いな、と思った

Podcastを聴いている方だったら分かると思うんですけど、たいていのPodcastでは参加する人が事前にshow noteというものが用意されています。

例えば、ajitofmというPodcastのshow noteは以下のリンク先にあるように、箇条書きで用意されています。

ajito.fm

ネット上の辞書でもPodcastで話す内容を用意するもの、と紹介されていますね。

ejje.weblio.jp

こうゆうのが用意されていると、事前にどんな内容が話されるのか分かって良いですね(必ずしもshow noteが全部きれいに消化されるとは限らないんですけど)。


というわけで、先日Podcast収録でもないんですが、長時間話すのが初めて、というメンバで集まった時に、事前にshow noteを作っておいたら割と話すことに共通認識が事前に形成できて、非常に盛り上がった、ということがあり…


show noteをどんな風に用意したら良いか、その辺りの知見は下記のリンクが参考になります。

medium.com


というわけで、ただの飲み会でもshow noteを作っておくことで(特にそれまであまり話したことが無い人同士であれば)、盛り上がりのポイントが作れて良いのでは?という話でした。

「Java本格入門」を買ってきた

丁寧な言語入門書はたくさんあるけど、ちゃんと言語機能を学べる人向けに、モダンな書き方や、ツールチェーンをざっと説明してくれる書籍って貴重。「Java本格入門」は、例えばScalaを書くためにざっとJavaの機能を知りたい、なんて人に丁度良いのでは?と思った。

Java本格入門 ~モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで

Java本格入門 ~モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで

「みんなのGo言語」とか…

みんなのGo言語[現場で使える実践テクニック]

みんなのGo言語[現場で使える実践テクニック]

古くは「モダンPerl入門」もそんな雰囲気だった。

モダンPerl入門 (CodeZine BOOKS)

モダンPerl入門 (CodeZine BOOKS)

よちよち感ある入門書と、クックブック系、フレームワークの入門書、特定技術に特化したものを除くと、この手の「ベストプラクティスひとめぐり」みたいな本が欲しくなるんだよね。

2018年版・この処理Scalaでどう書く?…前半戦

ふと、この記事にあるようなこと、Scalaだったらどう書くかな?と思ってまとめてみました。途中で力尽きたので、まずは前半戦まで!

www.m3tech.blog

あの処理、Scalaでどう書く?

基本的にScalaの標準ライブラリでやる方法を紹介し、Javaの標準ライブラリを使う必要があるところはその旨書いてあります。

また、調べていくとScalaJavaの標準ライブラリではできないことも有ったので、そこには「標準ライブラリではできません」と書いておきます。標準ライブラリ以外でやれる方法が有ったら、ぜひ教えてください。

なお、標準ライブラリはScala 2.12、Java 11の機能に基づいています。

標準出力・標準エラー出力

どちらもScalascala.Consoleオブジェクトのprintlnメソッドを使います(パッケージ名のscalaは省略可なので、以降は省略します)。

println("HELLO") // 標準出力にメッセージ

Console.err.println("ERROR!") // 標準エラー出力にメッセージ

単にprintlnと書いた場合は、Console.out.printlnが呼び出されます。

なお、標準ライブラリにはログ出力ライブラリは用意されていません。

ファイル関係

基本的にScalaの標準ライブラリでは、ファイル関係のサポートがほぼ無いので、基本的にJavaの標準ライブラリを使います。

パスの操作

Java 7から追加されたjava.nio.file.Pathsクラスを使います。

import java.nio.file.Paths

val p = Paths.get("/foo/bar/baz.txt") // OSごとの実装を持つPathインタフェースが返される
p.getFileName // ファイル名「baz.txt」を保持するPathが返る
p.getParent // 親ディレクトリ「/foo/bar/」を保持するPathが返る

val dirpath = Paths.get("/foo/bar")
dirpath.resolve("baz.txt") // パスの連結 「/foo/bar/baz.txt」を保持するPath…引数は文字列でもPathでもOK

Pathは、toStringで文字列に戻せます。また、Java6以前に作られたライブラリはjava.io.Fileクラスを要求するものがありますが、toFilejava.io.Fileに変換できます。

import java.nio.file.Paths

val fullpath = Paths.get("/foo/bar/baz.txt")
fullpath.toString // 文字列として「/foo/bar/baz.txt」が返る
fullpath.toFile // java.io.Fileでラップされた「/foo/bar/baz.txt」が返る

チルダ環境変数が含まれるパスを扱う

ScalaJavaチルダ環境変数をパスに展開してくれる標準ライブラリは無いようです。

実現しているライブラリがあればぜひ教えてください。

ファイルの読み書き

テキストデータの読み込みにはScalascala.io.SourceオブジェクトのfromFileメソッドが便利です。

val source = io.Source.fromFile("foo.txt", "utf-8")
val lines = source.lines
lines.foreach(println) // 行単位で標準出力へ
source.close

fromFileメソッドは文字列でのパス名以外にもjava.io.Fileクラスのオブジェクトも指定可能です。また、scala.io.Sourceはデフォルトで文字コードとして"UTF-8"が使われるようになっていますが、明示的に指定した方が分かりやすいでしょう。

反対に書き込みについては、専用のライブラリは(なぜか)用意されていないので、Java 7で導入されたFiles.newBufferedReaderメソッドを使います。ただし、Scalaにはtry-with-resource構文が無いので自前でクローズします。

import java.nio.file.Paths
import java.nio.file.Files
import java.nio.charset.StandardCharsets

val path = Paths.get("foo.txt")
val writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)

try {
  writer.append("内容")
  writer.newLine
} finally {
  writer.close
} 

構造が簡単なうちは自前でcloseメソッドを呼び出すようなコードを書いていても大丈夫だと思いますが、コードの構造が大規模になってくるとcloseの呼び出しも複雑化してきます。このような場合、Javaであればtry-with-resource構文がありますし、C#にはusing構文があります。Scalaでも構文は用意されていませんが、コーディングテクニックとしての「ローンパターン(loan pattern)」と呼ばれるものがあります。ここでは説明は割愛しますが、調べてみると色々な書き方が有るようなので、試してみましょう。

行数を数える(wc -l)

特に専用の構文やライブラリが用意されているわけではないですが、先ほどのio.Sourceを使うとシンプルに書けます。

val source = io.Source.fromFile("foo.txt")
source.getLines.length

ファイルの列挙

Java7で導入されたFiles.newDirectoryStreamを使います。

import java.nio.file.Paths
import java.nio.file.Files

val files = Files.newDirectoryStream(Paths.get("."), "*.txt")

try {
  files.forEach(println)
} finally {
  files.close
}

ファイルの情報(存在確認・作成日時)

java.nio.file.Filesのメソッド群を使います。

import java.nio.file.Paths
import java.nio.file.Files

val f = Paths.get("foo.txt")
Files.exists(f) // 存在確認
Files.isRegularFile(f) // ファイル?
Files.isDirectory(f) // ディレクトリ?
Files.getLastModifiedTime(f) // 更新日時…戻り値の型がjava.nio.file.attribute.FileTimeであることに注意!

その他、ファイルシステム固有の属性(作成日時、アクセス日時)は、Files.getAttributeメソッドを使います。戻り値がobject型になってしまうので、キャストが必要な点が要注意です。

val createTime = Files.getAttribute(Paths.get("foo.txt"), "unix:creationTime").asInstanceOf[java.nio.file.attribute.FileTime]
val accessTime = Files.getAttribute(Paths.get("foo.txt"), "unix:lastAccessTime").asInstanceOf[java.nio.file.attribute.FileTime]

コピー・移動・削除

こちらもjava.nio.file.Filesのメソッド群を使います。

import java.nio.file.Paths
import java.nio.file.Files

Files.copy(Paths.get("foo.txt"), Paths.get("bar.txt")) // コピー
Files.delete(Paths.get("bar.txt")) // 削除
Files.move(Paths.get("foo.txt"), Paths.get("bar.txt")) // 移動

コピーや、移動はオプションとしてStandardCopyOptionが用意する定数を指定することができます。例えば、StandardCopyOption.REPLACE_EXISTINGを指定すると、すでにファイルが有っても上書きします。

import java.nio.file.Paths
import java.nio.file.Files
import java.nio.file.StandardCopyOption

Files.copy(Paths.get("foo.txt"), Paths.get("bar.txt")) // コピー
// foo.txtを書き換える処理
Files.copy(Paths.get("foo.txt"), Paths.get("bar.txt"), StandardCopyOption.REPLACE_EXISTING) // 2回目のコピーで上書き

と、ここまでで力尽きたので、続きは明日以降!

外部コマンド

単純に実行する

外部のコマンドを実行し、標準出力を受け取る:

環境変数やカレントディレクトリを変更する

リダイレクトを使う

パイプを使う

spawn → wait (外部コマンドを起動し、終了を待つ)

シェルを実行する【危険!!】

時刻関係

文字列関係

文字列への式埋め込み

ヒアドキュメント

コマンドライン引数

終了時の処理&シグナルをtrapする

HTTPリクエスト(curlwget の代替)

吉祥寺.pmへの参加者を募集しています

このブログは企業テックブログという訳でもないので、特にエンジニア募集とかないですけど、定期的に吉祥寺.pmというイベントをやっているので、良かったら参加してみてください。pmとはついていますが、Scalaトークも歓迎です!

kichijojipm.connpass.com

あと、良かったら、Twitterのアカウントもフォローしてください。設計のこととかツイートしています。

twitter.com

「いかにして問題をとくか」を読んでみよう

いかにして問題をとくか

いかにして問題をとくか

先日の設計Night 2018で発表したスライドの冒頭で「いかにして問題をとくか」に出てくる4つのステップを引用した。

  1. 問題を理解すること
  2. 計画をたてること
  3. 計画を実行すること
  4. ふり返ってみること

元々、表紙をめくった2ページがチートシートになっていて、ソフトウェア開発の進め方を考える上で非常に参考になる要素が全部ここに詰まっているといってもいいくらいの充実した内容が書かれている。この2ページのために1620円を払っても全然いい。

スライドでは最初のステップ「問題を理解すること」だけを使ったけど、当然残る3つのステップもソフトウェア開発においては大事な考え方が詰まっている。

計画をたてること

ここでいう「計画をたてる」とはスケジュールを引くことではない。ここでは類似の問題を探してきたり、問題をとくための条件を整理したりする過程をいっている。

特にチートシートの最後に書かれている「問題に含まれる本質的な概念はすべて考慮したか.」をことあるごとに唱えた方が良い。

計画を実行すること

単に実行するだけではなく、段階的に(形式的、または直感的に!)進めていき、それぞれの正しさを理解すること、更には正しさを証明できるか?と書かれている。

自分が理解できていることと、他人に向かって証明できることはまた異なるといっている。

現代的なソフトウェア開発ではテストを書くことは当たり前になってきたので、この辺りの記載は非常に納得感がある。テストは、その書かれている範囲においてプログラムが意図通りに実行されることの証明になる(バグのないことの証明ではない)。

ふり返ってみること

結果が正しいかを試すことができるか、同じ結果を違った仕方で導くことができるか、ということが書かれている。

KPTつかったりして、振り返りを日常的にやることが大事だ、という考え方が広まっているので、この辺も納得感がある。

おわりに

見開きのチートシート、第Ⅰ部「教室にて」、第Ⅱ部「いかにして問題をとくか」までが約40ページで、ここまでを読めばほぼこの本の主要なことは全部読むことができる。残る200ページは雑多なトピックが並んでいるので、拾い読みしておけばいい内容…決して全部読まなくてもいい。