Software engineering from east direction

六本木一丁目で働くソフトウェアエンジニアのブログ

書評: パターン、Wiki、XP ~時を超えた創造の原則 がすごく面白かった

ソフトウェア設計とは何なんだというような話を社内でモヤモヤ話していました。

その話の流れで、@fuubitさんからアーキテクチャ設計の意味を問う - クリストファー・アレグザンダーの思考の軌跡というブログエントリを紹介していただいて、めちゃめちゃおもろいこれ!非常に興味深く読ませていただきました。

arclamp.hatenablog.com

すごく興味深かったので、ブログ冒頭で紹介されていた江渡 浩一郎さんのパターン、Wiki、XP ~時を超えた創造の原則 (WEB+DB PRESS plusシリーズ)も「これおもしろい!」と当日の夜にさくさく読ませていただきました。(風呂で電子版を1時間弱読んで体内の水分がおしまいになりました)

こちらの書籍が非常に面白かったのでどのような内容が書かれていたか紹介したいと思います。

パターン、Wiki、XP ~時を超えた創造の原則

この書籍は大きく、3部立てになっています。

  1. 第1部 建築
  2. 第2部 ソフトウェア開発
  3. 第3部 Wiki

いきなりソフトウェア開発の話ではなく、建築の話から始まります。ソフトウェア開発のプロセスや設計は大きく建築の世界の概念が参考にされていると聞いたことがある方は多いかもしれません。この書籍では、建築家 クリストファー・アレグザンダー が追求してきた建築設計の理論・概念整理が、ソフトウェア開発で普段聞く概念にどのような影響をもたらしているかという話が展開されます。

パターン、Wiki、XP ~時を超えた創造の原則 という書籍タイトルで想像つくかもしれませんが、デザインパターンやXP(エクストリームプログラミング)といった概念が書籍で取り上げられます。

また、XPが誕生までの過程のなかで、オブジェクト指向についても取り上げられます。

個人的に面白かった点

クリストファー・アレグザンダーの考え方の移り変わり

クリストファー・アレグザンダー氏は、"パタン・ランゲージ"という概念を考えだした方ですが、理論を構築して実践・失敗、そこから学び実践、とされています。本書では、彼の思考の移り変わりを 6 章にわたり非常にわかり易く解説してくださっています。 その中で提唱される原則や設計についての考え方は、普段その影響を受けたソフトウェア開発の舞台にいる我々にとっては「はっもしやこれはあの概念につながっていくのでは!?」と謎解きをしていくような感覚を味あわせてくれました。

クリストファー・アレグザンダーの追求

クリストファー・アレグザンダー氏の追求したものが書籍内では、次のように書かれていました。

彼が建築において追及したいと思っていたのは、「何がものを美しくするのか」という原理でした。 江渡 浩一郎. パターン、Wiki、XP 時を超えた創造の原則 (WEB+DB PRESS plus) (Japanese Edition) (Kindle Locations 401-402). Kindle Edition

ソフトウェア設計について深く考え自分なりの理解・考えを突き詰めてらっしゃる方々を見ていると、(いい意味で)理想や美や調和のようなものへの探求みたいなことを感じていて、そういう姿勢に私はその方の"ソフトウェアエンジニアとしての深さ"を感じて尊敬しています。アレグザンダー氏の追求したものを読んで、「なるほどなぁ」と言葉にならない納得感を覚えました。

老練な親方と新前大工の仕事の進め方

アレグザンダー氏の書籍「パタン・ランゲージ―環境設計の手引」では、老練な親方と新前大工の仕事の進め方という例が出てくるのですが、これはソフトウェア開発においても同様に言えるなと思いました。

