憧れのpodcastデビュー!
最初、もの凄い緊張してて全然喋れなかった。
色々話そうと思ったけど、あっという間の1時間でおそらく半分も喋れていない印象
もっと設計ナイトで喋ったようなことを喋ろうと思ったのに…
とはいえ、最後にYAPC::Tokyo 2019の告知ができたので、良かった
憧れの告知!
Podcastを聴いている方だったら分かると思うんですけど、たいていのPodcastでは参加する人が事前にshow noteというものが用意されています。
例えば、ajitofmというPodcastのshow noteは以下のリンク先にあるように、箇条書きで用意されています。
ネット上の辞書でもPodcastで話す内容を用意するもの、と紹介されていますね。
こうゆうのが用意されていると、事前にどんな内容が話されるのか分かって良いですね(必ずしもshow noteが全部きれいに消化されるとは限らないんですけど)。
というわけで、先日Podcast収録でもないんですが、長時間話すのが初めて、というメンバで集まった時に、事前にshow noteを作っておいたら割と話すことに共通認識が事前に形成できて、非常に盛り上がった、ということがあり…
べつにpodcast収録するわけでもない、ただの飲み会でもshow note作るの、いいんじゃないって思った
— magnoliak (@magnolia_k_) 2018年12月14日
show noteをどんな風に用意したら良いか、その辺りの知見は下記のリンクが参考になります。
というわけで、ただの飲み会でもshow noteを作っておくことで(特にそれまであまり話したことが無い人同士であれば)、盛り上がりのポイントが作れて良いのでは?という話でした。
丁寧な言語入門書はたくさんあるけど、ちゃんと言語機能を学べる人向けに、モダンな書き方や、ツールチェーンをざっと説明してくれる書籍って貴重。「Java本格入門」は、例えばScalaを書くためにざっとJavaの機能を知りたい、なんて人に丁度良いのでは?と思った。
Java本格入門 ~モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで
「みんなのGo言語」とか…
古くは「モダンPerl入門」もそんな雰囲気だった。
よちよち感ある入門書と、クックブック系、フレームワークの入門書、特定技術に特化したものを除くと、この手の「ベストプラクティスひとめぐり」みたいな本が欲しくなるんだよね。
ふと、この記事にあるようなこと、Scalaだったらどう書くかな?と思ってまとめてみました。途中で力尽きたので、まずは前半戦まで!
基本的にScalaの標準ライブラリでやる方法を紹介し、Javaの標準ライブラリを使う必要があるところはその旨書いてあります。
また、調べていくとScalaとJavaの標準ライブラリではできないことも有ったので、そこには「標準ライブラリではできません」と書いておきます。標準ライブラリ以外でやれる方法が有ったら、ぜひ教えてください。
なお、標準ライブラリはScala 2.12、Java 11の機能に基づいています。
どちらもScalaのscala.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
クラスを要求するものがありますが、toFile
でjava.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」が返る
ScalaやJavaでチルダや環境変数をパスに展開してくれる標準ライブラリは無いようです。
実現しているライブラリがあればぜひ教えてください。
テキストデータの読み込みにはScalaのscala.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)」と呼ばれるものがあります。ここでは説明は割愛しますが、調べてみると色々な書き方が有るようなので、試してみましょう。
特に専用の構文やライブラリが用意されているわけではないですが、先ほどの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回目のコピーで上書き
と、ここまでで力尽きたので、続きは明日以降!
このブログは企業テックブログという訳でもないので、特にエンジニア募集とかないですけど、定期的に吉祥寺.pmというイベントをやっているので、良かったら参加してみてください。pmとはついていますが、Scalaのトークも歓迎です!
あと、良かったら、Twitterのアカウントもフォローしてください。設計のこととかツイートしています。
先日の設計Night 2018で発表したスライドの冒頭で「いかにして問題をとくか」に出てくる4つのステップを引用した。
元々、表紙をめくった2ページがチートシートになっていて、ソフトウェア開発の進め方を考える上で非常に参考になる要素が全部ここに詰まっているといってもいいくらいの充実した内容が書かれている。この2ページのために1620円を払っても全然いい。
スライドでは最初のステップ「問題を理解すること」だけを使ったけど、当然残る3つのステップもソフトウェア開発においては大事な考え方が詰まっている。
ここでいう「計画をたてる」とはスケジュールを引くことではない。ここでは類似の問題を探してきたり、問題をとくための条件を整理したりする過程をいっている。
特にチートシートの最後に書かれている「問題に含まれる本質的な概念はすべて考慮したか.」をことあるごとに唱えた方が良い。
単に実行するだけではなく、段階的に(形式的、または直感的に!)進めていき、それぞれの正しさを理解すること、更には正しさを証明できるか?と書かれている。
自分が理解できていることと、他人に向かって証明できることはまた異なるといっている。
現代的なソフトウェア開発ではテストを書くことは当たり前になってきたので、この辺りの記載は非常に納得感がある。テストは、その書かれている範囲においてプログラムが意図通りに実行されることの証明になる(バグのないことの証明ではない)。
結果が正しいかを試すことができるか、同じ結果を違った仕方で導くことができるか、ということが書かれている。
KPTつかったりして、振り返りを日常的にやることが大事だ、という考え方が広まっているので、この辺も納得感がある。
見開きのチートシート、第Ⅰ部「教室にて」、第Ⅱ部「いかにして問題をとくか」までが約40ページで、ここまでを読めばほぼこの本の主要なことは全部読むことができる。残る200ページは雑多なトピックが並んでいるので、拾い読みしておけばいい内容…決して全部読まなくてもいい。
UML モデリングのエッセンス 第3版 (Object Oriented SELECTION)
マーチン・ファウラーと言えば、「リファクタリング」を筆頭にさまざまな名著を書いている方だけど、「UMLモデリングのエッセンス」も実に良い。なんとなくだけど、出版からかなりの年月が経っているからか、はたまたタイトルからUMLの子細な解説書かと思われているのか、あまり最近話題に上ることが無い気がする。
あと、シーケンス図が振る舞いを正確に定義するには不向きとか、ユースケースはあまり役に立たない図(つまり、ユースケース図)しか標準化されていないとか、とにかくUMLに対する「使える所は使う、使いすぎない」っていうスタンスがいいなって思った
— magnoliak (@magnolia_k_) 2018年11月12日
モデリング図法は、今自分が関心を振り向けている課題を効率よく解き明かすための方法論として捉えて、包括的/網羅的に仕様を子細に書き表すものとして利用しちゃいけないんだなって
— magnoliak (@magnolia_k_) 2018年11月12日
現代的なプログラミング言語の持つ強力な表現力に匹敵する表現力の有るモデリング図法とか有るのかな…でもわざわざ書くくらいだったらコード書いた方がいいよねっていう
— magnoliak (@magnolia_k_) 2018年11月12日
単なるコールバックも難しそうだし、メタプログラミングは全然想像もつかないし、ScalaのFutureをfor内包式で受けるとか
「設計Night2018 powered by Classi」というイベントで、「設計のための、問題の捉え方〜ドメイン知識の暗黙知を形式知に〜」というタイトルで発表しました。
実際に発表したスライドは読み物として冗長過ぎたので、圧縮したまとめ版を作っていて、そちらへのリンクを張って起きました。
スライド、まとめも長いんですけど、今回自分がまとめたかったのはこの一枚です。
今日の発表、ほぼこの一枚でもいいんだけどね#sekkei_n2018 pic.twitter.com/brQlsQLYD7
— magnoliak (@magnolia_k_) 2018年11月8日
今回の「設計Night2018 powered by Classi」というイベントは、今年のBuildersconで設計に関する最高の発表をされたしんぺいさんによる企画だったので、それは絶対に参加したい(自分も聞きたい)ということで、二つ返事で引き受けました。
イベントレポートの様子は当日のハッシュタグ#sekkei_n2018を追いかけるとご理解頂けるのではないでしょうか。
ちなみに、しんぺいさんの最高の発表内容は、下記のリンクから見ることができます、必見です。
開発現場で役立たせるための設計原則とパターン - builderscon tokyo 2018
最初、引き受けたはいいけど「ドメイン知識の暗黙知を形式知に」「暗黙知が問題の捉え方に移動した」について話して下さいと言われても、実際に何を話せば…とぐるぐる回ってしまったんですが、丁度2ヶ月ほど前に読み直していた「いかにして問題をとくか」に出てくる”条件はかき表すことができるか”という一文が自分の中で突然上手くハマってそこを出発点にしました。
(本文も学びが有りますが、エンジニアにとっては見開き2ページだけでも、開発のステップに関する学びがるので、お勧めです)
あとは、「ソフトウェアの設計における暗黙知あるある」と、以前から感銘を受けていたt_wadaさんのツイートを並べてみると、大筋ができました。
コードには How
— Takuto Wada (@t_wada) 2017年9月5日
テストコードには What
コミットログには Why
コードコメントには Why not
を書こうという話をした
結局のところ、プログラミング言語の進化とか、開発ツールの進化って、いかに開発者が考えた意図を未来に残して、かつそれが上手く後世の人が活用できるか?…それが上手くできないと、ソフトウェアの設計が継続的に上手くできるなんて無いんだぁ!!!って話じゃないかなーって常々思っていたので、それが話せて良かったなって思いました。
あと、懇親会で「ペアプロって暗黙知に有効ですよね」って言ってもらって、「それは確かに!」って思ったので、結局のところ明確に言っているかどうかは別として、みんなが感じている問題の本質は割と同じところにあるんじゃないかと改めて思いました。
色々な暗黙知(と、形式知)に関する文献(野中郁次郎や、マイケル・ポランニーの有名な本とか)を読んだり、論文もいくつか読んでみたのですが、割と抽象度が高かったので、ソフトウェアの設計においての「あるある」をまとめていったら、最終的に「事実」「関係」「原則」の三つに行き当たりました。この辺のまとめ方は、ほかの視点も当然あると思うので、絶対ではないですが、実感として分かりやすいかなって思っています。
最後に「基準」も暗黙知だな、という話を触れたは、統計的手法を使って暗黙知を形式知に変えていく活動って有るなーと思って、その辺を話したかったのですが、さすがに長くなってしまうので割愛しました。でも、マシンラーニングとかもそうですけど、あれって意識していない基準を明らかにしていく活動で、まさに今回のテーマにピッタリだなと思っています。ただ、この辺は自分で語れる要素があまり無いのでぜひ次の設計Nightが開催されたあかつきには誰か発表してほしいなぁと。
ケーススタディに上げた年齢の話は、以前に「4月1日生まれは早生まれ、根拠は”年齢計算ニ関スル法律”」という話を聞いて、調べたことがあったので。
実は、自分は逆に一番最初に「これは2月29日生まれを個別に条件を書かなくてもいい、なんてエレガントなルールなんだ!」と驚いていて、でも「法律の趣旨はそうじゃない」らしく、「あぁ難しいなぁ」と思った思い出からです。そりゃそうですよね…2月29日生まれを特別扱いしないために全員一日前にするっていうと、そりゃ本末転倒ですし。趣旨を理解するのは難しい。
日付の計算という、みんなが分かっているようで、意外と知らなかったりする事例が見つかって良かったなぁって。
ちなみにあの実装が正しいのか?と言われると、これもまた微妙な気がしていて、現実に「2018年2月29日」は存在しないので、その存在しない日の前日って何だろう?みたいな気持ちにもなったりもしていて、果たして実際世の中ではどうやって実装されているんでしょうね。
なお、最初はPerlのTime::Pieceモジュールを使って書こうとしたところ、全然意図通りの挙動をしていなくて(ドキュメントも分かりづらい)、しばらくハマったので、結局Rubyで書きました。色々な言語の日付系のモジュール、なかなか挙動が分かりづらいですね。
4年もテックイベントを開催し続けているくせに、よく考えてみると人前で30分話すのが初めてで(吉祥寺.pmはおかげさまですぐに登壇者が埋まってしまうので…)、最初作ったスライドが140枚とかになってしまい、「果たしてこれは終わるのか…」という気持ちになりました。実際に少し最後を飛ばして28分だったので、もう少し余裕をもったページ数にすべきだったなって。
今更登壇初心者みたいな話になってアレですが、終わった後に一緒に登壇した@moznion氏にあのままアップしても伝わらないかも…とアドバイスを頂いたので、アップ用にまとめ直しました。
今回のスライドを書くにあたって、初めて読んだ、又は久しぶりに読み直した本の数々です。どれも非常に学びのある本でした。
ビジネスフレームワーク図鑑 すぐ使える問題解決・アイデア発想ツール70
UML モデリングのエッセンス 第3版 (Object Oriented SELECTION)
オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方
エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)
実践ドメイン駆動設計 (Object Oriented SELECTION)
ちなみに実は設計ナイトは今回が2回目の開催で、最初の開催のきっかけはこのツイートでした。
設計nightをやればいいんじゃないかと
— magnoliak (@magnolia_k_) 2017年8月29日
そして、ちょっと時間は空いてしまいましたが、今年の3月に「酔いどれ設計ナイト」と称して開催しました。
この時も豪華な参加者の熱い設計トークが展開された訳ですが、居酒屋の片隅で開催していたイベントがこんな豪華なイベントになって帰ってくるとは…
設計に関して話すイベント、マジで最高なのでみんながそれぞれの設計ナイトをやって欲しいですね。今回、50人の定員枠に250人以上の応募が有ったので、確実に需要は有ると思うんですよね。
そして、この勢いに乗って、今年の年末はぜひ「年忘れ!設計ナイト」をやりたいと思った次第です。 たぶん、ただの忘年会なんですけど(フラグ)。
最後に、こんな最高のイベントを用意してくださった、しんぺいさん、Classiさん、本当にありがとうございました!感謝しかないです!