ABC129

ABC129に参加しました。Ratedのコンテストは2か月ぶりでした。

atcoder.jp

言語はJava8です。

A問題

a+b, b+c, c+aの中から最小値を出力する問題。

他の人の解答も見てみましたが、Javaの場合、意外にも3つの数字の中から最小のものを出力する気軽な方法はないく、Math.minを2回実行するやり方が多かったです。

https://atcoder.jp/contests/abc129/submissions/5837288

4分でAC。

B問題

問題のいう、S1とS2の差の絶対値は、「合計ーS1*2」の絶対値で求められるのでそれで解きました。

https://atcoder.jp/contests/abc129/submissions/5841491

8分でAC。

なんか冗長だなと書きながら思っていた以下のコードは、やはり改良の余地がありました。

if (Math.abs(sum - calc - calc) < minDifference){
    minDifference = Math.abs(sum - calc - calc);
}

改良後は以下

minDifference = Math.min(minDifference, Math.abs(sum - calc - calc));

C問題

パッと思いついた基本的な方針は以下の通りです。

  • ある段のわたり方は、「1つ前の段のわたり方」+「2つ前の段のわたり方」で表される。
  • 穴が開いていた場合、その段のわたり方は0通り。

最初の1.2段だけ気を付ければいいかな、と思いましたが、一点気を付けないところがありました。*1

ArrayList.contains()は遅い

それは、上記の通り、ArrayList.contains()は時間がかかるということです。

以下はTLEになった提出です。ある段が穴が開いているかの判別をしているところで、contains()を使っています。

https://atcoder.jp/contests/abc129/submissions/5846757

対応法は2つあります。

  • HashSetを使う

https://atcoder.jp/contests/abc129/submissions/5864593

  • 検索不要にする

例えば、自分の場合は穴の段数を下から順に取り出して*2、その段数の処理が終わったら次の穴の段数を取り出す、というようにやっていました。

他の人の解答例を見ると、すべての段について、穴が開いているか否かの配列をあらかじめ用意しているものもありました。

https://atcoder.jp/contests/abc129/submissions/5849100

37分でACしましたが、4回誤答しました。

D問題

本番中は解法が思いつきませんでしたが、解説を読むとそこまでひねったやり方ではないなと思いました。

for文を2000 * 2000 回しても結構速いんですね。

https://atcoder.jp/contests/abc129/submissions/5863198

結果

パフォーマンス:899

レーティング:588 → 636 (+48)

またがんばります。

*1:先に細かいところを補足しておくと、答えをこまめに1000000007で割るとか、穴が一つも空いていないパターンをカバーするなど

*2:本質とはあまり関係ありませんが、入力は小さい順になっている

Javaのより良い書き方を指南する『Java言語で学ぶリファクタリング入門』(2/2)

結城浩Java言語で学ぶリファクタリング入門』を写経しつつ読み終わりました。

Java言語で学ぶリファクタリング入門

Java言語で学ぶリファクタリング入門

本書は全部で15章あり、大きく3つの内容に分かれています。

そのうち、本エントリーでは「クラスの関係を整える大規模なリファクタリング」を説明した第11章~第15章を扱います。

「コードを整える小規模なリファクタリング」「クラスを整える中規模なリファクタリング」を説明した第10章までを扱ったエントリーはこちら

対象読者

  • プログラミングを初めて日が浅い人
  • Javaでの開発・実行環境がある人

サンプルコードの処理内容はそれほど難しくないと思います。2つ目の条件の理由ですが、本書を有効活用するには、実際にコードを書くことが不可欠なためです。

クラスの隠蔽

第11章はFactory Methodを扱っていますが、本書でも重要な章だと思います。

クラス名がnewでハードコードされているのを、Factory Methodに置き換えるリファクタリングです。

このリファクタリングによって何ができるようになるかというと、呼び出し側*1が、Factory Methodでインスタンス生成を行うことで「実際に生成するクラスを実行時に定めることができ」ます。

