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

量産型エンジニアの憂鬱

きっと僕は何物にもなれない。

JJUG CCC 2016 Fallに行ってきました

Java セミナー

JJUG CCC 2016 Fallに行ってきました。

何回か参加させていただいて、いつも電車で行ってたのですが、今回は車で行きました。
伊豆から新宿、高速使うと近い近い。

家帰ってから見たら、新宿まで行ったのに全然歩いていませんでした。

さて、聞いたセッションについて一言ずつ・・・

Be a great engineer!〜 フォローすべきトレンド、スルーすべきトレンドをどう見抜くのか

[CCC2016Fall]Be a great engineer! #jjug_ccc #ccc_a1 // Speaker Deck

聞いていて、首を縦に振ってました。

TwitterとかブログとかGitHubでコード書いてCPANに登録したりしたら、 色々とレスポンスいただいたりしていて、
最近自分でも「アウトプットするとインプット増える」ってのを言っていたので、
「情報を得るためには情報を発信する」ってのがぐう納得しました。

SpringはどうやってDIしているのか

SpringはどうやってDIしているのか? #jjug_ccc // Speaker Deck

本筋とは関係ないけど、農業とIoTも進んでるなあー。と感じました。
本筋は Spring の DI についてソースコードを追っていく感じ。
この時Surfaceのペンが壊れて気を取られていたら追いつけなくなってしまった。。。

理解するにはやっぱりソースコードリーディング必要やなあ。と思った次第。

Event Driven Microservices with Spring Cloud Stream

Data Microservices with Spring Cloud Stream, Task, and Data Flow #js…

今回自分が使っていない技術の話聞いたのはこのセッションだけですね。
今まで Spring Cloud のこと誤解していました。
そして連携がめっちゃ簡単で度肝抜かれました。

今はマイクロサービスは導入してないんですけど、カードとして取っておきたい技術。

Spring CloudでDDD的なマイクロサービスを作ってみる

GitHub - bufferings/jjug-ccc-2016-fall

DDDで出てくる言葉について、実際にやってみて理解が深まったという話

境界つけられたコンテキスト

組織の違いによって物理的に境界つけられたことが、結果的によかった。
DBに直接アクセスしちゃえば楽だけど、後のことを考えると・・・

ユビキタス言語

普段日本語で話してるのにソースに落とす時点で英語に変換しちゃっている。
社内で英語で話すようになって真のユビキタス言語を理解できた。

リポジトリ

DBとのやりとり。エンティティにはアノテーションすらつけない。 ここは Hibernateアノテーションぺたぺたつけてる自分的には悩みどころ。

ドメイン駆動設計とScala 〜既存プロジェクトへの適用〜

DDDについての基本的なところ教えていただいた感じ。
エンティティ、バリューオブジェクト、集約など
コンテキストの言葉の意味が通じる範囲の例がわかりやすかったです。
(自分のメモでは肉まんが関西ではになっているけど違う例だった。)

JPA と DDD の関係で僕が思っていること

JPAとDDDは相性いいのでは?っていうお話。

仕様と実装(ExlipseLink、Hibernate)でも違う部分もある。

自分は今の業務でHibernate使っているので非常に参考になりました。
上にも出てきたけどアノテーションでテーブルの情報などで汚染されちゃうのが嫌な場合は、 xmlファイルに定義すればいいと。

xmlしんどいからアノテーションっていう経緯もあるので、
すごい悩ましいところ。
まあ、方針さえ決まればいいところつまみ食いでいいと思っています。

そしてこのカタログは重宝しそう。
JPA マッピングカタログ - Qiita

ここまで聴いて撤退し、横浜でガッツ麵DXを食べました。

4年間乗ってきたワゴンRちゃん最後の長距離ドライブ。楽しかったです。

Perl6のコンストラクタと継承

Perl6

Perl5にはクラス構文がありません。

