技術関連の覚書

案件でやったり自宅で試したことの覚書

Java8をおさらいしつつJava9を眺める

https://d-cube.connpass.com/event/62507/

こちらに行って来ました

案件ではJDK8を使いながらJava7までの機能しか使えないなど(規約でLambda、Streamを許可されない)でちゃんと使ってこれなかったのでこれを機会に案件でどのように使ってきてJava9ではどのようにしたらよいかを聞いてきました。

これまでの開発環境(Java6+7)からJava8へ移行した時の話

Lambda式とStreamAPIの登場

Lambda式は1メソッドのインタフェースと実装をそのまま1行で書けるような記述ができます。 、Listや配列などのループを1行で記述もできます。 こういったことからfor文禁止にトライしてみたようです。

今までListをFor分で書くところがStreamで書くと1行で書けて見通しが良くなる →for文禁止の規約ができた

Streamを使えば

List lang = Arrays.asList("Java7", "Java8", "Java9");
for (String s: str) {
    System.out.println(s);
}

List lang = Arrays.asList("Java7", "Java8", "Java9");
Stream<String> st = lang.stream();
st.forEach(System.out::println);

にできます。

並列処理の場合はlang.stream()をlang.parallelStream()にするだけです。

やってみると

  1. for文よりも完結で読みやすい

  2. 並列処理も簡単に書ける

しかし

  1. 例外処理はそんなに得意ではない

  2. for文ダメ絶対はなかなかできない

for文を許す場合は * 処理が複雑で可読性が下がる場合 * count++などしたい時 →Finalになってしまうので値に変更を加えたい場合

結論

  • for文は原則禁止

  • 完全駆逐は難しい

  • StreamとLambdaで書くことでぱっと読みにくいが指摘しやすくなった*1

見通しの良いコードを書くことが大事

Date & Time APIの登場

Calendar 月が-1 Calendar.Julyなどなら問題はないが7にすると8月になってしまうなどバグの元があった

Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2017)
cal.set(Calendar.MONTH, Calendar.JULY) // ここをcal.set(Calendar.MONTH, 7)にすると8月になる
:

LocalDateTime date = LocalDateTime.of(2017, 7, 26, 15, 0, 0);

しかし、

  1. Javaの日付処理系はすでに資産があるのであまり困らなかった

  2. Date & Timeはたしかに便利

正直なところすでに日付処理はUtilなど整備していたのであまり有り難みがなかった*2

既存のコードは無理してリファクタリングしない 新規に使うならDate&TimeAPIの方がよい

これは同感でした

Optional

Optional<String> strOpt = Optional.of("Java")

//インスタンス生成

System.out.println(strOpt.get())

空のOptionalの生成

Optionalから値がある場合のみ処理をする if文で分岐するのはアンチパターン

if (s!=null) {
    System.out.println(s);
}

このように

ifPresent(s -> {
  System.out.println(s);
});
  • Optional -> nullであることを明示的に許容する

  • その戻り値にnullがあることをソースレベルで表現できることに価値がある

  • すべてOptionalにしたらいいというわけでない

  • isPresent+getはあまり今までと変わらないので使わないようにしてる

  • 使うならifPresentやorElse,orElseGet

java8は現場の開発者にとってインパクトが大きい変更が多数会った StreamやLambda式、Optionalなどは実装方針に影響をもたらしたのでは?

といった結論でした

Java5で変わったくらいの変更はあった感じはあるかな

それ故に

  • コーディング規約などはもっと早い段階で見直したかった

  • 学習コストはそんなに高くなかった印象(みんな新しい物好き)

逆に変わりすぎて手を付けられずにいるところも多かった感じもあります。 ただ、使ってみれば便利なんですけどね

Java9ではどうなる?

JDK 9 ここからダウンロードして使えます

開発者目線で気になるもの

jshell(REPL)

とりあえず、/helpと/exitを覚えておけばだいたい使える