本書でのリファクタリング後のコードを例にとります。呼び出し側(Main.java)で、図形のインスタンスを作成するコードは以下のようになっています。

Shape line = Shape.createLine(0, 0, 100, 200);
Shape rectangle = Shape.createRectangle(10, 20, 30, 40);
Shape oval = Shape.createOval(100, 200, 300, 400);

251ページから253ページを見ればわかるように、ここで作成されるインスタンスのクラスは、それぞれShapeのサブクラスであるShapeLine、ShapeRectangle、ShapeOvalとなっています。

しかし、呼び出し側ではそれらのクラス名は登場しない、すなわち隠蔽されています。

さて、第11章で重要なポイントは練習問題にもあります。

それはDependency Injectionです。呼び出し側でのインスタンスの生成時に依存関係を作り出す手法です。詳しくは練習問題の解答を参照してください。

DIについて、Spring入門書では、「開発者がFactory Methodなどのデザインパターンを駆使しなくても、DIコンテナから受け渡されるインスタンスをインタフェースで受け取れば、インタフェースベースのコンポーネント化が実現できる」と記載されています。

軽く調べた*2ところ、本書が出版されていた2007年当時ではSpring2.0が出ていたようです。

DIとFactory Methodが、似たような問題を解決するための手法であることを知れたのは、大きな収穫でした。

継承と委譲

第13章から第15章では、継承と委譲についてのリファクタリングが説明されていて、方針としては継承をやめて委譲を用いています。

Effective Javaでは継承について、スーパークラスの変更にサブクラスが影響されてしまうから使うときは注意すべきという指摘をしています。

個人的な感覚としては、Is-a関係があまり成り立ってなさそうだけど継承を使ってしまった、という経験はあまりないような気がします。

とはいえ、相続拒否に対しては良くない匂いを感じ取れるようになりたいですね。

これ以上先に進もうとすると、Javaにおける設計についてより深く学ぶ必要がありそうです。

まとめ

文法を知っている、実際に動くコードが書ける、より洗練されたコードが書けるという3ステップを考えたとき、本書では2つ目から3つ目のステップを学べると思います。

特に5章・6章・8章・11章が、個人的には重要に感じました。理由としては、出現頻度が高いことや、修正についての解説の有用性が高いことが挙げられます。

*1:本文中では「クライアント」と言われている

*2:参考→https://www.slideshare.net/movmov/spring-12-49833796

Javaのより良い書き方を指南する『Java言語で学ぶリファクタリング入門』(1/2)

結城浩Java言語で学ぶリファクタリング入門』を写経しつつ読んでいます。

Java言語で学ぶリファクタリング入門

Java言語で学ぶリファクタリング入門

本書は全部で15章あり、大きく3つの内容に分かれています。

そのうち、本エントリーでは「コードを整える小規模なリファクタリング」「クラスを整える中規模なリファクタリング」を説明した第10章までを扱います。

「クラスの関係を整える大規模なリファクタリング」を説明した第11章~第15章は別エントリーに回します。

対象読者

  • プログラミングを初めて日が浅い人
  • Javaでの開発・実行環境がある人

サンプルコードの処理内容はそれほど難しくないと思います。2つ目の条件の理由ですが、本書を有効活用するには、実際にコードを書くことが不可欠なためです。

リファクタリングが行われるべき二つの理由

本書を読んでいるとリファクタリングが行われる理由や背景は二つあるように思います。

  • 未熟なプログラマーによるもの
  • 度重なるプログラムの修正によるもの

未熟なプログラマーが書いたコードはそもそも修正の余地があります。

一方で、「最初から全部正しく」コードを書けていてもリファクタリングは必要です。第5章で

プログラムというものは作られた後、たくさんの修正を受けるものです。

とあり、それらの修正に合わせて、リファクタリングは必要になっていきます。

