Kotlin公式エクササイズKoansやってみた

仕事でKotlinを勉強する必要が生じたので、色々教材を探してみました。

とりあえず公式を抑えようということで、以下のKotlin Koansを試してみました。

play.kotlinlang.org

特色として、Web上で完結することがあります。

IntelliJ IDEA上でも実施できるらしいですが、自分はスムーズに行かなかったので諦めました。

対象は以下で述べられているように、Javaの経験者を想定しています。

Kotlin Koans is one of the most popular and most effective ways to get into Kotlin for people who already know Java.

いくつか学んだこと

  • Smart Castの基本的な活用法について
    • If文等で、その型であることが明らかな場合には、以降はその型であると暗黙的にみなされている。(以下は例)
fun demo(x: Any) {
    if (x is String) {
        print(x.length) // x is automatically cast to String
    }
}
  • Collection操作に関するあれこれ Javaでfilterとかmapを使う際はとりあえずstream()を挟むイメージだったのですが、Kotlinにはそういうのはないです。確かに無いほうが書きやすいような気がします。

使える関数についてはQiita記事で恐縮ですがこれがいいかと。具体例が載っているので分かりやすいです。

Kotlin のコレクション使い方メモ - Qiita

公式だとこれです。

Collection - Kotlin Programming Language

よくわかんないこと

まとめ

意外と難しいですね。というよりそもそもの概念を理解しないと書き方だけ真似しても意味ないような気がします。

Introductionのセクション以降はどのトピックを次にやってもいいでしょう。

ABC130(しゃくとり法)

直近のABC131には不参加でしたが、その前のABC130に参加したので振り返りです。

atcoder.jp

AとBは省略します。

C問題

「長方形を半分に分割する直線は、すべて対角線の交点を通る」ということを知っていたので、楽に実装できました。

https://atcoder.jp/contests/abc130/submissions/5964250

D問題

単純にループを回していると、O(N2)になって間に合わなさそうだと分かりました。

Kが大きい場合と小さい場合について、どちらも計算量が減るように実装してみました。

具体的には、Kが大きい場合には左端はそこまで大きくできないので、それに備えて限界値を算出しました。

さらに、ある範囲でKを上回れば、それより右端が右に行っても条件を満たすので、その時点でループを打ち切って該当個数を算出するようにしました。

以下が実装です。地味にDはコンテストで初ACです*1

https://atcoder.jp/contests/abc130/submissions/5976819

自分は1.9秒というギリギリでクリアしましたが、他の人は0.5秒くらいでクリアしています。

解説等を見ると、しゃくとり法という方法を使うといいことが分かりました。

qiita.com

自分が考えた不完全なアルゴリズムを蹴散らす華麗な手法でした。

しゃくとり法を用いて書き直したのが以下になります。

https://atcoder.jp/contests/abc130/submissions/6107964

無事、所要時間が0.5秒になりました。

まとめ

Dが解けたのでうれしかったです。

  • パフォーマンス:1213相当
  • レーティング:636→733 (+97)

またがんばります。あと、もう少し早く振り返りを書きます。

*1:コンテスト以外では解説読みながら2,3問しか解いたことがない

レビュー『ネットワークはなぜつながるのか』第2版

ネットでいい評判を昔から聞いていた印象があったので、今回読みました。

ネットワークはなぜつながるのか 第2版 知っておきたいTCP/IP、LAN、光ファイバの基礎知識

ネットワークはなぜつながるのか 第2版 知っておきたいTCP/IP、LAN、光ファイバの基礎知識

対象読者層

IT系のお仕事等に関わり始めて、しばらくした人がいいと思います。

他の人のレビューには、

各章の最初に「ウォーミングアップ」と称したクイズが載っていることである。本屋で立ち読みをしてみて、このクイズの問題を「ところどころ間違う」程度であれば、あなたはこの本をレジに持って行くべきである。もし、半分くらい間違えるようであれば迷うところだろう。問題の意味さえ分からないようなら、少なくとも今は読まないほうが良い。

とありますが、私も同意です。

構成

「ブラウザからWebサーバーにリクエストを送り、Webサーバーがレスポンスを返すまで」をツアーに見立てて全六章で説明しています。

それに伴い、構成は大きく二つないし三つに分かれると思います。

  1. クライアント・サーバーについて(第1,2,6章)
  2. ルーター・スイッチ・回線・プロバイダ等について(第3,4章)
  3. ファイアウォール等について(第5章)

普段はソフトウェアエンジニアをしている私についていうと、1,3番目は知識がありましたが、2番目はほぼ全く分からないというレベルでした。

6章の説明は1,2章の理解を前提としていますが、だいたい忘れているのでいい復習になります。

教科書然っぽいところ、そうでないところ

教科書を読んでいる感覚に近いです。文字がたくさんあります。ただ、詳細な図も十分にあるので理解に困ることはありません。

各フェーズによって、パケットがどのような姿をしているかを中心に学ぶことができます。

最後に数ページで要約した図表もあるのでうまく整理できます。

面白いのは、OSI参照モデルの話が出てこないことにあります。

ネットワークを勉強するとたいてい最初に登場しますが、特に必要ではないんだなということに気づかされました。*1

このように教科書のような側面をもつ本書ですが、異なる点もあります。

例えば、横方向へつなげることを意識している点がそうです。

「横方向へつなげる」というのはどういうことか、高校の科目「世界史」を例に挙げて説明します。

世界史には『ヨコから見る世界史』という有名な参考書があります。

ヨコから見る世界史 パワーアップ版 (大学受験プライムゼミブックス)

ヨコから見る世界史 パワーアップ版 (大学受験プライムゼミブックス)

普通の世界史の教科書では、「中世ヨーロッパの動き」のように、ある地域に絞って説明がなされます。一方この参考書は、特定の時代、例えば17世紀の世界はどのようになっているか?という切り口で説明がされています。

読者はこれによって、新たな世界史の見方を獲得し、世界史という莫大な蓄積のある分野について、理解を深めることができます。

『ネットワークはなぜつながるのか』も同様で、少しひねった、しかし重要なテーマに沿った説明によって、読者のネットワークについての知識を深めることに成功していると思います。

まとめ

本書はネットワークに関しての知見を、「ブラウザからWebサーバーにリクエストを送り、Webサーバーがレスポンスを返すまでの流れ」というテーマにそって体系化したものです。

一気通貫の知識のつながりを確認・補強する用途で使えると思います。

分量がかなり多いですが、読んだ記憶が残っているうちに通読するのが理想でしょう。

もちろん、各フェーズの確認には逐次使えます。私も1,2,5,6章は折をみて読み返したいなと思いました。

ほかの人の感想

昔の本なので、探せばたくさんあると思いきや、意外とありませんでした。

『ネットワークはなぜつながるのか』戸根勤(書評): trivialities & realities

*1:逆に、本書を読んだ後にモデルを見た場合は、しっくりきそう

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秒