jshellツールを使用するとJavaコマンドを実行して即座に結果を取得できる 1行実行でHello,Worldが書ける クラスを作る、メソッドを作る、他のメソッドをインポートできる

  • 補完が聞くようになってるのでタブを押して書ける

  • やろうと思えばいろいろできる

  • 最初の一行を実行するのが圧倒的に楽

  • 業務では使いドコロが思いつかない スクリプト的な開発みたいなことができるかですね

  • 初学時にちょっといじる

  • ペアプロで見せるなんかの時はいいかも

Read-Eval-Print-Loop

Rubyなんかにはあった

Stream新メソッド

  • takeWhile

list.stream().takeWhile(s -> s.startsWidth(“J”)).forEach(System.out::println);

  • dropWhile

list.stream().dropWhile(s -> s.startsWith(“J”)).forEach(System.out::println);

  • ofNullable

Java8でやるとnullチェックが必要な場合 map.get() == nullをチェック

keys.stream().flatMap(str -> Stream.ofNullable(map.get(str))).forEach(System.out::println);

Optional

ifPresentOrElse

opt.ifPresentOrElse(s -> System.out.println(“This is ”+s),() -> System.out.println(“nothing”));

Optional#Stream

OptionalをStreamに変換することができる

Optionalで構成されるListがある時StreamとflaMapを併用すると簡単nullをスキップした処理ができる

list.stream()

Optionalが使いやすくなる 使いドコロが増えそうな文ちゃんとコーディング規約を決めたい 実装時以外でnullを意識しないで良い

ImmutableなCollectionのファクトリーメソッド

List#of Set#of Map#of

コレクションのインスタンスを作る時

new Map<>(){{
  put();
  ..
}};

Guavaでイミュータブル

immutableMap = ImmutableMap.builder().put().put()...

がこんな感じに

list = List.of("Java7", "Java8", "Java9");
Set.of("Java", "Go", "Rub", "Scala");
Map.of("key1", "value1", ...)

もさっとしてたコードがすっきりする ライブラリを使ってたところが標準でできるようになる

Mapはkey,valueで改行しないと混乱しそうな気もします

モジュールシステム

jigsaw

Javaをモジュール化して必要な部分だけを使えるように

クラスパスと肥大化したJDK →複雑になり管理が難しくなる →依存関係がコンフリクトを起こす可能性がある

言語仕様の強化ではなくmoduleの機能と解決するもの

機能パッケージの依存関係の記述 公開するクラスとしないクラスの明治 予期せぬ利用をコンパイルエラーでチェック

解決するもの 意図しない場所でのpublicクラス利用による複雑さ

公開したいもの

  • 抽象的なもの

  • クラスへのアクセス

  • インタフェース

  • ファクトリ

公開しないもの

  • 実装

  • bean

  • model

向いてる開発

  • 大規模

  • 大人数

必要なさそう

  • 小規模

  • 少人数

→大きくなりそうならむしろ初めからモジュールを設計したほうがいい

すでに稼働している巨大なシステム →不要というよりおそらく難しい

実際にモジュールを使う場合

サイトA moduleとBmodule

大規模プロジェクト 大規模リファクタリングをする時

小規模プロジェクト moduleを使った安全な設計を取り入れる

システムのコンポーネント化をより意識

システムの導入は新規にしろ既存にしろ設計をしっかり意識する必要がありそう

大規模システムでのそれぞれが行ってたルール作成や規約づくりを標準に合わせる形にできるのでリプレース案件では使えるのかな?

延期延期で今年9月まで延ばされたJava9ですが、Jshellで動作を見ながら実装していくような開発になりそうです

*1:ただし、デバッグはしづらくなることもある

*2:確かに日付関係のライブラリを独自に作ってるところは多いです

Amazon LinuxでSlackbotを作ってみる

さっき作ったAWSインスタンスにSlackbotのプログラムを仕込んでみます

python環境の準備

[ec2-user@ip-10-0-10-50 ~]$ python --version
Python 2.7.12

python3系とpipをインストールする

[root@ip-10-0-10-50 ~]# yum search python3
Loaded plugins: priorities, update-motd, upgrade-helper
============================= N/S matched: python3 =============================
mod24_wsgi-python34.x86_64 : A WSGI interface for Python web applications in
                           : Apache
mod24_wsgi-python35.x86_64 : A WSGI interface for Python web applications in
                           : Apache
