upinetree's memo

Web系技術の話題や日常について。

長岡でScalaに入学した

9/28に新潟県長岡市でScala入学式に参加しました。 長岡IT開発者勉強会(#NDS33)の一環として開催されたハンズオン形式の勉強会です。 id:nkgt_chkonkさんが講師をしてくれました。

ScalaはおろかJavaすら普段いじってないレベルだったので不安でしたが、やってみるととてもおもしろかったです! 以下、簡単にレポートします。

ちなみに、資料はこちらにアップされています。

https://gist.github.com/Shinpeim/6740436

環境

Better JavaとしてのScala

写経したりしてScalaの動きを確認していきました。 お題となったのはドラクエ風RPGの戦闘。

PlayerからKnight、Magicianと継承させてみたり、 traitでWeaponを作ってLongSword object(static的なやつ)を作ったりしてました。

traitはRubyのmoduleみたいなやつで、ホント便利です。

trait Weapon
trait KnightWeapon extends Weapon

trait HasWeapon {
  protected var weapon: Weapon = NullWeapon
}
trait CanEquipKnightWeapon extends HasWeapon {
  def equip(w: KnightWeapon) = weapon = w
}

class Knight extends Player with CanEquipKnightWeapon

とかできる。 RubyいじったあとにJavaやろうとしてぐぬぬってなった記憶があったので、これがあると断然違います。 また、型をコンパイラがチェックしてくれるので、たとえばMagicianWeaponを装備しようとする怒られます。

型パラメータを使ってテンプレート的なやつを試したりもしました。 上記のCanEquipKnightWeaponだとCanEquip[T <: Weapon]みたいにできます。 scalaはいい感じに型で縛ってくれるので安心感ありますね。

モナド

Listの構造やmatchによる強力なパターンマッチ、再帰構造の利点など、手を動かして実際に確認していきました。 ここらへんからちょっとペースがきつくなっていきましたが、なんとかついていけました。 でも理解はふわっとした感じだったので、復習が必要ですね。

foreachとかmap、filterなどの高階関数Rubyで触ってたのですんなり理解出来ました。 Ruby使っているうちに、自然と関数型っぽい脳みそになっていたらしいです。

Optionモナドはすごくクールでした。 型で包み込んで忌まわしきnullチェックをコンパイラに任せられます。 Java8でも取り込まれるらしいので、ぜひ使いたい。

Futureモナドは遅延評価っぽいんだけどそうじゃないみたいでした。 このあたり理解が追いついてなくて、細かい部分でどう動作するのかってのがわかってないので復習したいです。

モナドって言葉が怖くてなかなかさわれなかったんですけど、今回はじめてやってみて、そんなに怖くないものだと理解できました。 モナディック!モナディック!

Twitter Bot

まとめとして、Twitter Botをみんなで作りました。 TLにぬるぽ見つけるとガッするやつ。

twitter4jを使ったのですが、gen-ideaってやるとsbtがダウンロードまでしてくれてとっても楽でした。

最終的にはTLがガッで埋まったのが良い思い出。

LT

マインドストームのPID制御の話が熱かった! 制御系出身で、マインドストームやったりもしてたのでテンション上がりました。

あと東京勢の発表は最初から最後まで草を回避できませんでした。 草を回避できないダメ人間ですみません。

僕も発表したんですが、内容を校正して、タイミングを見てブログ記事にしようと思いますー。

まとめ

とても満足度高い一日でした。

Scalaは日ごろネットで情報を見てもメリットが良く分からなかったのですが、 入学式では丁寧に「こんなところがカッコいいよ!」と教えてもらえたので魅力がよく分かりました。

積極的に、適材適所で使えるようになりたいです。

NDS32 GitHubハンズオンにいってきた

7/6(土), NDS32 GitHubハンズオンに参加して来ました。

Gitはコマンドである程度は使えていたのですが、SourceTreeも以前から気になっていました。 あと、人にGit勧めたりチームに展開するときにGUI環境があると説明しやすいかなーと思いつつ参加しました。

当日はあいにくの天候にもかかわらず満席で、NDSすげーって思いました。 また、大学の後輩が参加していたのもとてもびっくりでした。

GitHubハンズオン

やったこと

  • VCS, SCMとは
  • SourceTreeの使い方
  • GitHubの使い方
  • GitHub Pagesでホームページ作成
  • ペアを組んでフォーク、プルリク

SourceTreeは結構使いやすくて、画面もきれいで見やすくてよかったです。 操作も特に迷うことなく使うことができました。 ただ、Windows版のローカライズがまだのようだったので、 他の人に教えるときには注意が必要そうです。

また、GitHubの使い方も勉強になりました。 今まで使う機会のなかったGitHub Pagesに触れたのと、 ペアを組んでPull Requestもできたのが良かったです。

あと、GitHubで画像の差分を見られると知って目からうろこでした。 サンプルのドラえもんの差分がカオスで笑ってしまった。

講師の@dictavさん、ありがとうございました。

LT

LTして来ました。 軽い気持ちでネタLTしようと思ってたのがまさかの満席だったので、予想外に緊張しました。

※応用例を増やすためにワタクシの密かな趣味を大公開してましたが、恥ずかしいのでここでは消してます(・ω・)

一応このLTには意図がありまして、本編がSourceTreeでの初心者向けのGit勉強会だったので、 Gitをもっと気軽に使っていこうよ、というのと、コマンドライン版もこんな感じでつかえるよ、 というような、補足的なLTにしようかと思っていました。

すべるかなーと思っていたのに結構良い反応をいただけたので嬉しかったです。

他の方のLTも多種多様で、楽しく聞かせて頂きました。 ジャンルを超えたLTはNDSならではだなーと思います。

懇親会

ビアバッシュ!

買い出し班だったのですが、雨に打たれて大変でした。 外に出るタイミングで雨が強くなるという理不尽さでしたが、それも含めたのしかった。

オードブルはとても肉々しかったです。 ガッツリお腹いっぱいおいしい食べ物を食べられて満足でした。 写真取ればよかったなと今更後悔してます。

学生にSIerのリアルなこわい話をして若干やりすぎたかなーと思いました。 でも反省はしていない

まとめ

とても充実してたのしかった一日でした。

これを機に、社内でもSourceTreeを使ってGitいいよって話をしようかなーとも思ってます。

あと、学生すごいなーと改めて思いました。 僕も頑張らなきゃダメですね。

ということで、以上、遅くなったレポートでした。

TDD Boot Camp 長岡 1.0 に参加してきた

05/18 (土) に長岡で開催された、TDDBCに参加して来ました!

自分一人でTDDやってみてもよく分からず、前々よりTDDBCに参加したいと思っていたのですが、この度ついに長岡で開催とのことで、念願の参加となりました。

簡単にですが、まとめます。

大事だと思ったところ

  • 気づきは、「動かない→動く」で得られることが多く、早い段階で気付きを得ることが重要
  • 黄金の回転のうち、リファクタリングには意思が必要。意思がないと、回転の円が潰れてくる
  • 複数の問題、大きな問題を一度に相手にせず、小さく分割して連続的に倒していく
    • それを素早く繰り返すことが大事
  • 不安をテストにする。形骸化したテストにはしない
  • TDDの真の目的は健康。変化に対応できるのは健康なコードと健康なチーム

気付き

  • 今まで書いたテストは粒度がバラバラだった、テストを積極的にリファクタリングすることもなかった(特に粒度)。TDDBCで大体の感覚がつかめたので、どんどん書いて痛い目にあって学習しようと思う

  • ペアで作業すると、考えこんで先に進めないということがない。一人でやっているときは半分意地で悩み続けてしまうこともあるが、その前にペアからハッとする意見をもらって解決したり、ある程度のところで切り上げるということができた

  • ペアでのリファクタリングは本当に効果的。それを支えるのがテストコード。テストで振る舞いが保証されていて、安心してコードを良くしていけるのを実感

  • コードレビューで他の方々のコードを眺めて、なるほどと思うことがいっぱいあった。同じ問題をみんなで解いて、みんなでレビューし合うってのは楽しい

  • 新潟にもいろいろな技術者がいて、みんな頑張ってるんだってことが分かった。やっぱ外に出ないとダメだな

反省

  • 慣れてきたとき、段階を踏まずにテストをしてしまい、'Development Testing'でなくなってしまったケースがあった。「明白な実装」かそうでないかの感覚を練習でつかむ必要がある

  • US配列のMBAペアプロしてしまった。入力デバイスとか、エディタはペアとのスムーズなやりとりを妨げないよう配慮が必要だなーと実感した

  • レビューの時、MBAのディスプレイ出力をプロジェクタに出せなくてあたふたしてしまった

  • きのこ本持っていくのを忘れた

これから読みたい本まとめ

ニコレポをスクレイピングするスクリプトとライブラリ書いた

ニコ動って楽しいけど、ニコレポにずっと不満があった。

  • 1ページ20ログしか出ない。ページめくるのめんどくさい
  • ログの種類が絞り込めない。動画だけチェックしたいのにすぐ流れていく
  • ブラウザ開くのめんどくさい。ターミナルでチェックしたい

じゃあスクリプト書けばいいじゃんって思って、書きました。

http://github.com/upinetree/nicorepo

詳しくはGithubのREADMEをお読みください。

ふりかえり

まじめにTDDやったの初めてだったけど、どう考えてもテスト足りない。 でもどうやってテストしたら良いのかわからないところもあって、結局先に進むために諦めた部分も多かったです。

テストのコードリーディングもっとする必要があるなと実感しました。

でも、RSpec Mocksの使い方を学べたのは良かったです。

コードは、対話モードのopenコマンドと他のコマンドは意味的に違うのに同じとして扱ってるとか、気持ち悪い感じ。

再帰でページ送りできたのはちょっと良かったかなと思います。

ちょいちょい改善していこう。

Mechanizeでニコ動スクレイピングしようとしてコケた

ニコ動スクレイピングしたら楽しそうだなーと思ってやってみたら、 2回ほどコケたのでメモ。

homebrewで入れたopensslの証明書でコケる

opensslのバージョンが古かったので、homebrewでopenssl入れたら ruby2.0.0で証明書エラーでました。

http://qiita.com/items/12457815d5cee3723b97

こちらを参考に、証明書を入れて無事解決。

$ ruby -ropenssl -e "p OpenSSL::X509::DEFAULT_CERT_FILE"
"/usr/local/etc/openssl/cert.pem"

$ brew install curl-ca-bundle
$ brew list curl-ca-bundle
/usr/local/Cellar/curl-ca-bundle/1.87/share/ca-bundle.crt
$ cp /usr/local/Cellar/curl-ca-bundle/1.87/share/ca-bundle.crt /usr/local/etc/openssl/cert.pem

追記(2013/05/01)

WindowsでRubyInstallerを使ってRubyをインストールした場合、下記で対応します。

$ wget http://curl.haxx.se/ca/cacert.pem
$ cp cacert.pem /c/Ruby193/
$ export SSL_CERT_FILE=/c/Ruby193/cacert.pem

参考:Root certificates? · Issue #148 · oneclick/rubyinstaller

SSLバージョンでコケる

さて、Mechanizeを使ってみましょー。

ニコニコ動画にアクセスしてログインしてみます。

require 'mechanize'

LOGIN = 'https://secure.nicovideo.jp/secure/login?site=niconico'

agent = Mechanize.new
agent.post(LOGIN, 'mail' => mail, 'password' => pass)

が、ここで怒られます。

Errno::ECONNRESET: Connection reset by peer - SSL_connect
from /Users/upinetree/.rbenv/versions/2.0.0-p0/lib/ruby/2.0.0/net/http.rb:917:in `connect'

どうも、ニコ動はSSLv3じゃないとダメっぽいです。

http://stackoverflow.com/questions/11855324/ruby-mechanize-https-error

ここを参考に。

agent = Mechanize.new
agent.ssl_version = 'SSLv3'
agent.post(URL::LOGIN, 'mail' => mail, 'password' => pass)

これでOK!

追記(2013/05/01)

SSLv3は脆弱性が発見されたので、TLSv1以上にしましょう。

agent.ssl_version = 'TLSv1'

Rubyのwin32oleでWordファイルをPDFに一括変換する

WORD→PDF→結合という変換は結構な頻度で定期的に発生する作業だったのですが、 いい加減めんどくさいので自動化します。

Office2007以上であればPDF保存できるので、Win32OLEを使ってやりましょう。

下記エントリがとても参考になりました。

と、単に自動化したいのであれば上記エントリだけで済んでしまうので、ここでは僕がやったことを載せてみます。

やりたいこと

  • 指定したWordファイルを全てPDFに変換
  • 変換したら一つのPDFに結合

Word → PDF変換

WordはnewしたらQuitしないと開きっぱなしになるので、おっちょこちょいな僕としては怖いところです。 なので、確実にQuitできるようにちょっと細工します。

EAM(Execute Around Method)というのがあるらしいので、それを使いましょう。

※define_finalizerを使う手もありましたが、こっちのほうが面白そうだったので

require "win32ole"

class WordUtil
    def initialize
        @word_app = WIN32OLE.new("Word.Application")
    end

    def quit
        if @word_app then @word_app.Quit end
    end

    def to_pdf(doc_name)
        doc_fullpath = File.expand_path(doc_name)
        pdf_fullpath = doc_fullpath.gsub(/\.doc$/, ".pdf")

        begin
            doc = @word_app.Documents.Open(doc_fullpath)
            doc.ExportAsFixedFormat({
                "OutputFileName" => pdf_fullpath,
                "ExportFormat" => 17,            # wdExportFormatPDF
                "OpenAfterExport" => false
            })

            puts "success: #{doc_fullpath}"

        rescue
            puts "fail: #{doc_fullpath}"

        ensure
            doc.Close unless doc.nil?

        end
    end
end

class WordManager
    def WordManager.run_during(&block)
        begin
            word = WordUtil.new
            block.call(word)

        ensure
            word.quit

        end
    end
end


input_docs = ARGV[0]
input_docs = "*.doc" if input_docs.nil?

output_pdfs = input_docs.gsub(/\.doc$/, ".pdf")

puts "input docs: " + input_docs
puts "output pdfs: " + output_pdfs

# convert to pdf
WordManager.run_during do |word|
    Dir.glob(input_docs) do |fn|
        word.to_pdf(fn)
    end
end

WordManagerにブロックを渡して変換してもらっています。 これなら解放漏れしないね!

PDFを結合する

出力したPDFを結合するにはいくつか方法がありそうでしたが、今回は一番簡単そうだったpdftkを呼び出します。

今回やりたいPDFの結合はちょっと注意が必要でして。

  • 指定した順番で結合
  • ファイル名は毎回一定パターンで変わる

なので、yamlにキーワード並べて、その順番でパターンマッチングして結合、ということをしてます。 なんとめんどくさい。

require "yaml"

class PDFCat
    def initialize(pdf_names, pdf_keys)
        @sorted_pdf_names = pdf_keys.map do |key|
            Dir.glob(pdf_names) do |fn|
                break fn if /#{key}/ =~ fn
            end
        end
    end

    def concatenate(export_fname)
        cat_list = @sorted_pdf_names.join(" ")
        puts "files to be concatenated:\n    " + cat_list.split(" ").join("\n    ")
        puts "export file name: #{export_fname}"

        `"C:/Program Files/PDF Labs/PDFtk Server/bin/pdftk" #{cat_list} cat output #{export_fname}`
    end

end


# concatenate pdf files
yaml_fname = ENV['HOME'] + "/bin/pdf_keys.yaml"
yaml_data = YAML.load_file(yaml_fname)
pdfcat = PDFCat.new(output_pdfs, yaml_data['sorted_keyword_list'])

export_fname = 'catcatcat.pdf'
pdfcat.concatenate(export_fname)

もうちょいリファクタリングできそうですね。

でも疲れたから寝る。

参考サイト

Sublime Text とりあえず入れるパッケージリスト

自分用メモ。 Package Controlは入ってること前提です。

Sublime Text ?

http://www.sublimetext.com/

IMESupport

https://github.com/chikatoike/IMESupport

  • WindowsでIMEのインライン変換がおかしな位置に表示されるのを解消

ConvertToUTF8

https://github.com/seanliang/ConvertToUTF8

  • Shift-JISのファイルを編集するときに重宝
  • でも、 "Goto symbol" したり、 "New View into File" で複製したビューの切り替えしたりするとたまに文字化けする
    • そんな時は落ち着いてUndo
  • ショートカットキー設定ファイル(Packages/ConvertToUTF8/*.sublime-keymap)は再設定するか消しておく
    • GBKに変換するショートカットがctrl+shift+cに割り当てられているので、知らないうちにうっかり押しちゃう
  • 新規ファイル作成時のエンコードも設定できる

Solarized Color Scheme

https://github.com/braver/sublime-solarized

  • 個人的にお気に入り。落ち着く色合い
  • デフォルトのカラースキームにもSolarizedあるけど、こっちのほうが好き

Markdown Preview

https://github.com/revolunet/sublimetext-markdown-preview

  • 保存するとすぐ反映されるのでF5で確認できる
  • markdown.css編集するとプレビューの見た目変えられる
  • Githubライクのgithub.cssが付属
  • Github Flavored Markdownにも対応してるっぽい