Tallman

技術とか読書とかいろいろ

Ginza.rb#80でLTをしてきた

 当日の概要

Ginza.rb#80でLTをしてきた

ginzarb.doorkeeper.jp

LT

イベントの空気感的にはかなりカジュアルよりだったけど、社外でのLTは初めてでガチガチに緊張していた。当日のスライドは以下。

speakerdeck.com OSSへのコントリビュートを一年やってきて思ったところを発表した。koicさんが引用してくれたりyagiさんにいい話きけたといってもらったりして嬉しかったです。

他の人の発表も、「2.7からのパターンマッチは実は右辺代入だった!?」とか「同じシステムってなんだ?」とか「rubocop-minitestのリアルタイムリリース」とか「自分の一年間やってきたこと」とか「fill_inがモーダル開閉のfocus()でうまく機能しなくなる」とか「Kaigi on RailsはRubyKaigiと初心者向けの中間くらいの難易度で開催したい」とか色々な話題のLTがあって面白かった。

まとめ

Ginza.rb、毎回willnetさんやy-yagiさんのためになる話がきけるのでRuby好きの人にはオススメの勉強会。

graphql-rubyにコミットした

業務でgraphql-rubyを色々いじってたら「おや?」と思う挙動があった。調べてみると同じ内容でissueを立てている人がいた。

github.com

graphql-rubyでは_idといった引数を受け取った時にloadsオプションを指定しているとHogeSchema.object_from_idを呼んでレコードを取り出す動作を簡潔に書くことができる。 だけど実はこれはinput_object(いくつかの引数の型をまとめて定義したもの)として定義しないと使えなかった。(Mutaionでも引数につかえるのだけれどMutationの引数は実質input_objectの定義なので同じ。)

前回graphql-rubyをふんわり読んで色々脳内地図があり、issue内でもオーナーのrmosolgo氏が修正することに前向きそうだったのでPRを出した。

github.com

内容はinput_type内の処理をそのままfiledの引数の処理に持ってきたのと、内部で使っているload_application_objectが呼び出し元の@contextのリーダーメソッドに依存していたので外部から注入できるように変更したというもの。

rmosolgo氏が色々レビューをしてくれてありがたかった。(最後に氏みずからinput_object内の処理も少し書き換えるコミットを積んでくれた。不要にlodasに対して実行されていたコードが減ったので、PRの主目的以外の恩恵もあると思う)

GraphQLは仕事で使い始めたばかりだけれどテストコードやらみると色々勉強になって良い。

みんなのコンピューターサイエンスとプログラマの数学を読んだ

最近以下の二冊を読んだ

みんなのコンピュータサイエンス

みんなのコンピュータサイエンス

プログラマの数学第2版

プログラマの数学第2版

数学、コンピューターサイエンスに関する本を読んだ。

本を読んだ理由

僕は文系卒であり、新卒で入った組織もソフトウェアエンジニアリングとはあまり関係ない場所だった。
自分がコンピューターサイエンスの基礎がわかっているとは思えないし、アルゴリズムをものにしているとも思えない。実際AtCoderにはちょくちょくでているものの未だレートはこんな感じ。大体ABCのCまでなんとか解いてDには歯が立たない感じだ。

f:id:sasa5740:20200122203533p:plain

だいたい良いプログラマーとは?みたいな記事をみるとコンピューターサイエンスを学ぼう、アルゴリズムを学ぼうと書いてある。
Matzもいってるので多分正しいのだと思う。誰がいっているのかで判断するのは良くない 海外の企業も採用時にはまずアルゴリズムについてしっかり確認する印象がある。
そういった記事を読んでとても不安になり本に助けを求めた。

なんにもわからない