決定的な違いは仕事の手順である。老練な大工は、後で修正できないようなことはけっしてやらない。だからこそ、自信たっぷりと着実に仕事を進めていくのである。(中略)新前と親方との違いは、小さな過ちを吸収しながら建てていく方法を、新前がまだ修得していないだけのことである。親方のほうは、自分の作業を続けていれば、必ず後で過ちを修正できることを知っている。この単純かつ本質的な知恵があるからこそ、親方大工の仕事ぶりが、すばらしく、滑らかで、くつろいで、無頓着といってよいほどの単純作業に見えるのである。 江渡 浩一郎. パターン、Wiki、XP 時を超えた創造の原則 (WEB+DB PRESS plus) (Japanese Edition) (Kindle Locations 747-753). Kindle Edition

"老練な大工は、後で修正できないようなことはけっしてやらない"という一文に、そうだよなぁという気持ちになりました。

OOPSLA1996 での基調講演

OOPSLA(Object-Oriented Programming, Systems, Languages & Applications) 19961というオブジェクト指向プログラミングのシステム、言語、アプリケーションをシュダにしたカンファレンスで建築家のアレグザンダー氏が基調講演をされています

その中で次のような話がされたようです。

「生きた世界」(LivingWorld)はどのようにして生成され得るかという問題について扱いました。非常に興味深いことに、この問題は建築家や都市計画家ではなく、聴衆であるコンピュータ科学の領域に属する人々こそが答えを見つけることができるはずだ 江渡 浩一郎. パターン、Wiki、XP 時を超えた創造の原則 (WEB+DB PRESS plus) (Japanese Edition) (Kindle Locations 1990-1993). Kindle Edition

長い歴史のなかで、ひとつの答えを見つけるパスをコンピュータ科学の領域に呼びかけるという、学問はつながる瞬間があるのだなとぞわっとした感覚をもちました。

(主題の内容にはあまり触れなかった)

などと、主題を避けてピックアップしたところでも、各所で琴線に触れる内容で、とても面白かったです。

すごく人に伝えたかったので

第142回 PHP勉強会@東京で周辺の話もまとめた上でお話します。

ソフトウェア設計を少し学んでいる方々にとっては、「あの人がここに影響受けて、更にそれがあの人に繋がり、この概念にうぉぉぉ」という感動があります。まだ読んでないよ〜という方はぜひ読んでみてください!

外部イベント登壇しがち属性が考える登壇の使い方

TL;DR

  • 外部イベントを楽しむ・学びのきっかけにするための登壇の使い方
  • イベント運営の方々いつもほんとうにありがとうありがとう...

はじめに

社の飲み会などでカンファレンスに行ったり登壇したりすることの意味みたいなことがうっすら話題になり、各エンジニアの力量・フェーズによって"使い方"が変わるよなぁと思ったので考えをまとめてみます。

カンファレンスなどの外部イベントへ関わり始めたのは大学生のころからでした。大多数が職業エンジニアという属性の場に一人でいっていて、職業エンジニアになり数年経過した今でもいろいろなイベントに顔を出させていただいています。

そういった経過の中で、感じた登壇するとこういうことが良かったなとおもうことを書いてみようと思います。

目次

  • 外部イベントでの"交流を楽しくする"使い方
  • 外部イベント登壇をマイルストーンに置く"学びのペースメーカー"としての使い方
  • 思考の練度を上げる"きっかけ"としての使い方
  • 伝え方の練度を上げる"きっかけ"としての使い方

外部イベントでの"交流を楽しくする"使い方

カンファレンスなど初めて行く場で、その場で懇親会が始まったりすると、根本的に人見知りな私は話しかけるのに躊躇してしまいます。学生の頃は、「大学生なんです!」っていうと優しいおじさんたちが輪にいれてくれるといったことはあるのですが、職業エンジニアになるのと会話のフックが難しかったりしてさらに困難を極めます。

しかし、何かしらで登壇しておくと自分のセッションの聴講者の方々が大変ありがたいことに話しかけてくださったりします。
例えば、今年の6月29日に開催されたPHPカンファレンス福岡2019では、ユニットテストの現場の問題を原則に立ち返って考えるという内容の話をしたのですが、その後のAsk the Speakerや懇親会で、同じような課題感を持ってらっしゃる方々が集まってきていただいて、人見知りな私でも交流を楽しむことができました。

