覚えたら書く

IT関係のデベロッパとして日々覚えたことを書き残したいです。twitter: @yyoshikaw

Kotlin - Intellij IDEAで REPL

Kotlin ではREPLの機能が備わっているので、わざわざmain関数書いたりしなくても、 ちょっとしたコードを試すときにはREPLを利用するのが便利なケースがあります。

REPLは Intellij IDEA からも実行できるようになっています。


「Tools」→「Kotlin」→「Kotlin REPL」と選択することで起動可能です。

f:id:nini_y:20190505214223p:plain


または、

Shift キー2回クリックでの どこでも検索で "Kotlin REPL" と入力して、Enterキーをクリックする事でも起動できます。

f:id:nini_y:20190505214713p:plain


起動するとこんな感じです。

f:id:nini_y:20190505214802p:plain

あとは実行したいコードを入力して Command + Enter で実行可能です。ここでは変数に数値を割り当てて、その変数の値を表示しています。

f:id:nini_y:20190505214910p:plain


":quit" と入力して Command + Enter でREPLを終了することです。

f:id:nini_y:20190505214923p:plain


これでIntellij IDEA上でのKotlinのREPLができるようになりました。簡単なコードの動作確認はこれでできますね。

Kotlin - クラスとプロパティ

「Kotlinイン・アクション」 を読みながらの写経続いております。(Javaと比較しながら)

Kotlinイン・アクション

Kotlinイン・アクション

  • 作者: Dmitry Jemerov,Svetlana Isakova,長澤太郎,藤原聖,山本純平,yy_yank
  • 出版社/メーカー: マイナビ出版
  • 発売日: 2017/10/31
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログ (2件) を見る


値クラス

以下はJavaでのクラス宣言の例です。

public final class Person {
    private final String name;

    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

nameage のfinalなフィールドとそのフィールドに対するgetterのみを持つ単純なクラスとなっています。

このクラスを、 Kotlinへコンバートすると以下のようになります。

class Person(val name: String, val age: Int)

うん、とてもシンプル。

Javaのコードでは、コンストラクタ内で受け取った引数をフィールドに割り当てるコードを繰り返します。
まさにJavaの典型的なボイラープレートコードの一つと言えますが、
Kotlinではこれが無くなっており、すっきりしています。

このようなデータのみが存在して、実装コードが無いクラスは値オブジェクト(value object)と呼ばれる事があります。
多くのプログラミング言語では、これを宣言するための簡潔な構文を用意しています。

残念ながら Java ではこのような構文は提供されておらず、Lombok を利用する事で似たようなことを実現することはできます。


また、Kotlin ではデフォルトの可視性が public であるため、public の記述が無くなっています。


プロパティ

Java では、データを通常はprivateなフィールドに格納し、利用者がそのデータにアクセスする必要があるのであればアクセサメソッド(getterやsetter)を提供します。
このフィールドとアクセサの組み合わせはプロパティ(property)と呼ばれ、多くのライブラリやフレームワークに多用されています。

Kotlin では、Javaとは違い プロパティは第一級の言語機能となっています。これが、Javaにおけるフィールドとアクセサメソッドを置き換えるものとなっています。

Kotlin のクラス内ではプロパティを宣言する方法は、変数を宣言する方法と同じで valvar キーワードを使用します。各々の違いは以下の通りです。

