Write Code or Die

RubyやRailsまたはバスケットボールや筋トレについて書きます。

99bottles of OOP を読んだ

オブジェクト指向実践ガイドを書いたSandi Metzの新刊を読んだ。

実は年末くらいには買っていたのだけれども、積ん読してしまっていた。

しかし先週アップデート版が出たというお知らせを受けて(pdf版なのでアップデート版ももらえる)これは読むしかないと思い週末を利用して一気に読み終えた。

内容

OOPを実践する際の指南書。 オブジェクト指向実践ガイドももちろん表題の通りオブジェクト指向について解説していたが、それよりも実践寄りの内容。そして多くのページがリファクタリングについて書かれている。

It turns out that everything you need to know about Object-Oriented Design (OOD) can be learned from the “99 Bottles of Beer” song.

という一文から始まる通り、99 bottles of Beer という曲を作るクラスを書くところから始まる。

気になる人はここにサンプルコードがあるので参考になるかもしれない。

章ごとの概要(個人的なメモ) 

1 Rediscovering Simplicity

  • 自分で99 bottles of beer エクササイズをやって見て、例文と比較
  • 極端に具体的なコード、極端に抽象化されたコード、適度に抽象化されたコード、そしてShameless Green なコードの例
  • 品質の良いコードの判断材料
  • SOLC, Cyclomatic complexity, ABC
  • “good enough” なコードを書くこと

2 Test Driving Shameless Green

  • TDDの基礎的なところの解説
  • 99 bottles例文を使ってコードの品質を測定しながらTDD
  • コスパの良いテストを書く

3 Unearthing Concepts

4 Practicinng Horizontal Refactoring

5 Separating Responsibilities

6 Achieving Openness

  • the Data Clump code smell
  • Polymorphism
  • サブクラス
  • オブジェクトを「製造する」
  • 新機能を安全に追加

感想

まずは正直に読んでよかったと感じた。オブジェクト指向実践ガイドもそうだけれども、Sandi Metzの本は本当にオブジェクト指向に関して深い洞察を与えてくれると思う。何が一番良いかというと、本全体を通じて一つのコードを深く掘り下げていること。他の本では章ごと、いや話題ごとに異なるコードを用いて解説しているのであまり実感がわかないというかいざ自分が使うタイミングがイメージしづらいのだが、この本では99 bottles のコードを共に完成させていくような言わばチュートリアル的な感覚で解説してくれるので非常に自分はわかりやすいと感じた。そういえばオブジェクト指向実践ガイドでもBycycle クラスをずっと話していたのでわかりやすかった。

また、最初から最後までコードを変更した際に一貫して以下の質問をして考えている。

How difficult was it to write?
How hard is it to understand?
How expensive will it be to change?

--- 以下99bottles のケース--- 

How many verse variants are there?
Which verse are most alike? In what way?
Which verses are most different, and in what way?
What is the rule to determine which verse comes next?

個人的な新たな発見はこの本の至る所にあったのだけど、クラスの分割の部分が全く新しい概念だったと思う。普段Railsを使うにあたって、どうしても膨らみすぎてしまうクラスが出てくるのだが、迷った時にはこの本を参考にしながら書いていきたいと思う。

他にもコードの品質を測る方法や理論が多く出てきたので、また見返しながら調べようと思う。

3, 4, 5, 6章は全てRefactoringを参考にして書いてあるらしいので、読んでみるか。

しかし次はConfident Rubyと決めているので購入した。

その次はRefactoring

関連

www.sandimetz.com

オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方 | Sandi Metz, 髙山 泰基 |本 | 通販 | Amazon

Amazon.co.jp: Confident Ruby: 32 Patterns for Joyful Coding (English Edition) 電子書籍: Avdi Grimm, Sandi Metz: Kindleストア

Refactoring Ruby Edition

Goはじめました

Software Skillsに影響された

とあるきっかけでGo言語を利用する機会がでてきたので勉強の記録のためにもここに記す。 ブログとか書かない派だったのだが、Software Skillsを読んで書くことを決意した(単純かというツッコミは置いといて) 「そもそも、勉強した内容とか今更ブログに書いたところでもう既に世の中に出回ってるよー」という感じだが、一応書いてみる。

自分はRuby(Rails歴)2年 = プログラミング歴というバックグラウンドなので、他の言語をしっかり勉強するのは初めてであるし、静的言語とか型とかよくわからないのでこれを機にぜひ克服したい。

パフォーマンスはRubyの3倍らしいので、簡単なAPIサーバーとかGoで書けるようになりたいですな。

Go言語の文法を学ぶ

まずは文法のお勉強から

A Tour of Go