また、そういった交流の中で新しい気付きや課題を見つけることもあります。 例えば、Go Un ConferenceというイベントでGo API Validation error handlingという「みなさんどうしてますか?」という問いかけがほしい旨の内容を話すと、twitter上でそれに関する意見を貰えることができたりしました。

これは、聴講者として参加していただけでは得られなかった交流の仕方だなと思い感動を覚えました。

学びのペースメーカーとしての使い方

これについては、2018年のPHPカンファレンス2018でも次のようなLTをさせていただいていました。

俗に言う"発表駆動開発"というものでしょうか(本当に俗にいうかはわからないけどよく聞くので)。実際にこの効果はあって、普段業務では使ってないけど今後使っていきたい領域をカバーしたいというときに有用だと思います。
例えば、昨年のPHP勉強会でTerraformでAWSのインフラ構成構築を自動化する(入門)という発表をしました。この時の状況として、アプリケーションエンジニアなのでメインでTerraformを触るわけではないが、理解する必要があるし、少しずつクラウドやインフラ領域に対して自分の専門領域を広げていきたいと思っていました。そのために、雰囲気で見ている .tf ファイルを理解すべく発表をマイルストーンにおいてががっと勉強したという経緯があります。
このように、外部イベントで「その話ができるレベルにはなりたい」というマイルストーンをおいて、そこまで自分の能力を強制的に引き上げるというプロセスを私はよくやっていました。それの継続の末にいろいろな範囲をカバーできるようになってきた自分がいたりするので、負荷が高いやり方ですが眼の前の業務範囲に縛られないという状況を作りたい方にはおすすめな使い方だと思います。

逆に言うと、「その範囲は仕事の中で手が届くし、今やってないなら自分で仕事にしてしまえ!」くらいの能力・立場・心の力を持っているとこの使い方はあまり刺さらないメリットなのかもしれないと最近は思っています。

思考の練度を上げる"きっかけ"としての使い方

ソフトウェアエンジニアの"技術力"という言葉がどう定義でどう分類できるかというのは難しいですが、一つの要素として、実現するソフトウェアシステムに込められた 思考の深さ があるのではと思っています。
一つのクラスを作るなり機能を作るなりしても、その人が普段どれだけソフトウェア開発についての思考を巡らせていて、設計ノウハウ・知力をそこに込められているかは、結果的にメンテナンス性やパフォーマンス性といった別の指標で現れてくるのではと考えています。そういった意味で、さらに深いレベルで思考する、思考の練度を上げていくことは個人の能力に直結していくと思っています。

例えば、僕はユニットテストという一つのテーマでPHP系カンファレンスで何度か話しているのですが、それは毎回の発表時点ではまだ思考の練度が足りず話せなかったことをやろうとしています。カンファレンスを通して自分のソフトウェア開発に対する思考の練度を高めようとしています。

そういった形で自身のソフトウェア開発の造詣を深めるために登壇というきっかけを作るという事ができると思っています。

伝え方の練度を上げる"きっかけ"としての使い方

同僚のエンジニアのコードに対してレビューするといった機会や、同僚に対して何かしら働きかけを行いたいと思った際に、様々な伝え方があると思います。「俺のコードを読んでついてこい」というような職人タイプの引っ張り方もあれば、一から言葉とコード例で伝えていくという引っ張り方もあります。
職業エンジニアとしてそのソフトウェア・あるいはサービスに貢献する方法として、一個人としてのスキルの提供を通して貢献していくてもありますが、より再現性・レバレッジを利かせるのであれば自分以外も含めてチーム全体でどう成果物を出せるかというのは、大なり小なり重要な貢献の仕方です。 後者を考えると、「どう伝えるか」という点においていろいろな難しさがありますよね。普段から考えていないと「なんとなくこうしてる」といった見えない慣習的なことがあります。あるいは、自分のスタイルを人に伝達しようとした際に、そのメリット・デメリットを把握できているか、その人の状態で無理のないやり方に落とし込めるかという点が求められます。