モジュール名で bless された リファレンスをインスタンスとして扱うことができます。
ハッシュリファレンスまたは無名ハッシュを bless した場合、キー値ペアをメンバとして使えます。
Perl5 では new メソッドで 自身のモジュール名で bless した 無名ハッシュ を返すことでコンストラクタとして利用しています。

また、グローバル変数 @ISA にスーパークラスを指定することで、スーパークラスのメソッドが利用できるようになります(継承)。
上記スクリプト内では Bird インスタンスが Animal の name メソッドを利用しています。


さて、Perl6ではクラス構文が存在しています。

is で継承することができます。自然言語っぽくていいですね。 Bird is Animal。
メンバ変数が public な場合は上記のように簡単に記述することができます。
継承してもデフォルトコンストラクタがよしなにやってくれています。

メンバを private 変数にした場合はどうなるでしょうか。

全て Nil になってしまいました。
前回 の記事で書いた通り、 デフォルトコンストラクタでは private なメンバに値を渡してくれないようです。

今回は、継承した場合のコンストラクタについて考えましょう。

method new はオーバーライドされてしまう

サブクラスの new がスーパークラスの new でオーバーライドしてしまいます。

サブクラスで new メソッドを定義した場合に、スーパークラスの new が呼ばれず、値が設定できません。
また、サブクラスからスーパークラスの private メンバにアクセスすることもできません。
前回の記事のように無理やり private なメンバに値を設定してやろうとしていると、継承したときにスーパークラスの値が設定できなくなってしまいます。

submethod BUILDを使う

submethod BUILD の場合、スーパークラスのコンストラクタも呼ばれます。

スーパークラスの private メンバにも値を設定してやることができます。

method new と bless で書く方が Perl5 での記述と似ていてついそっちで書きたくなってしまうのですが、
基本 submethod BUILD 使う方がいいですね。

DBUnitでxmlからインサートするときに最初のレコードでnullを指定したい

Java テスト

DBUnitが便利ですね。
Spring Bootにおけるテストでは以下のように書けば毎回データセットをインサートしてくれます。

最初のレコードでnullを指定したい場合にちょっと戸惑いました。

二つ目以降のレコードに null を指定したい場合は、エレメントにカラムを書かなければ null になります。

f:id:duck8823:20161106001224p:plain

最初のレコードに null を指定して、二つ目以降のレコードには任意の値を指定したい場合、困ったことになります。
データセットを以下のように書いてインサートすると

f:id:duck8823:20161106001710p:plain

二つ目のレコードのnameカラムに値が入ってくれません。
どうやら一つ目のレコードに記述されているカラム名しか見ないようです。
二つ目以降のカラムに存在しないカラム名を指定してもエラーになりません。

ReplacementDataSet を利用することで null をインサートすることが可能になります。

文字列 {null} を null に変換しています。
データセットは次のように用意します。

f:id:duck8823:20161106002529p:plain

これで null がインサートされました。
普段はアノテーションでデータセットを指定できる TestExecutionListener を作ってこれを利用しています。
テスト毎にデータセットを指定するのに、以下のようにアノテーションで指定出来て便利です。

Perl6でprivateなメンバにコンストラクタで値を渡したい

Perl6

※ 追記あり

Perl6でprivateなメンバを作ったときに、コンストラクタで値を渡せなくてちょっとハマったのでメモ。

publicなメンバを設定する場合、

メンバ変数の $ の後に . をつけることで、アクセッサが自動的にできます。
インスタンスからメンバ名でアクセスできるようになります。
また、デフォルトコンストラクタでは、名前付き引数としてpublicなメンバに値を渡してやることができます。

publicなフィールドのみ持つクラスを作る場合はめっちゃスッキリ。
Pythonの namedTuple とかそんな感じで使えますね。

さて、メンバをprivateにしたい場合はどうするのか。
変数の . を ! に変更することで、 private なメンバになります。

この場合、アクセッサは自分で記述する必要があります。
また、デフォルトコンストラクタでは値を渡すことができません。

じゃあ、コンストラクタをオーバライドしてみましょう。

これでもダメでした。
blessの時点で値が入ってこないみたい。