最初から正しく書けそうな章

取り上げられている章のいくつかは、リファクタリング前のコードが明らかにイケてないものがあります。

先ほど挙げた背景のうち「未熟なプログラマー」の方です。

例えば、第1章はマジックナンバーの是正を扱っているのですが、これについては初めからマジックナンバーを含まないようにコーディングしていれば、そもそもリファクタリングが必要なくなります。

特に以下の章は、このように「そもそもどんな時でも修正前のような書き方はしないだろう」という印象を受けました。

  • 第1章:《シンボリック定数によるマジックナンバーの置き換え》
  • 第2章:《制御フラグの削除》
  • 第7章:《クラスによるタイプコードの置き換え》
  • 第10章:《例外によるエラーコードの置き換え》

多かれ少なかれ、全部の章にあてはまるのかもしれません。例えば、いくつかの章で見られる、以下のようなタイプを示すコードです。

    public static final int TYPECODE_LINE = 0;
    public static final int TYPECODE_RECTANGLE = 1;
    public static final int TYPECODE_OVAL = 2;

上の3行は図形のタイプを示しているのですが、Enumを使うし、数値は使わなさそうです。

このように、本書にはJavaより良い書き方を指南しているという側面があります。

一方で、修正や機能追加が進んだ結果、ifやswitchが増えてしまったので、それを整理していく、といった行為は、「度重なるプログラムの修正」で必要になったリファクタリングでしょう。

リファクタリングを狭く考えすぎた?

ここで、本書に立ち戻ってリファクタリングの定義を確認すると、

外部から見たプログラムの振る舞いを変えずに、プログラム内部の構造を改善すること

とあります。つまり、プログラムの改善理由は何でもいいわけで、本書が単純な*1Javaのより良い書き方とは」という内容になっていても全く問題ないという考えに至りました。

手を動かすべき

話は変わりますが、本書ではサンプルコードも用意されていますし、リファクタリングの手順も丁寧に記載されています。

実際に手を動かしてリファクタリングすることがとても重要です。

本を見ながらやってできるようにならなければ、実際のコーディングでリファクタリングができるようにならない、と思うからです。

まとめ

ここ最近、自分がJavaを書く上で教わったことや気づいたことがかなり載っていて、その点はうれしかったです。

繰り返しになりますが、分かっているだけではダメで、実際に書けることが重要だと思います。本書は良い練習台になると思います。

*1:主観を多分に含む

#しがないラジオ sp. 60に出演しました

2017年に開始され、現在100エピソード以上投稿されている技術系ポッドキャスト「しがないラジオ」にゲスト出演いたしました!

「出れるポッドキャスト」と謳っていますが、実際出れましたのでそのあたりを記載します。

なぜ出たいと思ったか

これについてはエピソード内でも語っているので補足的に。ポッドキャストの開始以来、いつか出たい*1と思っていたことや、出て話すだけのネタが集まったと思ったことです。

ラジオを盛り上げたいとも思っていて、その最も有効な手段がゲスト出演だった、というのもあります。

出演の流れ

出たいと言う、これだけです。

Slackでメンションを飛ばして出演希望を宣言しました。

f:id:alek3:20190520225802p:plain

1分かからずOKの返事が来た*2ので本当に出れるラジオなんだなと思いました。

宣言時は若干緊張しましたが、後から振り返るとどうってことないのでさっさと言ってしまった方がいいです。

日程調整

出演希望者が結構多いので先になるのかなと思っていましたが、たまたまGWが空いていたのでそこになりました。2週間後くらいの日程でしたが、そのときで6月くらいまで毎週収録が入っていました。

出演

ツクルバさんの会議室をお借りして収録しました。

最初は緊張しました。また、慣れてきても、2人が話しているところに割って入りづらく、結果として自分が話す時間が短かったかな?と思いました。

ただ、私自身はゲストがずっと話すよりも、パーソナリティの2人の考えを聞いてみたいという思いがありましたので、結果としては予定通りでした。