そのような伝え方の練度をあげるために、一つ登壇して"アウトプットを残す"ということが有効かなと考えています。
たとえば、PHPカンファレンス仙台2019 にて、テストが辛いを解決するテスト駆動開発のアプローチという発表をしました。
これは、「このコードにテストを書くのがつらいんだがどうすればいいだろう」というコードの悩みを何度か現場で聞き、それに対して説明していたことをちゃんと筋道立てた形で資料にしたいとおもったことがきっかけでプロポーザルを出したものです。
このように、実際に現場で「あの人にどう伝えればいいだろう」というテーマをもとに発表内容を構成していくと、自分自身が実は意識していなかったことが言語化され、伝える際の参考資料も登壇を通して手に入れることができます。
多かれ少なかれ、誰かに対して働きかけを行ったり、自身の知っていること・身につけていることを伝搬する機会はあると思うので、そのようなことを考えることが多い方にはこういう使い方がおすすめなのではと思っています。

最後に

使い方という形で登壇に対して自分が思っている「使い方」を書いてみました。こういう雑な記事がかけるのも、普段カンファレンスやイベントを有志で運営していただいている方々のおかげです。この場を借りて皆様に深く感謝の意を申し上げます。
この記事では、「エンジニアとしての市場価値」などの観点は入れていません。実際、個人のコミュニティにおける注目度が上がることによって、所属している企業に興味を持ってもらうフックになるという意味での価値は一つあると思います。個人的には その価値に溺れてしまうと名実の実が著しく乖離してしまう状況になってしまう危惧があり、今回はあえて省略させていただきました。
アウトプットの一つとして登壇というものをどう使えそうかということをつらつらと書きましたが、登壇だけが全てではまったくなく、業務やOSSのコントリビュート・ブログ等様々なものを、それぞれ個人が使い分けていけばいいと思います。
一つの考え方として参考になれば幸いです

#golangtokyo Go Conference Tokyo 2019 Spring 2次会 参加レポート

golang.tokyo#24 に参加したので、聞いた内容・感想をまとめていきます。

golangtokyo.connpass.com

(※LTトークの時間でバッテリーがあれだったので感想書けず...LTトーク非常におもしろかったです!)

CLI ツールを支える技術 2019 春 by @izumin5210 さん

感想

  • CLIツールを作りたいときに一番選択肢が多いパーサー・設定関連のライブラリどれがおすすめかという話がよかったです。

Go (Ebiten) で実践モバイルゲーム開発 by @hajimehoshi

感想

  • Goでゲームを作るとてもロマンの溢れた話でした
  • Gopher Conference 2019参加チャネルで拝見してた方なのでリアルで見れて個人的な感動がありました。

Chaos Engineeringの手前の話 by @hazumirr

感想

  • chaors engineering の原則が公開されてるのは知らなかったので読んでみたい
  • 実際にやる際の検討ポイントがしれてよかった

gRPC Server with golang by @abemotion

  • gRPCの構造がmodelになる
    • (チョット感じた言葉にならない感想)
      • リクエスト・レスポンスのインターフェースとドメインモデルにそのままなるのが違和感を感じる
      • 外部のインターフェースの関心にロジック自体が影響受けるようなイメージを持ってもやっとしたが、gRPCやるとそういうものなのかな?
  • gRPCのエラー処理、独自のエラーコードが用意されてる
  • gRPCがmiddlewareを様々提供している
  • gRPCで困ったこと
    • NULL非許容

感想

  • gRPCそろそろ試して業務でやるか考えようと思っていたので実装例ありがたい...
  • レイヤ構成とかの考え方は近い感じになっていて共感みがあった
  • gRPC、多言語を挟むときに便利。