postgresql92-plpython27.x86_64 : The Python3 procedural language for PostgreSQL
python34.x86_64 : Version 3.4 of the Python programming language aka Python 3000
python34-devel.x86_64 : Libraries and header files needed for Python 3.4
                      : development
python34-docs.noarch : Documentation for the Python programming language
python34-libs.i686 : Python 3.4 runtime libraries
python34-libs.x86_64 : Python 3.4 runtime libraries
python34-pip.noarch : A tool for installing and managing Python packages
python34-setuptools.noarch : Easily build and distribute Python packages
python34-test.x86_64 : The test modules from the main python 3.4 package
python34-tools.x86_64 : A collection of tools included with Python 3.4
python34-virtualenv.noarch : Tool to create isolated Python environments
python35.x86_64 : Version 3.5 of the Python programming language aka Python 3000
python35-devel.x86_64 : Libraries and header files needed for Python 3.5
                      : development
python35-libs.i686 : Python 3.5 runtime libraries
python35-libs.x86_64 : Python 3.5 runtime libraries
python35-pip.noarch : A tool for installing and managing Python packages
python35-setuptools.noarch : Easily build and distribute Python packages
python35-test.x86_64 : The test modules from the main python 3.5 package
python35-tools.x86_64 : A collection of tools included with Python 3.5
python35-virtualenv.noarch : Tool to create isolated Python environments

  Name and summary matches only, use "search all" for everything.

python3.5をインストールする

sudo yum -y install python35
sudo yum -y install python3-pip

pip の後に[Tab]キーを押すと候補が

pip
pip      pip-2.7  pip-3.5 

のように出てくるので pip-3.5 を使ってslackbotのインストール

pip-3.5 install slackbot

pythonでプログラムを書く

PythonのslackbotライブラリでSlackボットを作る - Qiita

ここを参考にプログラムの構成を作る

API_TOKENの値を設定

ボットのsettingを押下して

f:id:boctok-ctpoba:20170717223722p:plain:w300

f:id:boctok-ctpoba:20170717224032p:plain:w300

このままだとSlackとの間の通信ができないのでHTTPSでSlackとアクセスできるようにする

EC2のダッシュボードで「セキュリティグループ」を選び タブの「インバウンド」を選択 編集を押下して 「ルールの追加」を押下

項目 設定値
タイプ HTTPS
ソース カスタムを選んでSlackのIPアドレスを登録(xxx.xxx.xxx.xxx/32)

上記を設定して保存

EC2でサーバを作る手順

AWSでサーバを立てて見る手順

ネットワークの構築

ネットワーク構築(VPC)*1

AWSマネジメントコンソールの「ネットワーキング&コンテンツ配信」にある「VPC」をクリック

f:id:boctok-ctpoba:20170712230828p:plain:w300

VPCダッシュボードの「VPC」を選択

f:id:boctok-ctpoba:20170712230559p:plain:w300

VPC 接続の作成」を押下

f:id:boctok-ctpoba:20170713090904p:plain:w300

VPCを作成する

項目 入力値
名前タグ 任意の名前
PIv4 CIDR ブロック 10.0.0.0/16
IPv6 CIDR ブロック IPv6 CIDR ブロックなしを選択
テナンシー デフォルト

入力したら「はい、作成する」を押下

f:id:boctok-ctpoba:20170713091224p:plain:w300

インターネットゲートウェイの作成*2

ダッシュボードで「インターネットゲートウェイ」をクリック

f:id:boctok-ctpoba:20170713094238p:plain:w50

「インターネットゲートウェイの作成」を押下

f:id:boctok-ctpoba:20170713094759p:plain:w300

インターネットゲートウェイを作成する

項目 入力値
名前タグ 任意の名前

入力したら「はい、作成する」を押下

f:id:boctok-ctpoba:20170713095436p:plain:w300

この時点でまだアタッチされていないのでアタッチする

f:id:boctok-ctpoba:20170713100207p:plain:w300

前に作成したVPSを選択して「はい、アタッチする」を押下

f:id:boctok-ctpoba:20170713100907p:plain:w300

サブネットの作成*3