他に感じたのは準備の大切さです。何を話したいか考えたり、メインテーマについては自分の中で掘り下げることがもっと必要だったなと思いました。

公開

収録から2週間足らずで前半が公開、翌週に後編が出ましたので、スピーディーに出していただけたと思います。

自分の声を聞くのは最初非常に辛かったです。しかしそのうち感覚がマヒして慣れていきました。

まとめ

1年後くらいにまた出たいですね。まずは本業でサバイブできるように頑張ります。

*1:と思っていたからネタ集めをしていた

*2:正確には20秒

#genbadeDDD 「レガシーをぶっつぶせ。現場でDDD!」参加しました

こちらのイベントに参加しました!

genbade-ddd.connpass.com

気づいたときには無料参加枠は埋まっていたのですが、ブログ書きます枠が新設されたので、1人目として申し込めました。

以下の記載では基本的には登壇者が話したことを常体で書き、自分の感想とかは敬体で書いています。

登壇者の発表内容の記載がものによって全然違うのは、私の理解力の他に、スライドが公開されるかどうか知らなかったこともあります。結局全部公開されたのですごい。

前置き

イベントの説明にある「技術的負債が社会問題に!?」の内容とほぼ同様

ソフトウェアの核心にある複雑さに立ち向かう

株式会社ギルドワークス 増田 亨

www.slideshare.net

ドメイン駆動設計でなぜつくるのか

  • 動かした後も成長を続けられるようにする
  • ソフトウェアの変更を楽で安全にする
    • コスト・スピード・セキュリティにプラスに作用する
  • 技術の新しい古いは関係ない

「核心にある複雑さ」とは何か

  • ソフトウェア開発では色々な複雑さがある

  • ドメイン駆動設計で重視している複雑さは?

    • ドメイン:ユーザーの活動、ビジネスそのもの、複雑さの源泉
  • ドメインロジックとは何か?

    • →具体的にとらえると、ビジネスルール
  • ビジネスルールを適用する条件によってさまざまな分岐がある

    • そのため、複雑化する
  • ビジネスルールをドメイン層に切り出すと、入出力は面倒だけど複雑ではなくなる

    • したがって、変更が安全になる

その複雑さにどう立ち向かうか

  • 関心の分離の工夫
  • モジュールの構造の工夫

  • 従来のモジュール構造とビジネスルール

  • 計算から入出力を隔離する

    • 例えば、計算結果オブジェクトと、出力(画面、JSON、データベース)は分ける

上記二つの工夫がどのように違うのか、あまり理解できていないところがありますが、どちらにしても複雑さに立ち向かいやすくするための工夫なのかなと解釈しています。

本格的に立ち向かう

  • 深いモデルを探求する
  • ビジネスルールの中核を見定め、中核に集中する
  • ビジネスルール全体の関係を俯瞰的に整理する

エヴァンス本は、第1部~第4部からなる。第1部、2部は入門編で、本格的に立ち向かうなら第3部を読むとよい。

抽象的な教えを試行錯誤しながら解釈した DDD の実践レポート

ほげさん

www.slideshare.net

抽象的な話が多くてまとめづらかったのですが、 P36、37のところは、何となく理解できて、重要なところは依存関係が本当に必要なのか考えることと、変更の巻き添えを食らわないように、抽象化することなのかなと。

DDDサンプルコード ライブリファクタリング

関西Javaエンジニアの会 irof

株式会社ギルドワークス 増田 亨

後ろのほうにいたので何書いているかは具体的に見えませんでしたが、まあ後でコミットしてくれるでしょうということで。

レポジトリ github.com

動くアプリ

https://isolating-the-domain.herokuapp.com/

このIssueに取り組んだ。

従業員登録手順をcordinatorパターンに · Issue #101 · system-sekkei/isolating-the-domain · GitHub