cloud.google.com/go/pubsub internal by @izumin5210

感想

  • pub/subの概要をおさらいした上で中の実装こういう事やってるっていうコード読んでいくのがおもしろかったです。
  • 人がコード読んでるのを見るの色々なテクニックが見れて面白いですね。

最後に

会場を提供してくださった freee株式会社 さんありがとうございました!

Go Conference Tokyo 2019 Spring スピーカー参加・聴講感想 #gocon

Go Conference Tokyo 2019 Spring にてスピーカー参加してきました。今回はいつものカンファレンスより準備を早めにやったこともあり、がっつり他の方のトークを聴講できました。純粋なメモ・感想を書いていきます。

発表したSession

"Design considerations for container-based Go applications"という発表をしました。

発表自体の概要や背景については所属企業のブログエントリで公開するので詳しく書きませんが、Gopher君もらえて嬉しかったです。

f:id:khigashigashi:20190518162503j:plain
Gopher君かわいい

聴講Sessions

次のセッションを聴講しました。

  • Keynote "Go Module Proxy Life of a Query"
  • Hacking Go Compiler Internals 2
  • Goによる外部プロセス起動ベストプラクティス及びtimeoutパッケージ徹底解決
  • Dive into Buildkit LLB with Go
  • CPU, Memory and Go

Keynote "Go Module Proxy Life of a Query"

Memo

Impression

Hacking Go Compiler Internals 2

Outline

Memo

  • Lexer
  • Parser
  • Annotated AST construction
  • Typechecking
    • 型チェック
    • 変数・値のみではなく
  • Varitable binding
  • Inlining
  • Escape Analysis
    • new()関数、heapにおかれる
    • 変数定義で確保、stackにおかれる
    • stackにおいたものをheapにおかなきゃという判断
  • Closure Rewriting
  • Walk
  • SSA Generation
    • Go1.7で導入
    • Go1.7以前ではできなかった最適化できる

Impression

Goによる外部プロセス起動ベストプラクティス及びtimeoutパッケージ徹底解決

Outline

Memo

  • コマンドラッパー
    • ghq・mackerel-agentなどコマンドを実行する例
  • コマンド実行
    • os/exec packageを使えば簡単に
    • io,MultiWriter
  • シグナルハンドリング
    • SIGKILL・SIGSTOPはできない
    • SIGTERMで正常終了を促すのがお作法、できなかったらSIGKILL
  • exec.CommandContextの問題は、SIGKILLで強制停止・孫プロセスを停止できない点
  • Songmu/timeout
  • timeout.c
    • SIGCONTを送ることで強制的に再開させる

Impression

  • 本筋ではないですが作ってるライブラリの量がすごい、見習ってがんがん公開していきたいと思いました
  • 今回発表いただいた資料を見ながら公開されているライブラリを読むと更に勉強になりそう。ありがたく勉強させていただきます...!

Dive into Buildkit LLB with Go

Memo

  • Docker18.0.9で正式機能として利用できるBuildKit
  • BuildKitが提供するもの
    • buildctl・buildkidt
  • BuidKitはGoで書かれている
  • BuildKitもurlfave/cli 使ってるんだへぇ
  • LLB
    • BuidKitのコア
    • BuildKit では LLB(low-level builder) に一度変換する。 LLB は DAG 構造
    • grpcで通信・protocol bufferを使っている
  • Opertaionの依存はinputsに定義
  • 。DOT 言語に変換することで GraphViz で可視化できるツールとして llb2dot を作った
  • BuildKitはマルチステージビルドの並列化だけではなく、RUNレベルの1ステップ単位でも共通化できる。
  • Dockerfile2LLB
  • Dockerfileのlinterを作ったりできる