ダッシュボードの「サブネット」をクリック

f:id:boctok-ctpoba:20170713101302p:plain:w300

「サブネットの作成」を押下

f:id:boctok-ctpoba:20170714000641p:plain:w300

サブネットを作る

項目 入力値
名前タグ 任意
VPC 登録したVPCタグ
アベイラビリティーゾーン 任意
IPv4 CIDR ブロック 10.0.10.0/24

入力したら「はい、作成する」を押下

f:id:boctok-ctpoba:20170714001253p:plain:w300

ルートテーブルの作成

「ルートテーブル」を選択

f:id:boctok-ctpoba:20170715232417p:plain

「ルートテーブルの作成」を押下

f:id:boctok-ctpoba:20170716001546p:plain:w300

項目 入力値
名前タグ 任意
VPC 作成したVPCを選択

入力したら「はい、作成する」を押下

サブネットの関連付け

下の方にあるタブから「サブネットの関連付け」を選択

f:id:boctok-ctpoba:20170716235925p:plain:w300

「編集」を押下

f:id:boctok-ctpoba:20170716235208p:plain:w300

先ほど作成したサブネットを選択して「保存」を押下

f:id:boctok-ctpoba:20170717000359p:plain:w300

インターネットゲートウェイの設定

タブから「ルート」を選択

f:id:boctok-ctpoba:20170717000751p:plain:w300

「編集」を押下

f:id:boctok-ctpoba:20170717000850p:plain:w300

「別のルートを追加」を押下

f:id:boctok-ctpoba:20170717001022p:plain:w300

項目 入力値
送信先 0.0.0.0/0
ターゲット 作成したインターネットゲートウェイ*4

入力したら「保存」を押下

f:id:boctok-ctpoba:20170717001330p:plain

ルートテーブルの確認

ダッシュボードで「サブネット」を選択した後作成したサブネットにチェックを入れる

ルートテーブルタブを選択して内容を確認する

インスタンス構築(EC2)

ホーム画面の「コンピューティング」にある「EC2」を選択

インスタンスの作成」を押下

f:id:boctok-ctpoba:20170717002317p:plain:w300

AMIからAmazon Linux AMIを選択

f:id:boctok-ctpoba:20170717002529p:plain:w300

インスタンスタイプ「t2.micro」を選択して「次の手順:インスタンスの詳細の設定」を押下

f:id:boctok-ctpoba:20170717003006p:plain:w300

項目 設定値
インスタンス 1
ネットワーク 作成したVPC
サブネット 作成したサブネット
自動割り当てパブリック IP 有効化
テナンシー 共有-共有ハードウェアインスタンスの実行

「ネットワークインターフェイス」の「IPの追加」を押下して 「プライマリIP」に「10.0.10.*5を設定

入力したら「次の手順:ストレージの追加」を押下

f:id:boctok-ctpoba:20170717150247p:plain:w300

値はデフォルト値のまま(サイズ=8G、ボリュームタイプ=SSD)「次の手順:タグの追加」を押下

f:id:boctok-ctpoba:20170717152844p:plain:w300

「タグの追加」を押下

f:id:boctok-ctpoba:20170717154523p:plain:w300

キーと値を設定して「次の手順:セキュリティグループの設定」を押下

f:id:boctok-ctpoba:20170717155929p:plain:w300

セキュリティグループ名を任意に設定してデフォルトのセキュリティグループをに チェックして「確認と作成」を押下

f:id:boctok-ctpoba:20170717161426p:plain:w300

「起動」を押下してキーペアの作成

f:id:boctok-ctpoba:20170717165612p:plain:w300

ダッシュボードで「キーペア」を選択し、「キーペアの作成」を押下 任意の名前をつけて「作成」を押下

f:id:boctok-ctpoba:20170717164929p:plain:w300

公開鍵がダウンロードされるので任意のディレクトリ(通常 ~/.ssh の下)に移動して読み取り専用に変更 chmod 400 公開鍵.pem

インスタンスの状態がrunningになったら

f:id:boctok-ctpoba:20170717215507p:plain:w300

ssh -i 公開鍵.pem ec2-user@パブリックIPのアドレス