とりあえず一通り理解しながら目を通した感じ。理解が△でもどうせまた使うときにちゃんと調べればいいので、ふーんという感じで流していた。合計2-3時間くらいで完了。

Rubyしか触ったことない自分としては、型宣言するのってこういうことなのかーというのがまずは率直な感想。

途中interfaceってなんやこれはって思ったけれども、 http://cuto.unirita.co.jp/gostudy/post/interface/ これが非常に参考になった。Rubyでダックタイプを使っていたので、それと関連しながら考えることができた。型ってこういうことか。

最後の方に並列処理の部分とかあったけど、普通のWebアプリケーションとかではいつ出番が来るのだろうか?集計した結果とかを表示したい時とかにいいのかな?Go言語で目玉の機能なので積極的に使っていきたい。

WEB Applicationを作ってみる

では実際にGo言語でWeb Applicationを作るためにはどうすればいいのだろうと思ったので、A Tour of Goの最後のページにリンクしてあったオフィシャルなチュートリアルをやってみることにした。

Writing Web Applications - The Go Programming Language

カバーしている領域として

  • 読み書きができるデータ構造の作り方
  • Web Applicationを作るためのnet/httpパッケージの使い方
  • HTMLを処理するためのhtml/templateパッケージの使い方
  • ユーザのインプットをバリデーションするためのregexpパッケージの使い方
  • クロージャの使い方

と書いてあるのでまさに今欲しい内容

上から順番に一通りやって見て、1時間ちょいで完成。

チュートリアルとしても出来が良かった。

関数型言語の書き方がなんとなくわかってきた気がする。

net/httpパッケージを利用すれば簡単にwebアプリケーションを作ることができる感覚もできた。

handlerを準備してあげればよしなにやってくれるのかーと思ったが、もうちょい理解したいので公式ドキュメントを読む

ListenAndServe starts an HTTP server with a given address and handler. The handler is usually nil, which means to use DefaultServeMux. Handle and HandleFunc add handlers to DefaultServeMux:

handlerは通常nilだけど、Handle か HandleFuncがDefaultServeMuxにhandlerを加える….

何がわからないかって単純に「ハンドラ」というものがわからなかった…

What is a handler - Stack Overflow

あるケースでの処理の塊みたいな感じ?

handlerを加えるということは「このURLリクエストの時はこの処理です!」という宣言をするということだろうか。

恐らくかなり基本のことなんだけど、こういう基礎をちゃんとこのタイミングで知れてよかった(本当に良かった…)

というわけでハンドラを加えて簡単なアプリケーションが作れた!

次はJSON API サーバーを作るためにはどうすればいいのだろうか?ということでやって見たいと思う。

体育館予約を自動化しようとした話

この記事はFablic Advent Calendar 16日目の記事です。 http://qiita.com/advent-calendar/2016/fablic

こんにちは。Fablicのサーバーサイドエンジニア、Jamesです。 業務とは関係ないところでちょっとしたシステムを作ろうとした話をします。

今回を機にこのブログ開設しました。気が向いたときに色々発信してたいと思います。

概要

  • 手段と目的
  • 某区の体育館予約を自動化したい
  • 某区の体育館予約システムについて
  • Selenium WebDriverを使って体育館予約を自動化
  • ログインしてみる
  • そしていよいよ予約へ・・・

手段と目的

よく「テクノロジーは手段であり、目的ではない」という言葉を聞きますが、果たしてその通りにテクノロジーを使えている人はどれくらいいるでしょうか?実際に業務でバリバリプログラムを書いているエンジニアも、自分の身の回りのことにその技術を生かしきれていないことは多々あるのではないでしょうか。

かくいう私もそうです。「少しでも世の中を便利にしたい」という思いでエンジニアになったにも関わらず、業務以外で技術を活かすことがなかなかできずに「自分の周りのことも何も変えられないのはなんだかなー」と考え、そんな自分に悔しさを感じていました。

某区の体育館予約を自動化したい

話は変わり、私は中学でバスケットボールを始めてから今でも週1程度で続けております。なかなかハードなスポーツですが、体を動かすのは気分転換になります。好きなプレイヤーは昔からKobeですが、Mike Millerみたいなサイズがあるシューターとか、最近ではKenneth Fariedが好きです。日本人だと筑波大学の馬場雄大選手に注目しています。GW大学の渡辺雄太選手も大注目ですね!Bリーグも開幕して、なかなかバスケットボールシーンは熱くなっております。

しかし、そのバスケットボールを日本でする上で避けては通れない問題が一つあります。 それは 体育館がなかなか取れない ということです。

様々なつながりで集まった仲間でチームを作って活動していたのですが、体育館を取ることができない事が原因でなかなか集まって一緒にバスケットボールをすることができませんでした。

