【7/9(土)】Doma勉強会 in 東京 に参加してきた

f:id:tenten0213:20160710123302p:plain

【7/9(土)】Doma勉強会 in 東京 - dots. [ドッツ] に参加してきました。

Doma自体はちゃんと利用したことが無いのですが、昔S2JDBCは利用したことがあったので気になっていたこと、Enkan で使われていること、うらがみさんが常々おすすめしていて気になっていたなどの理由から参加してみました。

Domaの紹介 - @backpaper0 さん

トップバッターはうらがみさんで、Domaの紹介。 自身がDomaを利用したことが無かったので、丁寧な説明で分かりやすかったです。

以下良いなーと思ったポイント。

  • 2-way SQL
    • コピペでそのままSQLを実行できるので便利
  • Java8 対応
    • DAOメソッドの引数や戻り値をOptionalで包める
    • StreamやCollectorを利用できる
  • エンティティリスナー
    • 思考停止で登録日時とか更新日時を入れさせられることが多いので便利そう
  • コンパイル時のチェック
    • しょうもないミスは結構防げそう
  • JAR1つに依存するだけ
    • 他のJARに依存しない
    • 導入の敷居がかなり低い

全体的に機能は充実しているのですが、割りきって切り捨てている(※) ところもあり、シンプルになっていると感じました。 ※ 検索系は必ずSQLを書かせる、SQLファイルのincludeなどは提供しない、など

ドメインクラスの話 - @backpaper0 さん

引き続きうらがみさんの「ドメインクラスの話し」。 ドメインクラスと言ってもDDD的なアレではなく、Domaで扱える値オブジェクトのこと。

普通にやるとIntegerやStringなどの基本型だらけになるカラムのマッピングで値オブジェクトを利用できる。

引数の順番誤りを防いだり、値の導出をユーティリティクラスでやらず、値オブジェクト自体に閉じ込めることが出来たりして良い。 他にも可読性(引数や戻り値のシグネチャに現れる)やIDEの補完などでもメリットがあるよ、という話しを聞いて納得。

Webアプリケーションにおけるデータの流れと値クラスと基本型の境界の図はとても分かりやすかったです。 (こうゆうのちゃんと整理できるようになりたい)

うらがみさんは、アプリケーションのレイヤでは基本型を使わず、全てドメインクラスを使うようにしているとのこと。(凄い…)

Domaに限らず参考にできるエッセンスが多く、仕事で活用できそうなヒントをいっぱい貰えました!

とあるDoma2の使い方 - @gakuzzzz さん

自分は何の勉強会に来ていたんだっけ?となるインパクトのある内容でした。

基本的にImmutableにするため、資料の全てのフィールドはfinal…!

そんな@gakuzzzz さんのDomaの使い方のお話。

最初はEntityをImmutableにするという話で、IDをDBの機能で自動生成している場合の対応を紹介していました。

IDクラスや、notAssigned()というIDが未割り当てだという状態を定義する、notAssigned()同士はequals が成り立たないようにする、など様々な工夫が紹介されており、普段あまり考えて設計してないことを痛感。。。