Issueの内容としては、コントローラーの中で複数のサービスを呼んでしまっているから、コーディネーターパターンを用いて、コントローラーからみてシンプルにしたいということ。

Jigで出力するソースコードの可視化していて、議論に役立っていました。Jigは↓

github.com

他にもいろいろやっていました。パッケージの関係図を見ながら、依存関係が正しいかどうか議論をしていました。

コミットは以下の「賃金パッケージを導入」~「EmployeeRecordCoordinator導入」までです。

https://github.com/system-sekkei/isolating-the-domain/commits/master

劇的ビフォーアフターBIGLOBEのDDDの昔と今〜

ビッグローブ株式会社 曽根 大作

DDDとの出会い

  • 独自言語*1の世界、マニュアルはExcel、どこに置かれているか分からない
  • 2013年にJavaが導入された。DDD・Scrumで開発
  • のれんわけ方式での拡大計画
    • ある程度チームが成熟したら、分裂し、新しい人を加入させる

ビフォーアフター①モデルの書き方

改善前

名詞ベースのみのモデリング。 情報が足りない、責務・関連依存・多重度などが欲しいという問題があった。

改善後

3つのモデルを作成するようにした。

  • 概念モデル
    • 依存を書く
    • イメージは世界地図
  • コンテキストマップ
  • ドメインモデル
    • ふるまいを記載する
    • イメージはナビゲーション

ビフォーアフター②状態の表し方

改善前

ひとつのエンティティにすべてのイベントがぶら下がっていた

例えば、契約エンティティに、申し込み、解約、その他もろもろが全部入っている状態だった。

すると、エンティティが肥大化してきて、実装時に本来関係ないイベントまで意識する必要が出てくるようになってしまった。

改善後

状態ごとに必要な要素のみを持ったエンティティを生成するようにした。

例えば、ファクトリやリポジトリに渡して書く状態のエンティティを作成、永続化した。

すると、エンティティの責務がはっきりするようになった。

不要なメソッドやフィールドがなくなり、変更やテストもしやすくなった。

ビフォーアフター③チェック

様々な業務ロジックをどのように表現するかについて

改善前

アプリケーション層にもロジックが記載されていた。

可読性が低くなる、テストが複雑になる、ドメインモデルに表現することができないという課題が生じていた。

改善後

ドメイン層にチェックに必要な業務ロジックを集約することで、上記の問題を解決した。

実録!LOHACOにおけるDDDとCleanなArchitecture

アスクル株式会社 佐藤 大典、中村 俊之

前半(抽象的な話)

LOHACO*2は巨大なモノリシックとなっている状態だったが、そこから変更のしやすいシステムを目指した取り組みを紹介していました。

ユビキタス言語のところについて、実際どうやったらよりうまくいったか*3というところは聞いてみたかったですね。

ビジネス側とのやり取りが必要な分野だと思いますので、うまくいった場合の応用はかなり幅広く利きそうです。

後半(具体的な話)

Maven multi-moduleについては、気をつけようという感じでもなんとかなる気もしますが、仕組みで強制するメリットもあると思います。

あんまり関係ないですが、レガシーDB対応はそれ一つでかなり大きな知見なんじゃないかという感じがありますね。

ビジネスルールの複雑さに立ち向かう実践技法

株式会社ギルドワークス 増田 亨

www.slideshare.net

スライド番号に付随して補足を記載します。

8

  • 右が戦術、左が戦略
  • すべてのプロフェッショナルになれというわけではないが、第1象限の能力を高めようとしたら、他の象限についても補強しないといけない

11

「私は型原理主義者なので」とのこと。

17

汎用型とはint型など 楽で安全、というのは、制約がかかっていることによる。intとかだと何が入っているか分からない。

23

種類を限定すると、境界値テストがほとんど意味をなさなくなる。

34

むちゃくちゃ細かいロジックになってくると、マニュアルを読むだけではなく現場に聞いてみないと分からないことがある。