  • val : 宣言されたプロパティは読み取り専用
  • var : 宣言されたプロパティはミュータブルで変更が可能

例えば以下のようなクラス宣言が可能です

class Person(
    val name: String,   // <- 読み取り専用。フィールドとgetter が生成される
    var age: Int        // <- 書き込み可能。フィールドとgetter, setter が生成される
)

プロパティを宣言するときには、それに対応するアクセサ(読み取り専用のプロパティではgetter, 書き込み可能なプロパティではgetter とsetterの両方)も宣言されたことになります。

上記の Person クラスは Java からも Kotlin からも同様に利用する事が可能です。

Java からは以下のように利用可能です。

public static void main(String[] args) {
        Person p = new Person("Taro", 20);

        System.out.println(p.getName());  // -> Taro
        System.out.println(p.getAge());   // -> 20

        p.setAge(25);                     // -> age の値の変更
        System.out.println(p.getAge());   // -> 25
    }

Koitlin からは以下のように利用します

fun main() {
    val p = Person("Taro", 20)

    println(p.name)  // -> Taro
    println(p.age)   // -> 20

    p.age = 25       // -> age の値の変更
    println(p.age)   // -> 25
}

Kotlin ではgetterを呼び出す代わりにプロパティを直接参照します。
ミュータブルなプロパティの値の書き換えもsetter経由ではなく直接プロパティに値を渡します。


カスタムアクセサ

矩形(rectangle)を表現するクラスを定義して、その矩形が正方形かどうかを判別できるようにする場合、以下のように記述できます。

class Rectangle(val height: Int, val width: Int) {
    val isSquare: Boolean
        get() {
            return height == width
        }
}

isSquare プロパティは、値をフィールドに格納する必要はなく、この例ではカスタムのgetterの実装を持つだけとなっています。
必要な値はプロパティから値を取得するたびに毎回計算(判定)されます。

呼び出しの例は以下の通りです

fun main() {
    val r1 = Rectangle(10, 20)
    println(r1.isSuqare)    // -> 長方形なので false

    val r2 = Rectangle(100, 100)
    println(r2.isSuqare)    // -> 正方形なので true
}

このプロパティに Java からアクセスする場合は、isSquare メソッドを呼び出すことになります。


引数のない関数とカスタムgetterを持つプロパティのどちらを使うべきかについて、
どちらの選択肢も似ていて実装内容や実行速度の面では違いがありません。

違いがあるのは 可読性 だけです。
一般に、あるクラスの特徴を表現したい場合には、それをプロパティとして宣言するべきです。


まとめ

Kotlin の場合 Java に比べてかなり簡単な記述でプロパティの取り扱いができることが分かりました。



関連エントリ

AWS 認定ソリューションアーキテクト – アソシエイト

AWS 認定ソリューションアーキテクト – アソシエイト(AWS Certified Solutions Architect - Associate)の資格を取ってみました。(合格しました)

規約的にも細かな試験内容等書いたりはしませんが、受けてみた感想とか書いてみます。
もちろん、今回私が受験したバージョンの試験の話になります。(将来的には改訂になる部分もあると思います)


試験概要

  • 試験コード:SAA-C01
  • 試験時間:130分
  • 出題数:65問
  • 試験形式:多肢選択式
  • 受験料:15,000円(税別)
  • 試験範囲とその割合:
    • 回復性の高いアーキテクチャを設計する(Design Resilient Architectures)34%
    • パフォーマンスに優れたアーキテクチャを定義する(Define Performant Architectures)24%
    • セキュアなアプリケーションおよびアーキテクチャを規定する(Specify Secure Applications and Architectures)26%
    • コスト最適化アーキテクチャを設計する(Design Cost-Optimized Architectures)10%
    • オペレーショナルエクセレンスを備えたアーキテクチャを定義する(Define Operationally Excellent Architectures)6%

上記の本試験とは別に模擬試験というのを事前に受けることも可能です。
模擬試験の受験料は 2,000 円(税別) です。


受けてみての感想

受験してみての個人的な感想です。