しかし、この状況を打開すべく、ついに先日某区でチーム登録を済ませました。 それまで知り合いのチームに遊びに行かせていただいたり練習もせずに試合に出ていたりしたのですが、体育館が取れるようになると話は変わってきます。

私たちは、「これで自分たちの練習ができる!」と意気込んでいました。

しかし 体育館予約が全然できない のです。

原因としては

  • 予約はWeb上で行うことができるのだが、システムにアクセスできる時間が限られており、見れる人が少ない(9:00~22:00)
  • 予約できる日が限られている
  • 登録団体が多すぎて、空きが出ない

ということが挙げられます。

せっかくチーム登録をしたのに体育館が取れない! これはどうにかしなければいけないと思い、私はこう思いました。

「そうだ、ついに自分の技術力を役立てることができる」

Selenium WebDriverを使って体育館予約を自動化

今回はWeb上の動作を自動化するということで、Selenium WebDriverを使ってみることにしました。 Selenium WebDriverの概要に関しては、ここを参考にしてくだい。

Rubyが使える点と、ちょっと調べてみて参考記事が多そうだったので選びました。

ログインしてみる

いきなり予約する前に、まずは自分のチームでログインしなければなりません。 まずはトップ画面からログイン画面に遷移して、自分のチームのトップ画面に行くところまで作りたいと思います。

対象のシステムでは、

  • トップページ
  • 予約するするボタンをクリック
  • ログイン画面
  • ユーザー情報を入力
  • ログイン成功

という流れでログインできるので、この流れを自動化していきたいと思います

*Selenium WebDriverの使い方の基礎に関してはこの辺りの記事を参考にしました。 こうして、以下のようなスクリプトを作り、ログインした後、ログアウトすることに成功しました。

require 'selenium-webdriver'

class GymReserver
  TOP_PAGE = 'https://example.com' #トップページのURL

  # 以下アカウント情報
  ACCOUNT = 'XXXXX'
  PASSWORD = 'XXXXX'
  CODENUM = 'XXXXX'

  attr_accessor :driver

  def initialize
    @driver = Selenium::WebDriver.for :chrome
  end

  def login_execute
    click_reserve # トップページで「予約する」ボタンをクリックする
    login # ユーザー情報を入力し、ログイン

    driver.find_element(:id, 'FOOT1BTN').click #ログアウトボタンをクリック

    sleep 5  #  トップページで待機

    driver.close()
  end

  def click_reserve
    driver.get TOP_PAGE
    switch_to_iframe
    driver.find_element(:id, 'BB0').click
    puts 'succeeded to click button'
  end
    
  def switch_to_iframe
    iframe = driver.find_element(:name, 'iframe')
    driver.switch_to.frame(iframe)
  end

  def login
    fill_account_info
    driver.find_element(:id, 'loginID').click
  end

  def fill_account_info
    [ACCOUNT, PASSWORD, CODENUM].each { |info| click_each_char_button(info) }
  end

  def click_each_char_button(info)
    info.chars.each { |char| driver.find_element(:id, "KEY#{char}").click }
  end
end

GymReserver.new.login_execute

少しハマったポイントとしては、なぜかシステムがすべてiframeで出力されるようになっていた ために、画面遷移して際はiframeを指定して、そのiframeの中から要素を探してボタンを入力しなければならなかった点です。

  def switch_to_iframe
    iframe = driver.find_element(:name, 'iframe')
    driver.switch_to.frame(iframe)
  end

ユーザー情報を入力しているメソッドで一つ一つの文字を要素から探し出してそれぞれクリックしているのも、普通のformではなくiframe内のformを利用して入力しなければならなかったためです。

  def fill_account_info
    [ACCOUNT, PASSWORD, CODENUM].each { |info| click_each_char_button(info) }
  end

  def click_each_char_button(info)
    info.chars.each { |char|  driver.find_element(:id, "KEY#{char}").click }
  end

市町村が運営している予約システムはこのように素敵な仕様になっていることが多いので、皆さんもぜひ気をつけて下さい。

そしていよいよ予約へ・・・

ログインまで出来れば、あとは予約のパターンを調べて同じように操作をするだけです。 ついにこの瞬間が来ました。

自分のの技術が私自身のためだけでなく、ITからかけ離れているチームメイト達の役にも立つことができる

私は高まる緊張を抑えながら空いている施設を探して、予約パターンを探しました。 一つ一つ施設を検索して、空いている日を探しました。 一箇所でも予約できる施設を見つけれれば私の勝ちです。

しかしここに大きな落とし穴があったのです。













いや、どの体育館も空いてないやないかい (ツ)_/¯