論理、確率、帰納法、動的計画、データ構造は、説明できるほど理解できる時が来るのだろうか、競プロをやっていけば(周りよりスピードはゆっくりだろうけど)ついていくのだろうか。 「再帰はスタックに構造をいれていく」とか「5つのユニークな要素から3つ取り出す順列は5 * 4 * 3で60通りあるとか、順序を考えないと順序考えた分を割って5 * 4 * 3 / 3 * 2 * 1で10通り」とか読んでなんとなく意味はわかっても日本語が少し変わって問題を少しひねられたらなにもできない気がする。
根本は難しいことをできるだけ細分化して考えるということだと思う。しかし与えられた問題に適切なアルゴリズムを出す自信が全く無い。一歩ずつ頑張るしかないのだろう。

その他

「コンピューターサイエンス」と仮想メモリとかレジスタ、スレッド、プロセス、I/O、(メモリの方の)ヒープ、(スレッド毎の)スタック、カーネル、ソケットといった(多分)UNIXからつらなる概念は別扱いなのだろうか? この他にもHTTPだったりRDBMSだったりなんにもわからんなと思った2020年1月22日だった。

RustでGithubのissueひっぱてくるCLIアプリを書いた

Ruby、Elixirときて完全に別軸の静的型付け低級言語としてRustで遊んでいる。
お正月に泣きながらRustのコンパイラといろいろしてた。

github.com

ユーザー名とレポジトリ名を下のように渡すと
github-issue rails rails  

number |title                                                                                          |created_at           |

38237  |Update caching_with_rails.md                                                                   |2020-01-15T02:29:53Z |

38235  |Move advisory lock to it's own connection                                                      |2020-01-14T17:54:27Z |

38234  |Rails 6 : config.require_master_key=true doesn't raise an error if key does not exist          |2020-01-14T15:49:12Z |

38229  |Prevent `has_one` `build_association` from `touch` parent record if the record isn't committed |2020-01-13T22:11:50Z |

38226  |Active Record unit tests fail with MySQL 8.0.19                                                |2020-01-13T14:59:02Z |

という感じで標準出力するアプリを書いた。プログラミングElixirの題材をRustで書き直したやつ。まだまだテストでのモックとかやるべきことはいっぱいある。

Rustつまづきポイント

そもそもコンパイラになんとか通してもらうために無理した書き方をしている自覚があり、しかもきれいにする方法がわからないので書くたびに自分の無力感が高まって泣いていた。

文字列型の種類が複数

Rustでのいわゆる文字列には、メモリ長が決定されている組み込みの&strと、メモリ長が固定されていない標準ライブラリにあるString型がある。String型はヒープ(スレッド間で共有できるメモリ領域)に格納できて可変。 実際にコード内で "string"のように書くと&str型になるのでGithubからのレスポンスをStringとして扱う時に色々変換しなくてはならず辛かった。多分もっといいやり方があると思うので助けて。

Result型とOption型

つまづきポイントに入れてるけど同時にRustの優れてるポイント。多くの関数がこの2つのうちどちらかを返すことが多い。
OptionはNoneもしくは値を返すという型。 Noneはnullのようなもの。 返り値書くときにはSome(1)Noneという書き方をする。

Resultは例えばrunみたいな関数があったとして
pub fn run(args: Vec<String>) -> Result<i32, Box<dyn Error>>
ようにエラーを返すかもしれないことを明記できる型。
返り値書くときにはOk(1)Err(ParseError)という書き方をする。
これらの型で返された値はunwrap()をするか process(args)?のように末尾に?演算子をつけて例外やNoneが出たら関数全体としてエラーやNoneを返すということを明示することができる。しかしどんな形がベストなのかイマイチつかめない。ここではめったにエラー起きないだろうってところはunwrap()でそれ以外は?という感じで使えばいいのだろうか。
ちなみにNoneやErr()に対してunwrap()するとpanicする。unwrap_or_else()なんかもあるのでやりようはありそう。

所有権

もう全然スマートな解決方法がわからない。無理やりclone()したりして逃れている。
rows.as_array().unwrap().to_owned()
こんなコードも書きながらもっといいやり方ないのかと泣いていた。

Rustのよかったところ

よかったところというとおこがましいという気持ちになるくらいには使いこなせてないんだけど書く

パターンマッチ

最高of最高

Result型