  • アソシエイト と名のつく資格というのは一般的にかなり簡単に取れるというイメージがありますが、この資格に関してはそんなこと無いです。
    • というか、まーまー難しい
  • 普段、AWS触ってない人が受験するには敷居が高いかもしれません。まず、AWSのサービス名や用語などを覚えたり身につけたりする必要があるため。
  • 普段からバリバリにAWS触っている人にとっては、そこまでの難易度では無いのかも。
  • それでも、試験対策をしたり模擬試験は受けた方がいいと思います。
    • 模擬試験等を受けてみないと、この試験では一体どういう方向性での問いがあるのかの傾向が分からないためです。
  • ある程度具体的なユースケースに対して、そのユースケースの課題解決のためにAWSのサービスをどう組み合わせて使うのかという設問がいくつもみられます。
    • こういう設問を解くためには、AWSの各サービスの名前知ってたりするだけでは足りません。AWS上で一般的にどう設計するかということを知っておく必要があります。
    • (Javaの資格試験では重箱の隅つつくような設問があったりしたのに比べて、この資格試験は圧倒的に意味があるなーと思いました。)
  • 設問によって、コストの低減をもとめているのか、パフォーマンスをもとめているのか、可用性をもとめているのか、セキュリティ要件の達成をもとめているのか、運用負荷が下がることをもとめているのか といった事が問題文の中にきっちり書かれていることがあります。それを見落とさないようにしましょう。
    • "設問の中に出てくるユーザの要件は何なのか?"、"自分が選択した答えでもやりたいことを達成できるけどオーバースペックや高コストになっていないか?" などを考えるのが重要だと思います。


まとめ

まとめ?になるのか分かりませんが、
この資格を取るための勉強をしていくうちに、AWS上でのサービスの構築をする上での、AWSのベストプラクティスを結果的に学んでいくことになります。
場面場面にあったサービスやサービスのタイプの使い分け、組み合わせなどを身につけていく事ができます。

資格を取ることだけが目的とならずに、その資格が求めている素養を一定程度身に付けることに繋がっているように感じます。
そういう意味では、けっこう取得する価値がある資格なんじゃ無いかと思いました。



関連エントリ

「失敗から学ぶRDBの正しい歩き方」

「失敗から学ぶRDBの正しい歩き方」 を読んでみました。

失敗から学ぶRDBの正しい歩き方 (Software Design plus)

失敗から学ぶRDBの正しい歩き方 (Software Design plus)

内容紹介では以下のように書かれています。

失敗から学んで、MySQLとPostgreSQLの設計・運用を見直す

「データベースがよく落ちる」
「前任者が残したテーブル、SQLが読み解けない」
「RDBMSを入れ替えたら予期せぬバグが」
――MySQLやPostgreSQLといったRDBMS(リレーショナルデータベース管理システム)を使った業務システム、
Webサービスを設計・運用していると、こういった問題によく直面するのではないでしょうか。
本書はRDB(リレーショナルデータベース)の間違った使い方(=アンチパターン)を紹介しながら、
アンチパターンを生まないためのノウハウを解説します。
それぞれの章では、問題解決に必要なRDBやSQLの基礎知識も押さえるので、
最近RDBMSを触り始めた新人の方にもお勧めです。


目次以下のようになっています。

