バージョン管理システムってなんだ
職場でSubversionを使ってるはずなんだけど、自分含めてみなさんかなり理解が怪しい。そもそもバージョン管理とは何か、というのをまとめたいのでこっそり書き足してまいります。
バージョン管理史ざっくり
RCS(Revision Control System)
- 初版:1982 年
CVS(Concurrent Version System)
- 初版:1990年
Subversion
- 初版:2000年
Git
- 初版:2005年
参考
Emulsification ってなんだ
パスタをゆでて食おうと思ったときにレシピ検索をしたら Emulsification(乳化)って言葉を知った。英単語で呼ぶとかっこいいっす。
まず、乳化とは何かというところなんですが、本来混ざり合わない水と油が、均一に混ざり合った状態のことを言います。
とは言っても、水と油だけでは完全に混ざり合いません。ドレッシングをイメージすると分かりやすいでしょうか。
市販の瓶に入っているドレッシングって、普通に置いておくと下の部分に水分、上の部分に油分があって、食べる直前に振りますよね。振ると水と油が混ざり合ったようになるけど、またしばらくすると分離する。
しかし、マヨネーズは酢(水分)と油が混ざり合い、戻ることはありません。それは、たんぱく質(たまご)が入っているからです。たまごが乳化を安定させる役目をしています。
では、パスタソースの場合はどうなのかと言うと、茹で汁に溶け出したパスタのでんぷん質が、その役割を担います。
この乳化によって、オリーブオイルと水分が混ざり合い、とろみのあるソースとなり、麺によく絡んで美味しく食べられるというわけです。
わかりやすい。
自作gemのバージョニングについて
ここ見れば良さげ。
Ruby技術者認定試験(Gold)落ちた
前からRuby触ってるし大丈夫だろうと思ってて、前日にちょろっとやって受かる予定だった。結果は56点だった。馬鹿だった。
ポイント
- 「Ruby技術者認定試験改訂のお知らせ」にある1.8->2.1の変更点
- クラスの継承関係
- メタプログラミング
リンク
試験前に読んだものや、試験終わった後にもやもやを解消するのに役立ったリンクなど。
本
本はこの三冊がいいと思う。3冊ちゃんと読み倒せばGoldなんて簡単すぎるくらいかもしれない(自分はというと、Effective Rubyは読みかけ、メタプロRubyは読んでない。あと頭が悪い)。
公式問題集はいろいろひどかったから載せない。
もう1回くらい今月末に受けて受かりたい。1万5000円もかかるのが苦しい。とはいえ勉強やはり楽しい。しかし1万5000円...(以下無限ループ)
何で難しいのか・難しいものとどう向き合うか
難しさについて。
前提を知らない
前提を知らないと、難しいと感じる。=> 遠くにある高級そうなものではなくて、自分が理解できる近場の疑問を一つずつ解消していく。
訓練を必要とする
訓練を必要とするものは、素でいきなりやると難しく感じる。 => 訓練に時間を費やす決断をする。
必要がない
自分に必要がないものを理解するのはとても難しい => 必要が無いならやらない。必要だと感じたときにやる。
頭字語コマンドを展開するwdimというコマンドラインツールをgemとして公開しました
wdimという名前でgemを公開しました。ダブリューディムとかダブディムって読んでください。意味は What does it mean の略です。
シェルでwdim ls
と打つとlist segments
が返ってきます。つまり、頭字語やら略語やらジャーゴンになっていてひと目では理解しづらいUNIX/Linuxコマンドを展開してくれるコマンドラインツールになります。
使い方
インストール
gemコマンドが使える環境で以下を打ち込んでください。
$ gem install wdim (権限がないとかいわれる場合は) $ sudo gem install wdim
つかう
$ wdim cd
change directory
経緯
こちらに書きました。
今後
正直、まともに使えるようになる前にgemとしてリリースしてしまいました。ローカルでインストール作業(git clone
してgem build
してgem install
)してくれる人は少ないと思うので、ちょろっと試す際に試しやすくするためだけに公開しています。
今後はディクショナリを充実させたり、シェル作業中にパッと目につくような装飾をつけたり、また、起動の速度が気になってきたりしたらrubyではなくCで書いてHomebrewで配付したりとかそういうことを考えています。
ディクショナリ(現状はls
のようなコマンドに対してlist segments
のような意味が記述されているymlファイル)がなにより大事なのです。この頭字語コマンドの意味知ってるよ~という方からのプルリクお待ちしてます。頭字語の意味は検索すればたいてい出てくると思いますが、議論があるものもあり、微妙なものはIssuesで話しあえたりしたら楽しいなと思ってます。
UNIXコマンド ls とか mv とかのソースコードの場所
自分でコマンドラインツール的な何かを作りたい時に参考にするために、ls
とか mv
とかのソースは手元に置いときたい。
Coreutils - GNU core utilities の Downloads というとこからダウンロードできます。ダウンロードしたものは以下のコマンドで解凍できます。
$ tar Jxvf coreutils-8.25.tar.xz
さて、早速 coreutils-8.25/src/mv.c
とか読むぞーとおもむろにタグファイルを作って(ctags -R
)中身を読もうとしたところ、オプションをパースする場所を見つけました。getopt_long
か〜。中身が見たいぞ〜。と思ってタグジャンプしようとしたら、できないですね。これを見るには getoptというライブラリを見ないとだめですね。というわけで今度は The GNU C Library からglibc をダウンロードします。getopt.c が glibc-2.23/posix
下にありました。getopt_long
という関数は同ディレクトリの getopt1.c にありました。めでたしめでたし。
coreutils-8.25/lib/getopt1.c
にありました。めでたしめでたし。
「日本のWebエンジニアの大半が、変化に対応しきれなくなっている件について。」を読んだ感想
以下の記事がはてなブックマークで盛り上がっていました。TOEIC940点の人すごい。。。
中でも以下が一番ぐっと来ました。
UNIX/Linuxコマンドを英語で学習すると、pwd は「Print Working Directory」の略なので、そのまま英語の意味からコマンド名を覚えることができるなど、様々なメリットがありました。
名前はたいていそのツールが何を解決するのか、とかどんなアイデアなのか、とかを表しています。それを理解すると覚えやすいし、コマンドにどんなオプションが存在するのかも予想しやすい。だけど、UNIXコマンドのようにやたら頭字語になっていたりギークっぽい専門語となるとスルーしたくなります。僕はman
コマンドを使う時しばらくそれを男性のことだと思っていたし(正解はman man
でわかります)、Linuxが再帰的な頭字語(Linux is not unix)って聞いた時、なんだよそれって気持ちになりました。
変化激しいとこでやっていくのにはたくさん覚え続けなければいけないのはわかってるんですが、ツールの使い方を覚えて覚えて覚え続けるというのは人生を浪費しているような気もします。ツールの名前なりそれが作られた経緯やアイデアなどに着目して効率よくキャッチアップできるマンになりたいです。そういう時にコンピュータサイエンスなりはたまた別分野の教養なり知性なりなんやかんやが役立つと思うんだけど、結局どう考えても自分には無いものだらけなので今のところは「頑張る」以外になさそうだなと思いました。
もう今年24歳になるというのに「頑張る」しか言えることがなくてつらい...。以上です。
あわせて読みたい
追記
UNIXコマンドで頭字語やわけわからん名前付けのものを取り出して意味を出力するCUIツールの試作をつくりだした。たぶん難しいことはないので、CUIツールの基礎とパッケージの公開の仕方を学んで、あとはひたすら辞書を充実させて、自分と同じように頭字語に悩む人にとって役立つものにしたい。
何が難しいのかを切り出すだけでも難しい
他人が書いたソフトウェアを動かして困ったことが起きると、問題の特定に7割くらいの時間を使う。経験があったり仕様が把握できていたりすれば時間は短くなると思う。簡単なスクリプトならまだしも、20本のスレッドが一つのプロセス内で互いにタイミングをはかってやりとりしているような複雑なソフトウェアを改修するとなると、何が難しいのかを切り出すだけでも難しい。ソースコードの行末コメントに /* bug */
とだけ付け加えられていて恐怖を煽ってくるものもある。それを書いた人はもうこの職場にいない。
問題の特定に(自分の頭の回転が遅いというのはあるけども)時間がかかると何が辛いのかというと、仕事をしてない感がすごい。仕事をしてない感がすごいと自己嫌悪に陥る。すると、冷静な判断を下したりとか長期的な視野を持つことができなくなっていく。良いソフトウェアは書けず、書こうとする気力も失っていく。
何か複雑なものと向き合うときに、何が難しいのかを切り出すだけでも難しいということを認識する努力も必要なのかもしれない。優秀なエンジニアでさえ Yak Shaving を避けられないのだから、停止しているような時間にいちいち後ろめたさを感じていたら、精神がもたない。
あわせて読みたい聴きたい
Ruby製のウェブサーバライブラリWebrickのソースコードを読む
そういや一年前、「ウェブサーバーのこと知りたい -> Rack読もう。」となって挫折した。少しずつ暖かくなって意識が高まってきたし、今やっている仕事がずいぶんと(すくなくともRailsアプリ書くのと比較すると)低レイヤーなところなので、良い感じの相乗効果を狙って今のうちにサーバーについて理解を深めておきたい。そういうわけで、今春はWebrick読もう。
読みかた
今度は挫折したくない。以下の手法に従って読む。
また、Cのソースにも触れることになると思うので以下も参考にする。
使うもの
動的解析
基本的に解析は動的解析から始めるのがよい。 静的解析とは、多かれ少なかれ、プログラムの動作を予想することである。 対して動的解析で見るのは事実である。 まず事実を見ておいたほうが方向付けがしやすいし、間違いも減る。 最適化する前にプロファイルを取れ、というのと似ているだろうか。 事件解決はまず現場から、というのでもよい。
とのこと。まずは動かす。
サーバー起動
ruby -rwebrick -e 'WEBrick::HTTPServer.new(:DocumentRoot => "./", :Port => 8000).start'
なお、これは以下と同等(r オプション使うの初めてだ)。
ruby -e 'require "webrick";WEBrick::HTTPServer.new(:DocumentRoot => "./", :Port => 8000).start '
[2016-03-26 14:03:45] INFO WEBrick 1.3.1 [2016-03-26 14:03:45] INFO ruby 2.2.3 (2015-08-18) [x86_64-darwin14] [2016-03-26 14:03:45] INFO WEBrick::HTTPServer#start: pid=4563 port=8000
リクエストを投げる
クライアントとして、別のシェルを開いて以下を実行する。
curl localhost:8000
(クライアント側)
$ curl localhost:8000 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> <HEAD> <TITLE>Index of /</TITLE> <style type="text/css"> ...(以下略)
(サーバー側)
localhost - - [26/Mar/2016:14:04:04 JST] "GET / HTTP/1.1" 200 4076 - -
クライアントからHTTPリクエストを投げたらちゃんとハイパーテキストを返してくれたので、ウェブサーバーとして機能したと言える。サーバー側のログには時刻やHTTPメソッド・プロトコルのバージョン・ステータスなどが出されている。
静的解析
前準備
さすがにGithubのウェブサイト上でファイルを一つ一つブラウジングして理解できる気がしないので、「ソースコード完全解説ガイド」に従っていくつかの前準備を行う。
ドキュメントを読む
今回は http://docs.ruby-lang.org の説明を参照する。
汎用HTTPサーバーフレームワークです。HTTPサーバが簡単に作れます。
WEBrick はサーブレットによって機能します。サーブレットとは サーバの機能をオブジェクト化したものです。 ファイルを読み込んで返す・forkしてスクリプトを実行する・テンプレートを適用する など、「サーバが行なっている様々なこと」を抽象化しオブジェクトにしたものが サーブレットです。サーブレットは WEBrick::HTTPServlet::AbstractServlet の サブクラスのインスタンスとして実装されます。
WEBrick はセッション管理の機能を提供しません。
ソースコード入手
Webrick はRuby の標準ライブラリなので、Githubの ruby リポジトリから入手する。
git clone git@github.com:ruby/ruby.git
tags ファイルつくる
webrickはlib/下にある。そこでctagsコマンドを実行する。
cd ruby/lib/webrick ctags -R
参考:ctagsと連携するように環境を構築する - Qiita
ファイル構成を見る
MacBook-Pro:webrick gaaamii$ tree . . ├── accesslog.rb ├── cgi.rb ├── compat.rb ├── config.rb ├── cookie.rb ├── htmlutils.rb ├── httpauth │ ├── authenticator.rb │ ├── basicauth.rb │ ├── digestauth.rb │ ├── htdigest.rb │ ├── htgroup.rb │ ├── htpasswd.rb │ └── userdb.rb ├── httpauth.rb ├── httpproxy.rb ├── httprequest.rb ├── httpresponse.rb ├── https.rb ├── httpserver.rb ├── httpservlet │ ├── abstract.rb │ ├── cgi_runner.rb │ ├── cgihandler.rb │ ├── erbhandler.rb │ ├── filehandler.rb │ └── prochandler.rb ├── httpservlet.rb ├── httpstatus.rb ├── httputils.rb ├── httpversion.rb ├── log.rb ├── server.rb ├── ssl.rb ├── tags ├── utils.rb └── version.rb
読むの開始
先ほどのワンライナーをふたたび見る。
WEBrick::HTTPServer.new(:DocumentRoot => "./", :Port => 8000).start
まずは以下からざっくりと追う。
- HTTPServer.new
- HTTPServer#start
HTTPServer.new
インスタンス初期化時に何をしているのか。mount
というメソッドでパスにサーブレットを割り当てているようだ。あとは @virtual_hosts
という配列を初期化している。
HTTPServer#start
HTTPServerのインスタンスメソッドstart
見ようとしても、ない。継承元のGenericServer
のものだとわかる。
GenericServer#start
さて、このstartメソッドは何をしてるのか。コメントがあるので、それを見る。
137 ## 138 # Starts the server and runs the +block+ for each connection. This method 139 # does not return until the server is stopped from a signal handler or 140 # another thread using #stop or #shutdown. 141 # 142 # If the block raises a subclass of StandardError the exception is logged 143 # and ignored. If an IOError or Errno::EBADF exception is raised the 144 # exception is ignored. If an Exception subclass is raised the exception 145 # is logged and re-raised which stops the server. 146 # 147 # To completely shut down a server call #shutdown from ensure: 148 # 149 # server = WEBrick::GenericServer.new 150 # # or WEBrick::HTTPServer.new 151 # 152 # begin 153 # server.start 154 # ensure 155 # server.shutdown 156 # end
意訳する。
「サーバーを起動してコネクション毎にブロックを実行する。このメソッドはシグナルハンドラあるいは他のスレッドの#stop
か#shutdown
によってサーバーが停止するまでreturnしない。(以降、例外捕捉の説明)」
スレッド <--(コネクション)--> クライアント スレッド <--(コネクション)--> クライアント スレッド <--(コネクション)--> クライアント
という感じで、スレッドとコネクションとクライアントが1対1対1の関係になるのがこのstartメソッドを見るとわかる。
この処理はbegin節で囲まれてた中で無限ループしていて、先のコメントにあったようにシグナルハンドラなんかによって停止されたときにこの節を抜ける。するとensure節が実行されて、サーバーが停止する。
というわけで、実際のコードの中身について、大事そうなものをかいつまんで見てみていく。
- server_type.start
server_type.start
server_type にはデフォルトではWEBrick::SimpleServerとなるので、このstartメソッドをみる。
(server.rb) 27 class SimpleServer 28 29 ## 30 # A SimpleServer only yields when you start it 31 32 def SimpleServer.start 33 yield 34 end 35 end
yield
の一行しかない。渡したブロックそのまま実行するということがわかる。
setup_shutdown_pipe
よくわからない。パイプってなんだ(あとでみる)
svrs = IO.select([sp, *@listeners], nil, nil, 2.0)
IO.selectが何をしているのか。Rubyの組み込みライブラリなので、まずドキュメントにあたった方がよさそうだ。
http://docs.ruby-lang.org/ja/2.2.0/class/IO.html
IOクラスとは、
基本的な入出力機能のためのクラスです。
とのこと。では、このselectというメソッドはなにか。
http://docs.ruby-lang.org/ja/2.2.0/class/IO.html#S_SELECT
与えられた入力/出力/例外待ちの IO オブジェクトの中から準備ができたものを それぞれ配列にして、配列の配列として返します。 タイムアウトした時には nil を返します。
ソースも見てみる。IOクラスはwebrickの中には見つからないので、今回は pry-doc というgemを使ってpry(対話環境)から場所を見つけることにする。
[1] pry(main)> show-source IO.select From: io.c (C Method): Owner: #<Class:IO> Visibility: public Number of lines: 22 static VALUE rb_f_select(int argc, VALUE *argv, VALUE obj)
Cのソースで、rb_f_select
という関数だということがわかった。
start_thread
ThreadGroup#add
ThreadGroup の定義元に飛びたいけど、これは組み込みライブラリ、つまりCのソースになるので、webrickの中にはいない。ということで、今回は pry-doc というgemを使ってpry(対話環境)上から場所を見つけることにする。
pry> show-source ThreadGroup#add
とすると、このメソッドの定義元がわかる。どうやらthread.c にある thgroup_add
という関数らしい。
IO.select([sp, *@listeners], nil, nil, 2.0)
書き途中です。
Webサーバについてのメモ
一から調べだした。
雑理解
まず、調べる前に自分の雑理解を書き出す。
- WebサーバはクライアントからHTTPリクエストをもらってHTTPレスポンスを返す(HTTPサーバだ)。
- データのやり取りの際には recv とか write みたいなUnix のシステムコールで送受信を実現することになる。
- たくさんのクライアントから同時にリクエスト来ても処理できるようにスレッドやプロセスを分けるやり方もあるけど他の方法もある(らしい)。
- TCP 接続に必要な情報はIPアドレスとポート(だけ?ほんとに?)。
OSSを読む
- GitHub - apache/httpd: Mirror of Apache HTTP Server. Issues: http://issues.apache.org
- https://github.com/python-git/python/blob/master/Lib/SimpleHTTPServer.py
- https://github.com/ruby/ruby/tree/trunk/lib/webrick
参考
コンピュータへの畏敬みたいな感情
@moutend さんがこんなエントリを書いてバズっていた。
http://qiita.com/moutend/items/2696139d0b96805ea415qiita.com
何がすごいってもちろん @moutend さんがすごいだけの話でもあるんだけど、やっぱりこういうの読むとコンピュータが人間の能力拡張してるよすごいなー、と感動する。そういえば以前「ハクティビズムとは何か」とか「2045年問題」とか、あとは小飼弾さんの「コードなエッセイ」とかでそういう話を読んで、ろくにプログラミングもできないくせにコンピュータすごいと確信したのを思い出した。仕事としてコンピュータを触っていてうまくいかないことが多いと忘れがちだけど、身体能力を拡張して何かできるという全能感みたいなものを少しでも感じられるようにコンピュータを使っていきたい。そのためにはコンピュータへの畏敬みたいな感情を時々思い出していけたらいいと思う。あともう一度言うけど、@moutend さんはすごい。