コードを読む側、使う側としてResult型はとても便利。エラーを?でキャッチできるしこの関数にエラー処理が任されているんだなというのがひと目で分かる。 そもそも型というものがコールドリーディング時に便利。
たぶんOptionとResultは慣れると余計なエラーやNullの処理挟まなくて良くなるので便利そう。

ロスコンパイル

最終的に機械語になって人に配布できるというのがRubyから入るとかなり画期的に感じる。 一応このアプリもタグ付けしたらGithubActionで複数OSでバイナリをビルドしてzipにしてリリースするということができた。(linux環境だと何故かOpenSSLがないと言われてリリースビルドが通らない。libssl-devを直接入れても再現するので困ってる)

cargo

Elixirのmixと同じで、ライブラリやテストが言語に組み込まれているのもモダンな言語感があってよかった。リンターもしっかり搭載。

ビルド通ったときの安心感

僕はCとかの低級言語はなにも触った事ない。けれどよく未定義動作の処理に困る話は聞く。その中でRustでコンパイラ通るということはメモリを贅沢につかってこそすれ危険に利用してないことなので安心感がある。

俺は今Rustというかっこいい言語で開発しているという謎の興奮

これが9割

まとめ

Rust本当になにもわからん。でも実践Rust入門は良書です。

2019年を振り返る

はじめてのふりかえり

1月

  • エンジニアとして働いてなかった。2月に転職することがわかってたのでソワソワしていた気がする。新卒から一年と十ヶ月の短い期間だったけど迷惑かけまくったなぁと反省しています。
  • 東京に引っ越した。
  • 有給消化中にOSSにはじめてコミットした。嬉しくて書いた記事が思ったより反響があり、別記事内で言及してくれる人もいて嬉しかった。同時にQiitaの拡散力怖いと思ったのでメインはブログにしようと思った。 qiita.com

2月

  • 業務委託として今の社で勤務を始めた。出社時間が自由すぎてカルチャーショックだったのは覚えている。自分のかいたコードがチームのリポジトリのmasterにマージされた時の感動は忘れられない。
  • 読んだ本の中だとこれが印象に残っている。 sasa5740.hatenablog.com

3月

  • 業務で一つリリースがあった。といっても僕はアプリケーションのコードを書いただけなのだが。
  • 初めてエンジニアとして稼いだお金が口座に入った。こんなんでもらってええんかという気持ちになった。
  • この頃から読んだ本をアウトプットしようと思って色々やった。

sasa5740.hatenablog.com

sasa5740.hatenablog.com

  • Ruby2.7で追加されるパターンマッチに関してブログを書いたら実装した人から反応をもらえた。ブログ書くモチベの源泉となる体験だった。

sasa5740.hatenablog.com

4月

  • 基本情報技術者試験を受けた。この頃はポート番号とIPアドレスの区別もふんわり状態だったので勉強になった。合格証書が思ったよりしっかりしていて良かった。
  • 仕事ではCSSに苦労していた気がする。

5月

  • 仕事して本を読んでいた。

sasa5740.hatenablog.com

sasa5740.hatenablog.com

特に大規模サービス技術入門はすごい良書で、この後にプロセスとかメモリとかの勉強に触れようと思ったのはこの本のおかげだ。

6月

  • SQL実践入門を読んだ。これも良書でもっと早く読んでおけば良かったなと思った。

sasa5740.hatenablog.com

7月

  • 自分のPCをThinkPad X1 Carbonにした。Ubuntuのほうがコスパ良いじゃん!とイキってUbuntuにしたのだが、職場がMacBookの状態で更に別の環境を手入れするのは面倒だった。次はMacBook買うと思う。
    とはいえUbuntuをいれていろいろトラブルシューティングしている内にUNIXコマンドの知見がたまったのでそれはそれで良かった。開発環境も設定さえちゃんとすれば不満なく使える。

sasa5740.hatenablog.com

  • 新しいPCを勝ってモチベ爆上がりしたのでGemを書いた。Pryを頑張って読んだ気がする。面識ない人からPRをもらって飛び跳ねたのも覚えている。エイリアスで十分なことに気づき特に使ってない。

sasa5740.hatenablog.com