Impression

  • Dockerfileのlinterを作ったりできる、たとえば、「Dockerfile内で環境変数を与えていないか」みたいなlinterを作ることも可能。 僕のトーク内容触れていただいたからには帰って試さなければ…!
  • @po3rin さんのトーク、BuildKit・LLB概要レベルくらいしか知らない僕でも、実際に手を動かせる手ほどきになっていて、めちゃめちゃありがたかった...!
  • コードハイライトどうやってるんだろう?

CPU, Memory and Go

  • sonatard さんの発表

Impression

  • CPU, Memory and Go”のトーク、Goが何をしているかに関してわかりやすく解説いただいていてすごくよかった、後で資料公開頂いたら読み直したい...!
    • 公開いただいた読み返しまくる
  • 大盛況で立ち見勢だったのでメモは取れず

さいごに

Goの様々知見が聞けてめちゃめちゃ良かったです!運営の方々このような素晴らしい場をありがとうございました!

GoLandでgoldenファイルを用いたユニットテストを書く #golang

TL;DR

  • GoLandでgoldenファイルを任意のファイルタイプで認識できるようにする
  • それによって、goldenファイル作成時にGoLandの補完能力を失わないようにする

goldenファイルとは

Go言語でのユニットテスト作成時、JSONHTMLといった用に別ファイルをテストの引数や期待値に必要とするケースがあります。これに対して、.golden拡張子をつけたファイルとして別定義する手段があります。これは、Goの標準ライブラリのテストコード内でも使用されている方法です。

たとえば、TestDiff()というテスト関数内で次のようにJSON文字列を必要するケースを想像してください。

func TestDiff(t *testing.T) {

    want := `
{
  "string": "A",
  "integer": 1
}
`
    // 以降のテストコード
}

そのままテスト関数内に定義してしまうとそのテスト関数の見通しが悪くなってしまうかもしれません。これに対して、goldenファイルを使用する場合は、testdata ディレクトリ配下に.golden拡張子をつけたファイルを配置して使用します。

testdataディレクトリを配置すると、そのディレクトリはパッケージとしてみなされないため、テスト時のみに必要なファイルとしてプロジェクトに配置することができます。

https://golang.org/cmd/go/#hdr-Test_packages

The go tool will ignore a directory named "testdata", making it available to hold ancillary data needed by the tests.

今回はJSON形式のファイルなので、want.json.goldenという名前でJSONファイルを保存します。

{
  "string": "A",
  "integer": 1
}

このように配置することで先程直接JSON文字列を書いていたテストコードは次のようになります。

func TestDiff(t *testing.T) {

    want := getStringByFile(t, "testdata/want.json.golden")

    // 以降のテストコード
}

func getStringByFile(t *testing.T, path string) string {
    t.Helper()

    bs, err := ioutil.ReadFile(path)
    if err != nil {
        t.Fatalf("ioutil.ReadAll(%s) got unexpected error %#v", path, err)
    }
    return string(bs)
}

GoLandでのgoldenファイルに対する設定をする

goldenファイルを用いたテストはこのような比較的に大きくなりがちなファイル形式の際に重宝しているのですが、golden拡張子だとPlain Textとしてのファイルタイプ認識になることにフラストレーションを感じました。そのため筆者は、goldenファイルの命名とGoLandのFile Typesの設定を合わせることで任意のファイルタイプを認識できるように設定しています。

具体的には、*.json.goldenであれば、JSONファイルとして認識するというような設定をしています。実際に、設定方法を見ていきましょう。

まず、GoLandの設定画面を開きましょう。Macであれば、Command + , というショートカットで開きます。そこで、Editor/File Typesの画面へ遷移します。

f:id:khigashigashi:20190427143822p:plain
Editor > File Typesの設定画面

この画面では、ファイル名に対してどのファイルタイプで認識するか設定できます。*.json.goldenJSONファイルだと認識させたいので、JSONの設定に行きます。

f:id:khigashigashi:20190427145750p:plain
File Types: JSON

この拡張子パターンに、*.json.goldenを追加します。