で接続してみる

*1:Virtual Private Cloud

*2:インターネット経由でVPCに接続するためのゲートウェイ

*3:VPC内での分割したネットワーク。ネットワークを分割することで他のサブネットに影響を与えにくくすることで安全性を高める。

*4:フォーカスすると候補が出てきます

*5:は任意の値、1はダメだった

無茶振りへの対応

技術と離れるかもしれないけど、マネジメントとしてはちょっと書き残しておこうかなと言うことを

客先から1週間前倒しでお願いしますという無茶振りを水曜日に言われた時の話

リーダーから、休日出社して欲しいと言われましたが、期限は金曜日 休出したところで完成するのは月曜日になります 休出して遅れ出したと怒られるので無意味なことはやりたくはありません

普通なら間に合わないんですが、やり方があまりに効率悪いと思っていたので 間に合わせろというのであれば、お客さんにも手伝ってもらう手はずをつけない限り無理という提案をしました。

リーダーが動いてくれたと言うよりはお客さんの方も上から言われてのことで 無理はわかってるからできるだけ協力すると言ってくれたので実現できた感じもあります。

今回の納品物はドキュメントで、更に修正担当は他のチーム。 自分のチームに関わるところをチェックして実装と相違がないか確認して各担当に渡すというものでした。

これまでの手順 すべて紙の上で行って赤入れされたものをレビュー記録表に記入して担当者に渡します。

  1. 内部で打ち合わせてチェック

  2. 修正後、内部で再びチェック

  3. 内部レビューでOKが出た後客先に提出してレビュー

  4. 客先からNGがあれば修正、これを1からやり直す

  5. 客先OKとなったものを納品

ちなみにレビューは紙です

今回の手順

間に合わせるために内部レビューと客先レビューを一緒にしてしまえばいいので 会議室にノートPCを持ち込み

  1. チェックする人とお客さんは紙に慣れているので印刷物を用意して読んでもらった上で指摘部分を出してもらう

  2. 洗い出したものは、全てレビュー記録表にその場でお客さんと合意した内容で書き込み

  3. レビュー記録表を各担当の窓口に渡す

この方法にしてどうにか木曜日にレビューを終わらせて金曜日の納品に間に合わせることができました。

ただ、今は普通は後者のやり方のではないかと思いますが、全社のやり方も少なくはないかもしれません。

どうすれば早く終わるかというのは精神論ではなくいかに無駄な作業を省くかにあります。

ウォーターフォールが悪いというわけではなく、ウォーターフォール開発で失敗する多くのパターンは テスト工程をテストの実施時間しか取らないこと。

テストしてバグが見つかれば当然、修正が必要ですが、大昔、まだソースを紙に書いてキーパンチャーが入力していた時代の話(私も聞いたことしかありません) 机上でのチェックで全てバグは取り除かれていて、テストは完全に動くことをお客さんに提示するため というものだったようです。 だから、バグが出ると大騒ぎになる、隠すといったことがあったようです。

テストというのは、本番までにバグをなくすための作業なんですけどね。

そんな大昔のやり方を今も守り続けているところもあるので、そういうところに対しては文明の利器 自動テストなんてものはその信頼性とかを問われます。

登場してから15年以上経ち、やり方も公表されていて成功例も数多くあるのでそれを見せてあげることが良いのかなと思います。

ITについては伝統を守ることはあまり良い言葉ではないですね。

第2回 Alteryx User Group in 東京

【7/3】第2回 Alteryx User Group in 東京 - connpass

こちらに行ってきましたが、当日仕事で予定外の急ぎの仕事が舞い込み会場に到着した頃にはこの話が終わる頃でした。

第2回Alteryx User Group in 東京で「新製品&新機能紹介」の発表をしました #alteryx_ug | Developers.IO

前回のじょんすみすさんの話はこちらです

Alteryxユーザグループ第1回勉強会でLT発表しました | #alteryx #alteryx_ug | Developers.IO

BIツールはなかなか使う機会がないですが、やはり今後需要は伸びると思うので抑えておきたいです。

最後の藤さんのハンズオンでしたが、残念ながら私のPCにはAlteryxは入ってませんでした。