8月

  • 引き続き別のGemを書いた。rails consoleコマンドの実装を頑張って読んで書いた。ローカルではしっかり動作するの確認したんだけど職場のDocker環境でうまく動かなくて困っている。あとRailsのバージョンへの依存も激しすぎる。名前はかなり気に入っている。

sasa5740.hatenablog.com

  • Linuxの本を読んだ。これまたすごい良書で自宅環境をUbuntuにした利点も感じた。

sasa5740.hatenablog.com

9月

  • ポエム書いた

sasa5740.hatenablog.com

  • この頃Ruby以外の言語もちゃんとやらなきゃなという気持ちが高まりElixirを学習し始めた。

Elixirについて社内LTで発表したよ - Tallman

tokyo.ex#13 elixir本体ソースコードもくもくリード会に参加してEnum.tally書いてみた - Tallman

10月

  • 株式会社グロービスに正式にジョインした。
  • 応用情報技術者試験を受けた。これも無事に受かったので嬉しい。
  • ElixirへのPRがマージされた。大きめのOSSへのコミットはこれが初めてであり、ましてやプログラミング言語だったので相当嬉しかったことを覚えてる。強引感が否めなかったのでちょっと反省している。

github.com

  • HacktoberfestだったのでRailsにもパッチを送ってみた。放置されてるけど。後日OSSパッチ会でkamipoさんに聞いてみると優先順位が低いとのことだった。kamipoさんはすごい人。

github.com

11月

  • Punditにコミットした。仕事での困りをOSSへの貢献に変えるというのは一度やってみたかったので良かった。今年一番のPRだったと思う。

github.com

  • 社内でLearning GraphQLの読書会をやった。自分で始めた最初の勉強会だった。英語の本しかでてなかったりで最終的に参加者が二人になってしまい進め方を反省した。

12月

qiita.com

  • 静的型付け言語もやりたいなぁと思って最近Rustを書いてる。とりあえず型ジェネリクスというやつを完全理解した。所有権とライフタイムで脳が爆発している、メモリ管理を学ぶのに良さそう。
  • 会社でReal World Httpの読書会を始めた。これを写経しているだけでFindyで一人前のGopherと認定されるぞ!

まとめと来年の抱負

今年のはっきりとした成果は基本及び応用情報技術者の取得とElixirのコミットくらいだろうか。
2020年は

  • なにかしら外部の勉強会で登壇
  • 大学院に進学

の2つを達成したい。 JAISTの社会人コースの見学にいった。年始に願書をだそうと思っている。
僕はエンジニアとして一緒に働きたいと思っている人がいる。その人に少しでも近づけるようやっていきたい。

「エンジニアの知的生産術」を読んだ

読んだ理由

エンジニアとして働き始めたこの一年間、どうにも自分が闇雲に進んでいる感覚が拭えなかった。
目標にしている人はたくさんいるのだけれど、果たして自分は効率的に目的に向かっているのか?という疑問を感じるようになってきたので読んだ。

新しいことを学ぶには

情報収集、実践、応用はよく学習本であるやつという感想だったが、具体的に技術書を写経することについて述べられているのが面白かった。写経は効率が低いけれども写経しないと理解できないほどの問題に立ち向かわないとコンフォートゾーンから出れない、と書かれていた。最近自分もRustの技術書をヒィヒィ言いながら写経しているのだけれど、この本で少し勇気づけられた。
写経するときも頭を使って書き換えやコメントを利用しようとも書かれていた。このあたりは自分もよくやるのでこれからもやっていきたい。
逆にRubyの本を一から十まで写経するのも効率が良くなかったなという反省もあった。

やる気を出すには

この本ではタスクを一つに絞り、タスクを小さくするためにポモドーロ・テクニックを活用することが書かれていた。
タスクをマルチにするのは良くないのは自分も感じていて、同期的にタスクをこなすというのは腑に落ちた。 このブログもポモドーロ・テクニックを使って書いている。スマホを見ないと決めるのは大きな効果があった。

記憶を鍛えるには