f:id:khigashigashi:20190427145857p:plain
*.json.goldenを追加

この設定によって、JSON形式の文字列を格納するためのgoldenファイルを認識できるようになりました。その他のファイルタイプについても同様です。

まとめ

goldenファイルを使用することでテストの可読性の向上が見込めますが、エディターの力を借りることでテスト作成コストも下げることができます。GoLandを使用している方はひとつ試してみていただけると幸いです。

golangtokyo#23 参加レポート

golang.tokyo #23 参加レポート

TL;DR

  • golang.tokyo #23に参加
  • tenntenn さんのポインタの話がわかりやすかった
  • まだまだGoのポインタわかってなかった。

golang.tokyo #23

平成最後のgolang.tokyoに参加してきました。LT枠で落選してしまったのですが、LT枠は落選しても参加できるとのことでお邪魔しました。

golangtokyo.connpass.com

絶対に分かるポインタ / tenntenn

docs.google.com

Memo

  • 変数
    • メモリ上で管理されている値を保持する領域
  • ポインタ
    • 変数の格納先を表す値、どこにしまってあるか
  • 型の表現方法
  • リテラルのポイント型
    • ex. *struct{N int}
  • ポインタのポインタ
    • **int: *int型のポインタ
  • ポインタ演算
    • &: ポインタ値取得
    • *: ポインタが指す先取得
  • ポインタが必要な理由
    • 代入
  • 内部にポインタ
    • slice, map, channel
  • go help test

Goをはじめるにあたって知っておいてほしいツールやテスト/mom0tomo, micchiebear

Memo

-> % go env GOROOT
/usr/local/opt/go/libexec

Delveを用いたデバッグ & pprofを用いたプロファイリング / 渡邉 光

Memo

感想

tenntennさんのポインタの話がわかっているつもりでもいざ質問されるとしっかり間違えたので、まだまだ基礎を抑え直さないといけないなと反省しました。あと、ベースターズビールがおいしかったです!

PHPerKaigi 2019 の「PHPでJVMに入門する」を聞いて

TL;DR

  • PHPerKaigiでのめもりーさんの「PHPJVMに入門する」がおもしろかった
  • 自分の知らなかったことを調べて残しておく

トークPHPJVMに入門する」

fortee.jp

@m3m0r7さんのPHPJVMに入門するという内容がおもしろかった。PHPJavaを動かすという力強いトーク

自分のトーク時間がちょうど裏で当日現場にて聞けなったので、YouTubeで公開されている動画を拝聴しました。

www.youtube.com

PHPバイトコードを読む方法など、いろいろPHPのことを知らなかったので、今回知らなかったことを調べてみます。

個人的な調べごと

PHPのfloat・doubleについて

トーク内で、PHPのfloat・doubleについて一瞬だけ触れていらっしゃたのあらためて調べてみる。

とりあえず、PHPの公式ドキュメント「浮動小数点数」をこちらに。

www.php.net

このページには、「浮動小数点数の精度」という警告があるんですね。

浮動小数点数の精度は有限です。 システムに依存しますが、PHP は通常 IEEE 754 倍精度フォーマットを使います。 この形式は、1.11e-16 のオーダーでの丸め処理で誤差が発生します。 複雑な算術演算をすると、誤差はさらに大きくなるでしょう。そしてもちろん、 いくつかの演算を組み合わせる場合にも誤差を考慮しなければなりません。

あぁ、よく聞くこのトラップって公式の警告としても掲載されているんですね。

IEEE 754 倍精度フォーマットは、IEEE Standard for Floating-Point Arithmetic、直訳すると「浮動小数点数算術標準」で、浮動小数点の計算で広く採用されている標準規格ですね。

よって、複雑な演算をすると誤差が大きくなる例として、こんな感じですね。

<?php

$iv = 0;
$fv = 0.0;

