読者です 読者をやめる 読者になる 読者になる

会津大生ソースコードレビュー大会

こちらは Aizu Advent Calendar : ATND の16日目の記事です。

今日は以下のイベントを行いましたのでそのレポートです!
会津大生ソースコードレビュー大会 | イベントアテンド [ATND] でイベント作成・チケット販売・参加者の出欠管理

開催趣旨

自分のコードを晒したり、人のコードを読んだりというのを学生間でやってみたいと思い主催してみました。

進め方

以下の流れで行いました。

  1. 13:00 Gistの登録方法紹介
  2. 13:15 進め方の説明
  3. 13:20 自己紹介
  4. 13:30 @puyopop6さんによるAOJ問題のPythonコード
  5. 14:00 @masapontoさんによるAOJ問題のCコード
  6. 14:45 休憩
  7. 14:55 @youxkeiさんによるダイスの目をパースするJavaコード
  8. 15:30 @yutoppさんによるリンカのためのC++コード
  9. 16:10 @youxkeiさんによるパーサージェネレータのDコード
  10. 16:40 まとめ
  11. 16:50 撤収

左画面がbefore, 右画面がafterになるようにエディタの画面分割をして編集していこうと思ったのですが、綺麗なコードが多かったので、得られるプラクティスをまとめるという方式になっていきました。

@puyopop6さんによるAOJ問題のPythonコード

f:id:ishn:20121216135104j:plain
AIZU ONLINE JUDGE AOJ0026 Dropping Ink を解くコードです。「
AOJ0026の問題です。pythonで解いてみました。最後のリスト内包表記でちょっぴりpythonっぽさをアピール。
」とのこと

寸評

  • 3行目, iはindexの意味で使われていないので明示的にunusedのような名前にしてみるのもいいかもしれない
  • 同じく3行目, mapやfilterで書き直せるかもしれない
  • [[10]*10]*10だと誤りなので気をつけよう
  • largeなどは定数として使われているがPythonで定数的表現をどうする?
  • 24行目, Pythonならではの評価式。綺麗に書けるので素晴らしい

感想: ワンライナー的に凝った書き方もできるのに、可読性も良いのでPythonすごいなーって思いました。

@masapontoさんによるAOJ問題のCコード

AIZU ONLINE JUDGE AOJ10031 Search II を解くコードです。
10031.c

  • inputは関数の動作を表していない。mallocしてリソースを返すものなのでget_とかのほうがいいかも?inputは入力の変数に使ったりする。
  • S,Tが大文字なのはなぜ? => これは問題の条件に合わせた
  • タブとかスペースに気を使おう。input *のあとのスペース2つとか、printfのインデントとか。
  • 競技プログラミング的には、動的メモリ確保をしなくてもいいように出題されている。自分で対処できないバグにつながっていくのでmallocは避けよう

で、みんなで訂正したいったのがこちら↓

でも実はまだWrong Answerでしたwなんでだろう

感想: プログラミング経験が浅いとおっしゃっていましたが、今日来ていただいて本当にありがたかったです。mallocとか、習ったものを実践していこうという姿勢はとても好感がもてます。そういう挑戦が含まれたコードをみんなで囲むのがレビュー大会では意義のあることだと思います。

@youxkeiさんによるダイスの目をパースするJavaコード

f:id:ishn:20121216151357j:plain
TRPGで使われるダイスの処理をパースしていくコードです。たとえば「2d6+5」というのは「2つの6面体サイコロを振った合計に5を足した値」という意味になります。そのようなStringを受け取り、空白文字の除去などを行った上で値やダイス情報を保存したりしています。処理の順番は一番下のskipからになるのでさかのぼって読んで行きました。
f:id:ishn:20121216151832j:plain

  • 関数名、変数名はもっとよくできるかも?Resultというのも場所によっては違和感があった
  • Resultの変数に、例がコメントにあれば読みやすかった。nextなど予想しづらい


感想: 解説があれば理解しやすい綺麗なコードでした。変数の使われ方のレファレンスがどこかにコメントであれば、ほとんど一人で読めそうです。

@yutoppさんによるリンカのためのC++コード

事前知識が必要なコードです。今回最も難易度が高いものでした。
リンカ作ろうJP$1 - yutopp's blog @yutoppさん本人のページに情報がまとまっています。コード本体は長いのでリンクからどうぞ。
pe_gen
論点としては

感想: 低レイヤーになると処理系依存なところもでてくるのでコードだけを見て全てを知るというのが難しくなり、事前知識にそってやっていく必要がありますね。そのためのドキュメント整理がなされているかなんかも良いコードの条件かもしれません。同じ学生で、ここまで深い知識をつけられたのは凄いと思います。普段あまり交流の無い他の学生にもそれを見せる機会ができたのは有意義でした。

@youxkeiさんによるパーサージェネレータのDコード

@youxkeiさんが作っているコンパイル時パーサージェネレータ(ctpg)のコードです。ctpgに関しては本人のgithubにドキュメントがあります。 https://github.com/youkei/ctpg/wiki/ctpg%E3%81%A8%E3%81%AF
今回も長いのでリンク先を参照してください。
ctpg/src/ctpg.d at master · youkei/ctpg · GitHub

このうち、decode()という関数(257-366行目)に焦点をあててレビューしました。Unicode文字列の先頭を適切にデコードするものです。ctpg全体だと難しいですが、この部分なら10分で理解できるものでした。

UTF-8, UTF-16, UTF-32をビットマスクにより判別して処理を場合分けしているシンプルなコードです。

  • Dの仕様で、単体テストを直下に書けるのは読みやすい。仕様も把握できる。
  • ifの中身をもう少しわかりやすくできる?でもこれで最小限だし難しいかも
  • 実際に呼び出しているのは554行目のような感じ。Dでは、f(a)をa.f()と書ける。それを何度も組み合わせるとa.map(...).filter(...).writelnのように、話す順番で処理を記述できる

感想: こちらも解説があればこれ以上手を加えるところが思い浮かばない感じでした。Dといってもこのレベルであれば便利だなーと素直に思えますね。

大会を終えて

様々なレベルの方にお越しいただいたのでとても勉強になりました。今回初めてだったこともあり沢山の課題も見つかりましたが、みなさんのコードの提供により楽しく終えることができました。

収穫

  • 良いコードを精読する機会にもなった
  • 知らない言語の良さを知れた
  • プログラムに登場する"名前"についてみんな真剣に考えているのが分かった
  • 長いコードにはドキュメントやコメントがあると読みやすさがかなり違うのが分かった。長いコードというか、(1)変数の生存期間が長い あるいは (2)変数の種類が多い もの
  • 目的のコードの言語的な習慣が見えていると書きやすいということがわかった。手本を真似るのは大事

課題

色々なレベルの人がより楽しく参加できるようにしたいですね

  • 空気が少し固かったので、リラックスできるような仕掛けを考えたい。沢山しゃべることで面白くなるイベントなので
  • 今回はみんな優秀すぎて直すところが無かった!クイズみたいに明らかに良くない部分を作ってもらうのがいいかも?
  • 一人の持ち時間をキッチンタイマーとかで設定するとメリハリがつくかも
  • プレゼン10分, ツッコミ20分で決めて一番直された人が勝ち(あるいは負け)とか
  • ゲームとかイベントドリブン的なプログラムが今回無かった
  • 超絶技巧スクリプトを読みやすくするのもたのしそう

また機会があれば、会津大生同士のスキル向上ができるようなイベントをやっていきたいです!