この章で面白かったのは、一度読んで思い出してからさらにもう一度読むという「思い出し学習」が単に本を四回読んだだけの人より学習効果が高かったというものだ。
「思い出し」というのは記憶の穴を自己認識し危機感を得られる行為らしい。技術書を読んだあとに目次をみて内容を説明できるか?というぐらいなら真似しやすいだろうか。ブログを書くにのは二回目の通読のような気がするので、ブログを書く前に「思い出し」をやるといいかもしれない。

効率的に読むには

読書の目的は大雑把な地図、思考の道具というのが面白かった。自分の場合何しろ基礎体力が足りないと感じているので大雑把な地図がほしい。そのためにいろいろな分野をつまみ食いする。というのが大事なフェーズなんだろうと感じた。 とりあえずブログを書いて人に教えるを重点的に意識したほうが良さそう。

何を学ぶべきか?

戦略をもって学ぶのが良いということが書かれていた。 差別化戦略について語られていて、A要素だけでは人に勝てないならB要素もかけ合わせて卓越することが重要だと書かれていた。よくキャリア戦略なんかでも語られている考え方だと思う。「境界をまたぐ、複数の組織に属する」というのは本やOSSでも達成できることのような気もするけど、実際に体験するためには働いたり留学なり何かしら義務を持ったほうがいいのだろうか。

まとめ

現実の行動で変わったことは

  • ポモドーロ・テクニックを使うようになった
  • 広く片っ端からつまみぐいすることも悪くないと考える様になった。
  • 本を読んだあとに目次をなめる行動をするようになった。

ぐらいだろうか、周りがすごいエンジニアばかりで差別化するというのがなかなか思いつかない。

「食事する哲学者」で学ぶデッドロック

最近 プログラミング言語Rustを読んでるのですが、並行処理のチュートリアルで「食事する哲学者」という問題を知りました。

昔々、裕福な慈善家が、5人の高名な哲学者が宿泊できるカレッジを寄付しました。それぞれの哲学者には思索活動にふさわしい部屋が与えられました; また共用のダイニングルームもあり、そこには丸いテーブルが置かれ、5人それぞれが専用で使うイス5脚で取り囲まれていました。 彼らはテーブルを反時計回りに座ります。哲学者の左側にはそれぞれ金のフォークが配され、 中央には大きなボウルに入ったスパゲッティが常に補充されていました。哲学者は大半の時間を思慮に費やすのですが; 空腹になった時は、ダイニングルームに出向き、自分専用のイスに座り、左側のフォークを取上げ、スパゲッティに突き刺します。 しかし、絡まり合ったスパゲッティを口元まで運ぶには2本目のフォークが必要でした。なので哲学者は自分の右側にあるフォークも使う必要がありました。 食べ終わったら両側のフォークを元に戻し、席から立ちあがって、思索活動を続けます。 もちろん、1本のフォークは同時に1人の哲学者しか使えません。他の哲学者が食事したければ、 フォークが再び戻されるまで待たねばなりません。

並行処理でデッドロックが起こりうる問題です。

f:id:sasa5740:20191127212423p:plain
丸が哲学者で棒がフォークです!!!!
そのまま各哲学者が同時に右のフォークをとるとこうなります

f:id:sasa5740:20191127212547p:plain
丸が哲学者で棒がフォークです!!!!!!!

この状態になってしまうと1が左のフォークを取りたくても5が持っているので取れない、5も早くパスタをとってフォークをおろしたいけど4がフォークを持っているので取れない。…となり全員がお互いのフォークを下ろすのをおみあいしてしまう、いわゆるデッドロック状態になります。

プログラミング言語Rustでは5だけ最初に左のフォークを取らせて確実に誰かが両手にフォークを持てる状況を強制させていました。
この問題は 食事する哲学者の問題 - Wikipediaにも乗ってるけど色々デッドロックを起こさない方法があります。

セマフォって概念ここで初めて知りました。 dirty/cleanなんかはページングで使われてる気がする。

Rustにセマフォあったみたいだけど非推奨になっていた。MutexとCondvarでなんとかするのだろうか。