操作自体は簡単そうなのでどこかで試せるといいなと思う勉強会でした。

Developers.IO 2017に行ってきました(3)

14時 実案件で見るデータ分析用AWS基盤の構築方法

Developers.IO 2017セッション「実案件で見るデータ分析用AWS基盤の構築方法」を発表しました #cmdevio2017 | Developers.IO

元々はGlueの話の予定がまだ東京リージョンで公開されず急遽変わりました。

Redshiftは自分で試すには高額なサービスなので話だけでも聞きたいなと思っていたので良かったのですが、 やはり触ったことのないサービスはイメージしづらい。

ドキュメント読んで復讐が必要だなあ。

17時 Amazon Elasticsearch Service の使いドコロ

Developers.IO 2017セッション「Amazon Elasticsearch Service の使いドコロ」で話しました #cmdevio2017 | Developers.IO

私はElasticsearchは入れてみてちょっとした検索ならしたことがあって、全文検索の仕組みはなんとなくわかる程度です。 MySQLでも全文検索の機能があったりするので使ってる人もいるのかな。

RDBMS製品にも付いてたりします。

案件ではsolrは使ったことはあるんですけどね。

もうちょっと本格的にやってみようと思うセッションでした。

この後は FestivalIO

飲みながらのスポンサー企業の方のセッションがありました、

Developers.IO 2017に行ってきました(2)

みんな早いな いくつかすでにレポートブログが上がってました。 お弁当の内容、クラスメソッドの企業案内などランチセッションの話は書いてる方が多かったので別の見方で行ってみます。

それから、昨日書き忘れてましたが、クラスメソッドのロゴが変わったそうです。

classmethod.jp

昨日の続きで、12時からのランチセッションです。

だそうです。 ごちそうさまでした。

この後の懇親会でもお酒や食べ物が出てきたので食費だけでもかなりお得です。

横田社長のセッションですが、マーケティング部嵩原部長との掛け合いも楽しかったです。

横田:女性比率が上昇、特にマーケティング部が多いです 嵩原:別に侍らせてるわけじゃないですよ

クラスメソッドにはベルリン、バンクーバと海外にも拠点があること これは時差がおよそ8時間の場所を選び、リモートで作業しているため日本で夜間になる作業も国外で日中に行うため 横田社長いわく 「私は、徹夜でゲームをするのは好きですが、夜勤は嫌いです」とのことでした

肝心なこと

これからのUIとしてAlexa事業部を作った話。 今の子は(横田社長の子供の話でした)パソコンの画面をスワイプしたり、テレビのリモコンに話しかけたりするくらい スマホがあるのが当たり前の時代に生まれ、自分たちはもう古い世代だと(私はそれより古い世代だったりします) そんな世の中でもお年寄りは手紙や電話が中心の通信をしているというので、そのような人たちも使えるインタフェースVUI(Voice User Interface)に着目したということでした。

AWS Pollyなど優秀な音声変換もあるし、OK GoogleやHey Siriなど音声変換はすでにあるので今後その精度を上げて 誰もが使えるインタフェースになっていくでしょう。

chatOpsからvoiceOpsへと変えていく動きもありますし。

13時 Developers.IO 2017セッション「A1. クラメソの請求を支える技術 〜40歳中年エンジニアの生存戦略〜」#cmdevio2017 | Developers.IO

月3〜5件くらいの請求が300件超に急増して営業も事務もほとんど請求の作成に追われる事態になっていた。 これを解決した結果

しがないOLのはじめてのMySQL | Developers.IO

となったようです。

後半は40歳中年エンジニアの生存戦略

何でもできる人なんていない 開発だけがエンジニアの仕事ではない

一時期フルスタックエンジニアと言う言葉が流行りましたが、これだけ多様化してくると何でもできる人というのは化物でしょう。 もちろん、なんとなくわかることは大事ですが。

自分も、全体を通せば一通りやっては来ましたが何でもできるとは違うなと思います。 ある意味ではフルスタックですが、どれもそれなりなエンジニアかなと思って過ごしてましたが なんか救われた気がしました。

また次の日に持ち越しです