それなら、blessした後に private なメソッドを介して値を渡してやればいいんじゃないか。

イケました。
private なメソッドはメソッド名の前に ! をつけます。
インスタンスから実行しようとしてもちゃんと syntax error になりました。

アクセッサをオーバライドする

アクセッサをオーバーライドしてdieするなどして、アクセスできなくしちゃう方法もあります。
この場合、コンストラクタはデフォルトでいいので便利かも。
クラス内からメンバ変数にアクセスする場合に . でアクセスするとオーバライドしたメソッドが呼び出されてしまうので、 ! でアクセスするのが注意点。


[2016/11/06追記]

BUILDで書く

ご指摘いただきました。公式でちゃんと書かれてますね。

submethod BUILD で private なフィールドに値を設定できます。
ご指摘&URLのご紹介ありがとうございます。
newをオーバーライドするのは、どうしても固定長引数にしたい時など限定的な場合のみにした方がよさそうですね。

ウェブでログインが必要なルーチンワークをPythonスクリプト書いてJenkinsさんに実行してもらう

Python Jenkins 自動化

最近、ルーチンワークを少しずつ自動化しています。
ウェブをチェックするようなルーチンはスクレイピングを行うのですが、ログインなどのブラウザ操作が必要な場合もあります。
ブラウザ操作が必要な場合でも自動化するのが今回の目標。

Python + Seleniumで自動操作

ウェブブラウザの自動操作はSeleniumの得意とするところです。
JavaPythonPerlRubyJavaScript(Node.js)など様々な言語で利用できます。

やっぱりパパッと書いて実行するのはスクリプト言語の得意とするところですね。
普段はPerlスクリプトを書くことが多いのですが、今回はPythonで書きました。
理由は、 Selenium Server を実行するのがめんどくさかっただけ(これも後述するDockerfileに書いちゃえばあとは簡単)。

今回は、Facebook
f:id:duck8823:20160903215516p:plain
この部分の新着通知をSlackに通知したいと思います。

書いたPythonスクリプトはこんな感じ。


WebDriverのAPIこちらを見れば書いてあります。
引数に渡されたユーザ名とパスワードを利用してFacebookにログインし、ログイン後のページ要素から情報を取得しています。

Slackへの通知はWebHooksを利用。
WebHooksのURLは適宜変更してください。

このスクリプト


で実行できます。

f:id:duck8823:20160904015408p:plain
ローカルマシンで実行する場合はWebDriverをFirefoxで指定するといいです。

Dockerで実行できるようにする

上のスクリプトをJenkins上で実行できるようにするには、Dockerコンテナを作ってその中で実行するのが楽です。
Python3.5、Selenium、PhantomJSをインストールしたDockerfileはこちら。


これを実行するのは、


Jenkinsに実行させる

ジョブはフリースタイルで作成しました。

ソースコード管理

f:id:duck8823:20160904012339p:plain
スクリプトとDockerfileがあればよいので、gistにのせてそこからcloneするようにしました。

ビルド環境

f:id:duck8823:20160904012624p:plain
パスワードをビルドに直書きしたくなかったので、credentialsに登録したユーザ名とパスワードを利用できるようにします。
(コンソールには表示されてしまいます。)
Credentials Buinding Pluginを利用しました。
参考にしたのは、ここ

ビルド

f:id:duck8823:20160904013052p:plain
Dockerを実行させるスクリプトのユーザ名とパスワードを、ビルド環境のUse secret text(s) or file(s)で指定したものに変更します。

定期的に実行させる

f:id:duck8823:20160904013401p:plain
あとは定期的に実行させるだけです。
ビルド・トリガ定期的に実行にチェックを入れ、cron形式でスケジュールを登録します。
上記の例は毎朝9時に実行する例。



これを応用すれば内部サイトのアップデート確認、実行などいろんなことができます。
JenkinsもDockerがあれば簡単に実行できるいい時代です。
ローカルJenkinsさんを雇ってルーチンワークを肩代わりしてもらいましょう。