へっぽこびんぼう野郎のnewbie日記

けろけーろ(´・ω・`)! #vZkt8fc6J

JavaやPHPのハッカソンに潜り込んでPythonにリプレイスしてきた話

先日忍び込んだハッカソンで、「Java+Spring Frameworkで書かれたこのサンプルコードか、PHP+Laravelで書かれたこのサンプルコードを参考に何かつくってください」というお題をもらったので、朝から夕方まで7時間弱で食事は水オンリーで作業した結果、Python+Djangoでリプレイス作業をしたという成果をだして、気づいたことがあったのでとりあえずブログに書きます。成果はGitHubにあがってますが、汚いので見ないでほしいです。あとそのままでは動きません。pipで必要そうなライブラリをインストールしてください。

書く前の知識

  • Javaは書いたことある
  • Tomcatは知っている
  • SpringBoot自体は実行したことは1回ある
  • PHPは知らない
  • Spring Framework何も知らない
  • pom.xmlとはなんなのか
  • LTIやCaliperというIMC Globalという団体が作ってる規格がよくわからない(そもそもこれがメイン)

得られた知識

Java関係のもの

  • pom.xmlは、NPMでいうpackage.jsonみたいなもん
  • Spring Frameworkの中にはTomcatがあるものもある
  • DI使われていて便利そうだった。ただServiceの使われ方が何かおかしいように感じた
  • Javaはやっぱり冗長だった。Modelのところにgetなんたらとかが大量にあって悲しく感じた
  • RepositoryでのCrudRepositoryは便利そうな感じがしたけど、Djangoの文化と違いすぎてやるならフレームワークを作るところからやる必要を感じた
  • Spring Bootでのエントリーポイントが、PythonでいうWSGIみたいな感じで萌えポイントだった
  • SpringのControllerで、アノテーションにRequestMappingがあるのはいいなと思った(いまさら感)
  • IntelliJは良い

PHP関係のもの

  • 引き続き知らない

JavaPHP関係以外で得られた知識

  • LTIは要はHTTPのセッションに何入れるかのやつ。それとOAuth2
  • CaliperはCaliper(日本人はみんなそんなに知らないということがわかった)

パワーコードの教訓として得られたもの

パワーコードは実践では良くない

Spring Frameworkのことを全然知らないままやったので、何がどうなっているかわからないまま書き始めていた。

それで「とりあえず」と最初に決めたことにあとあとまで引きずられてしまった。たとえば最初はHello Worldからやったんだけど、そのHello Worldの書き方を最後まで継承し、コピペでいとも簡単に増殖した。

わからない→わかった!→じゃあこの書き方まずいよね→まぁいいか

というスパイラルが繰り返された結果、負債につぐ負債が誕生した。

たとえばViewを書くときに、最初はHello Worldからやったので、View(DjangoのView。Spring FrameworkではController)はクラスから作らず、関数で書いていた。↓こんなの

def index(request):
    return HttpResponse("Hello World")

ここにロジックを追加(個人的にロジックはここに集約すべきではないと思うけど)して、あとからテンプレートを追加することになったので、とりあえずテンプレートにコンテキストを渡せるものを作成することにした。

このへんで、サンプルのJavaコードで使われている「model」には、Djangoで使われているコンテキストの役割もあるということが明確に判明した。

それと同時に、ThymeleafというSpring Frameworkの中で使われるテンプレートがあることを知った。書き方はunderscoreやJinja2とは違って、どっちかって言うとWPFxamlみたいな感じ。

def my_render(template_file, modellike):
    template = Template('<html>foo</html>')
    html = template.render(Context({}))
    return html

def index(request):
    # ~~~ ロジック ~~~
    return my_render("index.html", model)

この状態から、ファイルからロードしてレンダリングする場合に、テンプレートの文字列をいちいちロードするのがめんどくさいので、ファイルをその場でオープンするという荒業を使っていた。

def my_render(template_file, modellike):
    source = open('app/templates' + template_file).read()
    template = Template(source)
    html = template.render(Context(modellike))
    return html

def index(request):
    # ~~~ ロジック ~~~
    return my_render("index.html", model)

そして、ここのindex関数部分がコピペでどんどん増えていく。

最初からDjangoで用意されていたものを使えばいいという話だけど、そもそもわかってない状態から作り始めてこの時点で「こういうふうに書くのがSpring Web MVC Frameworkというやつらしい」ということを理解したので、最初からそういうふうに作ることは知識的に無理だった。

なので、こんな感じでどんどん最初のものから負債が溜まっていく。0.1の瑕疵が最終的に全てを食い尽くすモンスターになっていった。

そのため、初期ではわずかしか行わなかったデバッグ作業も、終盤では多く含まれていた。つらい。

他人が書いたいいところを活かせず、自分の領域にすべて持ち込んでしまう

Spring FrameworkにはどうやらDIがあるというのを知ったけど、これを時間内に実装するのは無理だと判断して無視して実装していった結果、Pythonの方で冗長になり、何の生産性もないクラスがいくつかできあがってしまった。

逆に明確にDIを理解していないことが判明したことはよかった。

いわゆる抽象的な概念の知識が増えない

時間に追われていることもあって、既知の知識の範囲内でコーディングすることしかできなかった。

新しい難しい概念で腰を落ち着かせて考えるべきものは、こういうコードの書き方では手に入れられないなと思った。

今回得られた知識は、最初からある程度知っていた知識を焼き直したぐらいのものだった。

そういう面から見ると、業務とは直接関係ない勉強というのは重要だと思った。

時間管理は重要だった

「これは絶対無理。これはいける。これはできるけど時間的にキツいし、なくてもいいから切り捨て」という判断がだいじだった。

「この領域は何分でできるか。1個で5分なら、5個で完成だから15分くらいかな?」「残タスクはどれだけかマークダウンで洗い出し」というように見積もって、時計をときおり見ながらタスクをこなしていった。

タスクの洗い出しは、各領域を整頓するために脳からシリアライズしたぐらいで、途中で完全に全体構造が見えてからは全く必要なり、バージョン14時ぐらいで更新停止した。

ものすごく疲れる

タスクが完了してから、空腹と頭痛と体のだるさを一気に感じて死にそうだった。

帰りの電車で座れなくて「アアアアア」とゾンビみたいになっていた。

たぶんいつもやってる仕事よりやや簡単だったのでゾーンに入っていたのだと思っている。

時間管理の結果「飯を食う時間は無駄」と判断して休憩なしでやっていたので、こういう作業の仕方ばっかりやってると体を壊しそう。

ライブラリを読むのは正義

他人が書いたライブラリの中でエラーが発生したときは、まず読み、意味がわからなかったらググり、エラーの意味がわかるけどなんで出ているのかわからない場合、ライブラリの中でデバッグするという挑戦が必要だと思った。

それで仕様がわかったりしてた。(ちなみにハッカソンではあと5分しかないのに、なんでエラーになるのかわからないところがあって、最終的にライブラリの中身を編集して完成させるという暴挙に出た)

推論重要

「こうなってる?→なってたらここはこうなって、こっちはこうなってるはず→なってた!!!」というプロセスを繰り返せていて、特に何もドキュメントを読むことなくSpring Frameworkの外観を把握できた。なので今ドキュメントを読むと相当いろんなことがわかるようになっていると思っている。

新しいことを学ぶときは他人が書いたコードが一番勉強になる

ドキュメントを読むより、人が時間かけて書いてくれたコードをガンガン読んだ方がドキュメントより正確だし、自分で思考して推論していけるのでよかったと思う。

たぶんドキュメントを読んで自分でSpring Frameworkの環境を構築してJavaで書いていくより、効率的に学習できた。

ただし、既知の概念だけでは得るのが難しいような概念(自分にとって完全に馴染みのない概念)は、おそらくそもそも推論の原理的に難しくて、未知の情報に対して既知の情報が足りなさすぎて、解決への探索に計算リソースが膨大に必要になると思った。

だから、情報量が格段に多い、いわゆる難しい概念を日常的に獲得していくことで、他分野の知識も得られやすいのかなと感じた。

英語できないとつらすぎ

ハッカソンの最初で、アメリカ人の人が最近の動向とかを説明してくれていた。1時間ぐらい。最初は日本人向けに英語をゆっくり話していたけど、慣れてきたのかだんだん早くなっていき、そもそもよくわかっていないものをよくわからない単語と組み合わされて話されていたので、一部理解できても、ものすごくつらかった。

ふつうに英語の重要性を感じた。

おもったこと

最近本業でわけわかんないのにインフラ周りばかりやっていてスランプぎみだったので、集中してコーディングできて、一つのものを作り上げることができたのは、精神衛生的に良かった。

なので、こういう本業とは直接関係ない、やつあたりみたいなコーディングも時々やるのがいいかなと思った。

Spring Frameworkがどうこう以上に(たぶん個人的には使わないし)、色々と教訓が得られたのがよかった。

振り返ってみると全然大したことしてないので、たとえばDIのへんとか勉強したいと思った。

🐹