for ($i = 0; $i < 4000000; $i++) {
    $r = mt_rand(1, 1000);
    $iv += $r;
    $fv += $r / 10;
}
var_dump($iv);
var_dump($fv);
// int(2001061191)
// float(200106119.09999)
// ちょっと値がずれてる

さらに、十進数では正確な小数で表せる有理数、たとえば 0.1 や 0.7 は、 二進数の浮動小数点数としては正確に表現できません。 これは、仮数部をいくら大きくしても同じです。 したがって、それを内部的な二進数表現に変換する際には、どうしても多少精度が落ちてしまいます。

公式ドキュメント内の例を借りるとこういうことですね。

<?php

// 0.1 + 0.7 = 0.8 に見える
var_dump((0.1+0.7)*10);

// 0.1 + 0.7 = 7.9999999999999991118...
// これを切り捨てると7になる
var_dump(floor((0.1+0.7)*10));

精度の高い計算が必要な場合は、任意数学関数: BC Math関数gmp関数を使用するとのこと。トーク内でもgmp関数は紹介されていましたね。

きっと、トーク内で言及されていたfloat・doubleの問題点はもっと深いところにあるかもしれませんが、基礎的なところを抑え直してみました。

refs

バイナリリーディング

トーク中のスライドでバイナリを表示する際のコマンドに xxd を使っていて、「それなんだっけ」って思ったので基礎的なことだろうなと自分を恥じつつ調べます。

www.tutorialspoint.com

16進数dumpするlinuxコマンドですね。

$ man xdd
NAME
       xxd - make a hexdump or do the reverse.

SYNOPSIS
       xxd -h[elp]
       xxd [options] [infile [outfile]]
       xxd -r[evert] [options] [infile [outfile]]

雑に手元にあるGoファイルをxxdでdumpしてみます。

$ xxd main.go
00000000: 7061 636b 6167 6520 6d61 696e 0a0a 696d  package main..im
00000010: 706f 7274 2028 0a09 2267 6974 6875 622e  port (.."github.

バイナリレベルでの調査をしたいときに便利そうだなとおもいました。エミューレータ自作を試みたらこういうシーンに出会うのでしょうか。

refs

vld extension

PHPJavaを読むことで、PHPの中間コードが理解しやすくなるという話がありました。vld extensionの気持ちになれるということなんですが、「なるほど、vld extensionな(知らない)」という自分でしたので調べます。Vulcan Logic Disassemblerの略でvldとのことで、PECLで配布されています。

pecl.php.net

Provides functionality to dump the internal representation of PHP scripts

PHPスクリプトの内部表現をダンプする機能を提供してくれる拡張ということですね。

オペコードを覗いてみる記事で、@syossan27さんが、入門記事を書いてくださっていたので、ありがたく引用させていただきます。

<?php
    echo "Hello, PHP.";

の場合は、こんな感じでオペコードをダンプできるようですね。

$ php -d vld.active=1 -d vld.execute=0 test.php

Finding entry points
Branch analysis from position: 0
Jump found. Position 1 = -2
filename:       /Users/bps/test-php/test.php
function name:  (null)
number of ops:  2
compiled vars:  none
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   2     0  E >   ECHO                                                     'Hello%2C+PHP.'
   3     1      > RETURN                                                   1

branch: #  0; line:     2-    3; sop:     0; eop:     1; out1:  -2
path #1: 0,

refs

JVM Specification

JVM Specificatonについて言及されていました。JVMの気持ちになった経験がなかったので、少し読みに行ってみます。

docs.oracle.com

Chapter 1 Introductionの歴史の話がエモい気持ちになってよかったです(小並感のある感想)。

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-1.html#jvms-1.1

感想まとめ

PHPわかっていなかった」という気持ちになったのでたいへん刺激になるトークでした。トーク内の実装紹介スライドにて、「constant pool countは歴史的理由で-1する」という話があって、歴史的理由を調べてみたものの見つけられなかった...。でも、そもそもこの実装の背景を理解できているかというと正直理解できていないので、精進します。