お次はDomaを使ったCollect検索の話し。序盤はおお、便利そう!って感じだったのが徐々に…いや、しょぼちむの頭が邪魔でコードが読めなかったってことにしておこう!…(´・ω・`)

後から資料をじっくり見なおしてみると理解できる部分も多く、1:nや、n:mの検索はかなり便利に思えました。

@gakuzzzz さんのツイートこんな感じで怖い人だ!って思っていましたが、とても優しい型でした!

Domaの開発で大切にしている10のこと - Qiita - @nakamura_to さん

最後はDoma開発者の @nakamura_to さん。 初めてQiita Slide見た!

Domaって7年も前からあるんですね。自分がIT業界に入って8年目なので、新人の時からあったのか。

7年間も開発を継続して、新機能の追加やJava8対応など利用者の要望や、新しい言語機能を積極的に取り入れているのホント凄い。

内容としてはDomaを開発するうえのフィロソフィのようなもので、シンプルさを重視しつつ、プロダクトの核となる部分は曲げない。

でもトレンドや利用者の要望は取り入れていくし、逃げ道(JDBCを自由に使える)を用意してあるので別のライブラリへの切り替えも容易(そもそも1JARだし)である、といった話でした。(絶対スライドを見たほうが良い!)

捨てるところは捨てる、プロダクトのコア・バリューとなる部分は曲げない、というバランスが素晴らしくて感心を通り越して感動してしまいました。(何様だって感じだけど良い言葉が思いつかない)

LT

Doma2とMVC1.0でJava EE Webアプリを作ろう! // Speaker Deck - @suke_masa さん

Java EE 成分濃い目でした。とはいえDoma2はもちろん、MVC1.0、Payara Micro、Thymeleafなどてんこ盛りな構成で面白かったです。

Doma2 with Kotlin - @yy_yank さん

大トリはやんくさん。 さすがの巨匠の風格でLTなのにnakamura_toさんより長く話していましたw

NASAのロゴは、うん、似ている気も…?

Togetter

おわり

懇親会ではnakamura_toさんやうらがみさん、がくぞさん、とーますさんの話しに付いて行くのでいっぱいいっぱいだったけど、かなり楽しかった! うらがみさん、発表でも懇親会でもかなり緊張していて、本当にDomaが好きで、憧れているのがわかった。 こういった、ユーザが好きだから開く勉強会は熱量が多くて刺激になる。

発表者の方々、運営をされていたとーますさん、dotsの方々、ありがとうございました!

会場、めっちゃお洒落で良かったです。

MacBook Airのバッテリーを自分で交換した

MacBookを持って勉強会に行ったら20分くらいでバッテリー切れた。

 さすがにマズイと思って調べたら、どうやら修理に出さないでも自分で交換できる模様。

早見表とは異なるが、MacBookの裏面を見たらA1466と書かれていたので、以下のバッテリーを購入。

 

www.amazon.co.jp

 

バッテリー交換に必要な工具も買っておいた。

 

www.amazon.co.jp

 

 

 

www.amazon.co.jp

 

 作業手順は以下のiFixitのサイトを参照。

特に難しいことはなく、ドライバーでネジを外してバッテリーを外して交換して、また元に戻すだけ、という至って簡単な手順だった。 

 

f:id:tenten0213:20151015232944j:image

 
初めて開いたので、結構ホコリが溜まっていた。
 
f:id:tenten0213:20151015232955j:image
 
f:id:tenten0213:20151015233004j:image
 
修理に出すと数営業日必要なところ、自分で作業すれば30分程度で済むし掃除もできるのでオススメ。

(WIP) Seasar Conference 2015に参加してきた

f:id:tenten0213:20150928032045j:plain

Seasar2との出会いは4年半くらい前だった気がする。既に枯れてはいたが、それまでCOBOLや自社フレームワークを利用してきた自分には驚きと新鮮な刺激の連続でのキャリアに大きな影響を与えた、とても思い入れのあるフレームワークだ。

とはいえ、もう3年くらい使ってはいないわけなんだけど。そんなSeasar2の作者やコミッタ、ヘビーユーザだったエンジニアの、過去や現在、未来の話しが聞けそうだぞ!ってことで参加した。

続きを読む

hubot-irof作った

これはいろふ Advent Calendar 2014 - Adventarの4日目です。

3日目はid:sue445さんのいろふさんグッズを作った - くりにっきでした。

やばい、マグカップ欲しい。

いろふさんとの思い出

Twitter上ではちょくちょくやり取りしていたけど、インスタンスとはDevelopers Summit 2012 Kansaiで初めて遭遇した気がする(もしかしたら違う勉強会で会ってたかも?) 家に泊めてもらった時に見た技術書の量に衝撃を受けた記憶がある。

JJUG CCC 2014 Fall(11月15日開催) | 日本Javaユーザーグループで久々に会って、いろふさんが執筆者として参加したJavaエンジニア養成読本にサイン貰った。ありがたや〜(T人T)

f:id:tenten0213:20141203011528j:plain

本題

Hubotスクリプト作った。

ライセンスはいろふ・ライセンス

npmにも上げているので、自分で作ったHubotのディレクトリでnpm install --save hubot-irofして、external-scripts.jsonhubot-irofを追加すれば使えるようになる。

コマンドはhubot irof meしかない。

f:id:tenten0213:20141203010630p:plain

いろふさんを召喚したい時とか、反応に困った時、なんとなく賑やかしに…ご利用ください。

5日目は…緊急参戦の@yy_yankさんのJavaプログラマーのはしくれダイアリー: マジ感謝ないろふさんに俺のライムを送るです!+(0゚・∀・) + ワクテカ +

PushbulletのBookmarklet登録したら捗った

休憩中にiPhoneで見ていたページを会社のPCで表示したりするのにPushbulletが便利で、よく使ってる。 ただ、見ていたページのリンクをコピーしてPushbulletのアプリを立ち上げてPushするのダルい。

なのでBookmarkletを登録して手間を省く。 自分で作ろうと思ったけど、以下のGistがあがっていたので利用した。

Gistをコピーして適当に"Pushbulletに送る"って感じでBookmarkletを登録する。

f:id:tenten0213:20141130233533j:plain

んで、見ているページでBookmarkletを実行するとタイトルと見ていたページのリンクが入力された状態でPushbulletが立ち上がるので、後はデバイスを選択してPushするだけ。

f:id:tenten0213:20141130234532j:plain

逆にPCで見ているページをiPhoneで見たいときはChrome拡張使うと便利。

来週からスマホ持ち込み禁止の案件に行くからイロイロ工夫しなきゃ。

HubotにZabbixのアラート通知するの作った

halkeye/hubot-jenkins-notifier · GitHubhipchat/hipchat-cli · GitHubパクって参考にして作った。 両方MITライセンスだったからMITにしたけど、大丈夫だろうか…

正直HipChatを使っているなら、hipchat-cliを使ったほうが色付けられたり出来るので、そっちの方が良い。

参考にしたり改変したときのライセンスをどうしたら良いのか判断するの難しい…

Intellij IDEAのRubyプラグインの有効化に失敗していたんですが、pikが原因でした→pikのconfig.yamlが原因でした

Intellij IDEAのRubyプラグインの有効化に失敗していたんですが、pikが原因でした なんて記事があがっていたけど、怒りにまかせてファイル消して対応したとか書いてあってモヤモヤしたので調べてみました。

動作環境

エラー再現

  • 既にインストール済だったRuby pluginをIntelliJ IDEAからアンインストール
  • pikをインストールし、ruby-1.9.2-p136をインストール
  • 再度Ruby pluginをインストール
  • IntelliJ IDEAの再起動

f:id:tenten0213:20140331192154j:plain

エラーが出ました。参照元の記事と、Rubyのバージョンが違うだけでエラー内容はほとんど同様です。エラー内容のテキストは記事の一番下にでも貼り付けておきます。

原因

どうやらpik関連のYAMLを読み込んだ際にエラーが発生しているようです。 %HOME%/.pik/にconfig.ymlといういかにもっぽい設定ファイルがあるので覗いてみると、以下のような内容になっていました。

--- 
"[ruby-]1.9.2[-p136]": 
  :path: !ruby/object:Pathname 
    path: C:/Users/tis302655/.pik/rubies/ruby-1.9.2-p136/bin
  :version: |
    ruby 1.9.2p136 (2010-12-25) [i386-mingw32]

--- {}

エラーに出ている箇所が見事にありますね。

but found another document
 in 'reader', line 8, column 1:
    --- {}

まさにこのファイルのようです。 YAMLは「---」で区切ると1ファイルに複数のYAMLドキュメントを含めることができます。1ドキュメントだけ取得するはずが、別のドキュメントまで取得できてしまったからエラーになったようです。

対応

ということで、config.ymlの不要部分を削除し、以下のようにしてから

--- 
"[ruby-]1.9.2[-p136]": 
  :path: !ruby/object:Pathname 
    path: C:/Users/tis302655/.pik/rubies/ruby-1.9.2-p136/bin
  :version: |
    ruby 1.9.2p136 (2010-12-25) [i386-mingw32]

IntelliJ IDEAを再起動することで正常にプラグインを読み込むことが出来ました。

エラー内容はちゃんと読んで対応しなければいけませんね。

エラーの内容

Plugin 'org.jetbrains.plugins.ruby' failed to initialize and will be disabled.  Please restart IntelliJ IDEA.

expected a single document in the stream
 in 'reader', line 2, column 1:
    "[ruby-]1.9.2[-p136]": 
    ^
but found another document
 in 'reader', line 8, column 1:
    --- {}
    ^

    at org.yaml.snakeyaml.composer.Composer.getSingleNode(Composer.java:110)
    at org.yaml.snakeyaml.constructor.BaseConstructor.getSingleData(BaseConstructor.java:120)
    at org.yaml.snakeyaml.Yaml.loadFromReader(Yaml.java:481)
    at org.yaml.snakeyaml.Yaml.load(Yaml.java:412)
    at org.jetbrains.plugins.ruby.ruby.RubyUtil.loadYaml(RubyUtil.java:106)
    at org.jetbrains.plugins.ruby.version.management.pik.PikSdkRefresher.parseConfig(PikSdkRefresher.java:133)
    at org.jetbrains.plugins.ruby.version.management.pik.PikSdkRefresher.getSdkInfos(PikSdkRefresher.java:60)
    at org.jetbrains.plugins.ruby.version.management.SdkRefresherBase.refreshSDKs(SdkRefresherBase.java:59)
    at org.jetbrains.plugins.ruby.version.management.SdkVersionManagerUtil.updateSDKs(SdkVersionManagerUtil.java:14)
    at org.jetbrains.plugins.ruby.version.management.ProjectSdkRefresher.initComponent(ProjectSdkRefresher.java:23)
    at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter$1.getComponentInstance(ComponentManagerImpl.java:548)
    at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter.getComponentInstance(ComponentManagerImpl.java:590)
    at com.intellij.util.pico.DefaultPicoContainer.getLocalInstance(DefaultPicoContainer.java:225)
    at com.intellij.util.pico.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:212)
    at com.intellij.util.pico.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:199)
    at org.picocontainer.alternatives.AbstractDelegatingMutablePicoContainer.getComponentInstance(AbstractDelegatingMutablePicoContainer.java:75)
    at com.intellij.openapi.components.impl.ComponentManagerImpl.createComponent(ComponentManagerImpl.java:121)
    at com.intellij.openapi.components.impl.ComponentManagerImpl.a(ComponentManagerImpl.java:112)
    at com.intellij.openapi.components.impl.ComponentManagerImpl.init(ComponentManagerImpl.java:89)
    at com.intellij.openapi.project.impl.ProjectImpl.init(ProjectImpl.java:296)
    at com.intellij.openapi.project.impl.ProjectManagerImpl.a(ProjectManagerImpl.java:281)
    at com.intellij.openapi.project.impl.ProjectManagerImpl.access$300(ProjectManagerImpl.java:83)
    at com.intellij.openapi.project.impl.ProjectManagerImpl$9.compute(ProjectManagerImpl.java:569)
    at com.intellij.openapi.project.impl.ProjectManagerImpl$9.compute(ProjectManagerImpl.java:565)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl$4.run(ProgressManagerImpl.java:240)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl$TaskRunnable.run(ProgressManagerImpl.java:464)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl$6.run(ProgressManagerImpl.java:274)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl$2.run(ProgressManagerImpl.java:178)
    at com.intellij.openapi.progress.ProgressManager.executeProcessUnderProgress(ProgressManager.java:209)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:212)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl.runProcess(ProgressManagerImpl.java:171)
    at com.intellij.openapi.application.impl.ApplicationImpl$10$1.run(ApplicationImpl.java:645)
    at com.intellij.openapi.application.impl.ApplicationImpl$8.run(ApplicationImpl.java:419)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)
    at com.intellij.openapi.application.impl.ApplicationImpl$1$1.run(ApplicationImpl.java:149)

追記

関連するissueがあがっていました。

対応としては同様にコードを修正してるっぽいです。

これ以上調べないでいいかなって思っていたのですが、後輩にpikも調べろやって感じの対応をされたので、pikのコードも見てみました。

おそらく…以下の49行目でglobalにインストールされたRubyに関するドキュメントを吐こうとしているものの、@global = {} の状態のまま書き込んでるから --- {} になってるんじゃないかと。

https://github.com/vertiginous/pik/blob/22a028c84a44088aa813bc8da1d0ae1a7a6597be/lib/pik/config_file.rb#L49

一応irbで簡単に試してみました。 @global = {} のままだと確かに --- {} になります。

irb(main):001:0> require 'yaml'
=> true
irb(main):002:0> @global = {}
=> {}
irb(main):003:0> YAML.dump(@global)
=> "--- {}\n"

rubyのバージョンも疑ってみましたが、1.8,1.9,2.0もほぼ同様の出力になったのでバージョン差異は問題ではなさそうです。(1.8は"--- {}\n\n"でしたが)

あとは、Ruby plugin側のコード変更でエラーが出るようになったことが考えられますが、調べるのが面倒なのでここらへんでおしまいにします。

また後輩に調べろやって言われないといいな。。。