  • 第1章 データベースの迷宮
  • 第2章 失われた事実
  • 第3章 やり過ぎJOIN
  • 第4章 効かないINDEX
  • 第5章 フラグの闇
  • 第6章 ソートの依存
  • 第7章 隠された状態
  • 第8章 JSONの甘い罠
  • 第9章 強すぎる制約
  • 第10章 転んだ後のバックアップ
  • 第11章 見られないエラーログ
  • 第12章 監視されないデータベース
  • 第13章 知らないロック
  • 第14章 ロックの功罪
  • 第15章 簡単すぎる不整合
  • 第16章 キャッシュ中毒
  • 第17章 複雑なクエリ
  • 第18章 ノーチェンジ・コンフィグ
  • 第19章 塩漬けのバージョン
  • 第20章 フレームワーク依存症


読み終わった感想は、

「この本をもっと早くに読みたかった(もっと早くに存在していてほしかったw)」

です。

正直、インターネット上にも同様の情報が存在していたりしていますが、
こうして書籍に整理されてまとまっていると、読みやすいですしとても理解しやすいです。


書籍の冒頭の「はじめに」というページで、以下のように書かれています。(一部抜粋)

「データベースの寿命はアプリケーションよりも長い」が筆者の持論です。
なぜならば、データベースはサービス開発当初から存在することが一般的で、
アプリケーションコードのようにリプレースされることは稀だからです。

・・・

RDBは広く使われている反面、次のような注意事項があります。
●データベースの停止はサービスの停止を伴うことが多いため、メンテナンスしにくい
●データは常に増え続け、リファクタリングしにくい
●サービスの中核を担うため、変更による影響が大きい

このように、RDBのアンチパターンはアプリケーションのアンチパターン以上にダメージが大きいのです。
そして厄介なことに、RDBの問題はある日を境に顕在化するということが多いです。
当初は良かれと思った設計が、あとになって問題を引き起こすこともままあります。
・・・

本当に、これはまさにだと思います。

昨日まで正常に動作してたのに今日になって急に問題が発生するというのは、RDBのあるあるだと思います。

筆者含めて多くのエンジニアが経験してきた(データベースの)問題をパターン集として共有化してくれています。
そして、本当はどうすべきだったのかという道しるべが書かれています。

経験済みの人は、あの時こうすればよかったのかと理解できますし、
まだ問題の状況を経験していない人も将来起こりうる問題を疑似体験させてくれます。

DBにちょっとでも触れるエンジニアは全員読んだ方がいいと思います。

そのぐらい良い本です。


RDBの設計をする上で念頭におきたいこと

RDBの設計をする上では当然のことなのかもしれませんが、
自分の中で念頭に置いておかなければならないと思った内容を書籍内から一部抜粋しました。

  • RDBは、"時間軸と直交するような設計" が大切です。ですがそれを使ったサービスとしては、
    時間軸と直交しないデータ=履歴を保存することが同じくらい重要です。
  • RDBはRelational Database(リレーショナルデータベース)の頭文字を取っています。その元となっている考え方がリレーショナルモデルで、リレーショナルモデルは集合を扱うデータモデルのことです。
    • 集合には次のような性質があります。
      • 重複がない
      • 実在する要素しかない(NULLがない)
      • 要素に順序がない
    • ソフトウェアとしてのRDBMSには重複もNULLもソートもあります。実際に必要なデータは多種多様で、リレーショナルモデルのみで表現することは難しいため、拡張されているのです。
    • RDBMSは、リレーショナルモデルよりも幅広くデータを扱えることで表現力が上がりましたが、やはりリレーショナルモデルがもとになっているため、リレーショナルモデルにない世界を扱うことは苦手です。
      ソートはリレーショナルモデルの外の世界の話ですので、パフォーンスのボトルネックになりやすいのは必然なのです。


まとめ

ちょっとコンテキストが違うかもしれませんが、
「勝ちに不思議の勝ちあり、負けに不思議の負けなし」という言葉があります。(江戸時代の大名、松浦静山の剣術書『剣談』)
勝つ時(成功した時)は偶然勝つこともあるが、負ける時は必ずその負けた理由(失敗した理由)があるという意味です。

成功や勝ちに関しては運や偶然がつきまとい、成功の原因を導き出そうとしてもただの結果論でしかない場合も少なくありません。
それに対して、失敗や負けといったものは必然性が高く、その原因分析することに意味があるケースが多くあります。
一つ一つの失敗を積み上げると法則性や対処方法が見えてくることがあります。

今回取り上げた書籍も "失敗から学ぶ..." というタイトルが付いており、まさに失敗からの法則性を導き出しているとも言えます。

この本を読んで、RDBに対して先んじて失敗してくれた人たちや事例から多くのことを学びましょう。



関連リンク

Kotlin - 文字列テンプレート

「Kotlinイン・アクション」 を読みながら相変わらず写経してます。(Javaと比較しながら)

Kotlinイン・アクション

Kotlinイン・アクション