44

SEの領域といった印象。本自体は難解らしい。

感想

前半のプレゼンでも感じたことですが、非常にメモが取りやすいです。例えば資料内では表や箇条書きになっていることでも、それについて論理的な構成立てで話してくださるので、自分の中に入っていきやすいです。

全体まとめ

レガシー改善というのは最新技術で華麗に解決するというものではなく、地道な取り組みで成果を積み重ねていくものだと思います。

非常に複雑なビジネスロジックに対する戦いは、いつまでもなくならないと思いますが、逆に知見も豊富になりうると思います。これからも頑張っていきたい。

*1:xmlベースの何かという話だった

*2:アスクル保有するECサイトドメインが単純なECサイトより複雑

*3:もしくは必要なかったか

レビュー『チーム開発1年目の教科書』

技術書典には参加していませんが、こちらの書籍を読みましたのでレビューします。

マインドセット

チーム入りたて、チーム開発も初めての自分が、1日でも早く価値を生み出せるようになるにはどうすればいいか?という問いから始まっています。

その中で本書が主張しているのは、コミュニケーションであったり、情報の整理であったりします。

情報整理の効率化については、Markdownを取り上げてかなり掘り下げられています。

コードを書くのも価値創造ですが、情報の整理(あるいはその効率化)も価値を生み出していると思います。

スコープの絞り込み

似たようなタイトルの商業書籍に『チーム開発実践入門』というのがあります。

チーム開発実践入門 ~共同作業を円滑に行うツール・メソッド (WEB+DB PRESS plus)

チーム開発実践入門 ~共同作業を円滑に行うツール・メソッド (WEB+DB PRESS plus)

ざっくりいうとそこで取り上げられているのは、バージョン管理・チケット管理・CI・CDです。

体系的に学ぶことができますが、分量も300ページとそれなりです。

一方、本書ではチケット管理以降をバッサリと切り、100ページ強に抑えることができました。   これはスコープの絞り込みによるもので、「1年目」ならGitの把握の方が優先だということでしょう。

論理の省略

Markdownを取り上げるにあたって一つ気になったのは、論理の省略です。

どういうことかというと、例えば私は今のプロジェクトでドキュメントはワードやエクセルで書いています。

すると、Markdownが活躍する余地はありません。なぜなら対応していないからです。

なので、「ドキュメントは何処に、なんのソフトウェアで書かれるべきか」という説明があると「なぜMarkdownを身につけるべきなのか」という問いについて、納得感が出てくると思いました。  

その他

誤字がいくつかあったので、どこかで指摘しようかなと思っています。

[AWS][EC2][Windows Server 2019]同サブネットグループ内で、pingが通らないときに確認すべき2点

タイトルのとおりです。

複数のWindows Serverインスタンス間で通信を行おうとしたのですがうまくいかず、そもそもpingも通らないことに気づいたものの、対処に少々時間がかかったのでまとめます。

ちなみに、以下で説明する確認ポイントはpingの受け手側が対象です。

セキュリティグループの確認

VPCにはデフォルトのセキュリティグループが用意されていますが、対象のEC2インスタンスがそのグループに所属していることを確認してください。

↓こんな感じのグループです。

f:id:alek3:20190427111843p:plainf:id:alek3:20190427111853p:plain

※追記:これは、このセキュリティグループに所属するインスタンスからのインバウンドトラフィックを許可するものです。

VPC のセキュリティグループ - Amazon Virtual Private Cloud

Server内のセキュリティ確認

これだけだとつながらない場合は、Windows Serverのセキュリティを緩めます。

メニューから、「Windows Security」にアクセスし、ファイアウォールの設定画面を開きます。

f:id:alek3:20190427112120p:plain

このうち、Private NetworkのFirewallをオフにします。

f:id:alek3:20190427112218p:plain

ping確認

通りました。

f:id:alek3:20190427112548p:plain