  • 作者: Dmitry Jemerov,Svetlana Isakova,長澤太郎,藤原聖,山本純平,yy_yank
  • 出版社/メーカー: マイナビ出版
  • 発売日: 2017/10/31
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログ (2件) を見る


簡単な文字列フォーマット

Kotlin では、文字列テンプレート(string template)と呼ばれる機能が導入されています。
Rubyなどにも導入されているものとかなり似ているものだと思います。

変数名の前に $ を置くことで、文字列リテラルの中でローカル変数を参照することが可能となっています。

例えば、引数が負数かどうかチェックして、負数であれば IllegalArgumentException をスローし、その例外の中に引数の値も情報として含めるものとします。
そのようなメソッドを作成する場合、Javaでは以下のようなコードになります。

public class StringTemplate {

    public static void main(String[] args) {
        validation(-1);
    }

    private static void validation(int value) {
        if (value < 0) {
            throw new IllegalArgumentException("parameter is invalid. [parameter: " + value + "]");
        }
    }
}

"parameter is invalid. [parameter: " + value + "]" というような文字列連結を記述する必要が出てきます。


Kotlinであれば、文字列テンプレートを使って同様の関数を以下のように記述できます。
$vale の部分が文字列テンプレートの利用箇所です。

fun main() {
    validation(-123)
}

fun validation(value: Int) {
    if (value < 0) {
        throw IllegalArgumentException("parameter is invalid. [parameter: $value]")
    }
}

Kotlinのコードの実行結果は以下のようになります。正しく例外がスローされ、引数の値も情報として含まれていることがわかります。

Exception in thread "main" java.lang.IllegalArgumentException: parameter is invalid. [parameter: -123]
    at net.yyuki.sandbox.string.StringTemplateKt.validation(StringTemplate.kt:10)
    at net.yyuki.sandbox.string.StringTemplateKt.main(StringTemplate.kt:5)
    at net.yyuki.sandbox.string.StringTemplateKt.main(StringTemplate.kt)


文字列連結で値を埋め込む手段を記述することになってしまいますが、文字列テンプレートを利用することでやりたいことを素直に表現するわかりやすいコードになると思います


式を埋め込む

この記法は単純な変数への参照だけではなく、複雑な式でも利用可能です。式を利用する場合は、その式の周りを波括弧で囲みます。

これにより、配列の1要素を埋め込むというような記述もできます。
たとえば、配列の先頭要素が空文字列でなければNGという(謎の)チェックをする関数を作成します。値が空でなければ例外をスローして、その要素の値を例外に情報として埋め込みます。

コードは以下のようになります。${array[0]} の部分が文字列テンプレートの利用箇所です。

fun main() {
    val arrayVale = arrayOf("sample1", "sample2", "sample3")

    validation(arrayVale)
}

fun validation(array: Array<String>) {
    if (array[0].isNotEmpty()) {
        throw IllegalArgumentException("The first element of the array is not empty. [first element: ${array[0]}]")
    }
}

実行結果は以下の通りです

Exception in thread "main" java.lang.IllegalArgumentException: The first element of the array is not empty. [first element: sample1]
    at net.yyuki.sandbox.string.StringTemplateKt.validation(StringTemplate.kt:13)
    at net.yyuki.sandbox.string.StringTemplateKt.main(StringTemplate.kt:7)
    at net.yyuki.sandbox.string.StringTemplateKt.main(StringTemplate.kt)


例えば、if 式を埋め込むことも可能です。

fun main() {
    val a = 100
    val b = 200

    println("As a result of comparison, the big value is ${if (a > b) a else b}")
}

実行結果は以下の通りです

As a result of comparison, the big value is 200


まとめ

Javaで文字列連結で書いていたような場面で、Kotlinの文字列テンプレートを利用するとコードの見通しがよくなります。