Kotlin _4

### ジェネリクス
型を汎用化する
class使用時にデータ型を指定する

class MyData<T> {
    fun getThree(x: T){
        println(x)
        println(x)
        println(x)
    }
}

fun main(args: Array<String>) {
	val mi = MyData<Int>()
    mi.getThree(55)
}

### data class

data class Point(val x: Int, val y: Int)

fun main(args: Array<String>) {
	val p1 = Point(3, 5)
    val p2 = Point(3, 5)
    
    println(p1)
    println(if (p1 == p2) "same" else "not same")
}

### Collection
List: 順番を持つデータの集合(Immutable/Mutable)、Set: 順番を持たない|重複を許さないデータの集合(Immutable/Mutable)、Mapはkeyと値でデータを管理(Immutable/Mutable)
– Immutableなデータを作る
– listはlistOfで使う。変更する場合は、mutableListOfで使用する

fun main(args: Array<String>) {
	val sales: List<Int> = listOf(20, 30, 40)
    println(sales[1])
}

– setはsetOf
– 変更する場合は、mutableSetOfで使用する

fun main(args: Array<String>) {
	val answers: Set<Int> = setOf(5, 3, 8, 5)
    println(answers)
    println(answers.contains(3))
    
    val set1 = setOf(1, 3, 4, 8)
    val set2 = setOf(3, 5, 7, 9)
    println(set1.intersect(set2))
    println(set1.union(set2))
}

– mapはmapOf
– mutableMap

fun main(args: Array<String>) {
	val users: Map<String, Int> = mapOf("yamada" to 10, "tanaka" to 20, "sato" to 30)
    println(users["yamada"])
    println(users.size)
	println(users.keys)
    println(users.values)
    println(users.entries)
}

### map
コレクションを処理するための命令にmap, filter, forEachなどが使える

fun main(args: Array<String>) {
	val prices = listOf(53.2, 48.2, 32.8)
    prices
    	.map{ n -> n * 1.08} // 引数 ->処理
        .filter { n -> n > 50}
        .forEach { println(it)}
}

### 例外処理
try & catch

class MyException(message: String): Throwable(message){
    
}

fun div(a: Int, b: Int){
    try {
        if(b < 0){
            throw MyException("not minus!")
        }
        println(a / b)
    } catch(e: ArithmeticException){
        println(e.message)
    }
}

fun main(args: Array<String>) {
	div(3, 0)
}

### Nullable
nullになりそうな型は、型の後ろに「?」を付ける

fun main(args: Array<String>) {
	val s: String = null
    println(s)
}

Null can not be a value of a non-null type String

fun main(args: Array<String>) {
	val s: String? = null
    println(s)
    
    if(s != null){
        println(s.length)
    } else {
        println(null)
    }
}

Kotlin _3

### class

class User {
    var name = "Me!"
    fun sayHi(){
        println("hi $name")
    }
}

fun main(args: Array<String>){
	val user = User()
    println(user.name)
    user.sayHi()
    
    user.name = "steve"
    println(user.name)
    user.sayHi()  
}

constructor
->classの引数の渡し方はmethodと同様に型を指定する

class User(var name: String) { // constructor
    var team = "red"
    init {
        println("instance created: name: $name, team: $team")
    }
    fun sayHi(){
        println("hi $name")
    }
}

fun main(args: Array<String>){
	val tom = User("tom")
    println(tom.name)
    tom.sayHi()
}

instance created: name: tom, team: red
tom
hi tom

### getter, setter

    // getter
//     get(){
//         return field.toUpperCase()
//     }
    get() = field.toUpperCase()
    // setter
    set(value) {
        if(value != ""){
            field = value
        }
    }

### override
継承される側はopenを付ける

class AdminUser(name: String): User(name){
    fun sayHello(){
        println("hello $name")
    }
    override fun sayHi(){
        println("[admin] hi $name")
    }
    
}

open class User(var name: String){
    open fun sayHi(){
        println("hi $name")
    }
}

fun main(args: Array<String>) {
    val bob = AdminUser("bob")
    println(bob.name)
    bob.sayHello()
    bob.sayHi()
}

### アクセス修飾子
public:どこからでも、protected: そのクラス+サブクラス、private:そのクラスのみ
-> アクセスをcontrollすることで安全なプログラムを書ける

### 拡張

fun User.sayHi(){
    println("[ext] hello $name")
}

val User.myName: String
 get() = "I am $name"

open class User(var name: String){
    fun sayHi(){
        println("hi $name")
    }
}

fun main(args: Array<String>) {
    val bob = User("bob")
    println(bob.name)
    bob.sayHi()
}

### 抽象クラス・具象クラス
抽象クラスはabstractとする

abstract class User{
    abstract fun sayHi()
}

class Japanese: User() {
    override fun sayHi(){
        println("こんにちは!")
    }
}

class American: User() {
    override fun sayHi(){
        println("Hi!")
    }
}


fun main(args: Array<String>) {
	val tom = American()
    val aki = Japanese()
    tom.sayHi()
    aki.sayHi()
}

### Interface
抽象プロパティ、抽象メソッド、メソッド

interface Sharable {
    val version: Double
    fun share()
    fun getInfo(){
        println("Share I/F ($version)")
    }
}

class User: Sharable {
    override val version = 1.1
    override fun share(){
        println("Sharing ...")
    }
}

fun main(args: Array<String>) {
	val user = User()
    user.share()
    user.getInfo()
}

Kotlin _2

### 演算

fun main(args: Array<String>){
	// + - * / %
	val x = 10
    println(x / 3)
    println(x / 3.0)
    println(x % 3.0)
    
    var y = 5
    y++
    println(y)
    y--
    println(y)
    
    var z = 4
    z += 12
    
    // AND &&, or ||, Not !
    val flag = true
    println(!flag)
}

3
3.3333333333333335
1.0
6
5
false

### 文字列

fun main(args: Array<String>){
	// 文字列
	println("hello " + "world")
    
    val name = "yamada"
	println("my name is $name")
    println("my score is ${15 + 33}")
    
    // \n:改行 \t:タブ
    println("hello\n wor\tld")
}

hello world
my name is yamada
my score is 48
hello
wor ld

### ifの条件分岐

val score = 85
    if(score > 80){
        println("great!")
    } else if(score > 60){
        println("ok")
    } else {
        println("soso ..")
    }

> >= < <= == != 三項演算子 [code] val result = if(score> 80) “great” else “soso”
println(result)
[/code]

### when

// when
	val num = 3
    when(num) {
        0 -> println("Zero")
        1 -> println("One")
        2, 3 -> println("Two or Three")
        in 4..10 -> println("Many")
        else -> println("other")
    }

### while

var i = 0
    while (i < 10){
        println("loop: $i")
        i++
    }

do {
        println("loop2: $i")
        i++
    } while(i < 5)
&#91;/code&#93;

### for
&#91;code&#93;
for (i in 0..9){
        if(i == 5) break
        println(i)
    }

for (i in 0..9){
        if(i == 5) continue
        println(i)
    }
&#91;/code&#93;

### 関数
関数の引数は型を指定する
&#91;code&#93;
fun sayHi(name: String = "John", age: Int = 23){
    println("hi! $name($age)")
}

fun main(args: Array<String>){
	// for (変数)
    sayHi("tom", 22)
    sayHi()
}

値を返す時は、関数側で型を指定する

fun sayHi(): String{
    return "hi!"
}

fun main(args: Array<String>){
    val msg = sayHi()
    println(msg)
}

fun sayHi() = "hi!"

-> 配列で返す場合はどうするんだろう??

Kotlin _1

kotlin
ScalaやGroovyなどの言語と同様に、Javaバイトコードにコンパイルされて、JVMで動作する静的型付けのオブジェクト指向
静的なnull安全が保証されている、NullPointerExceptionを防ぐため、@Nullable 型と @NonNull 型が組み込まれている
Javaよりコードが短く簡潔で、Javaのコードを呼び出せる
Uber、Evernote、NetflixなどがKotlinを使用

### 1. Hello World

fun main(args: Array<String>){
    println("Hello world")
}

### 2. 変数

// -val 再代入できない 
// -var 再代入できる
// なるべくvalで宣言し、必要なところのみvarで宣言する

fun main(args: Array<String>){
    val msg: String = "Hello world"
    println(msg)
}

再代入はできない

fun main(args: Array<String>){
    val msg: String = "Hello world"
    println(msg)
    msg = "Hello world 2"
    println(msg)
}

Val cannot be reassigned
再代入の場合はvarを使う

fun main(args: Array<String>){
    var msg: String = "Hello world"
    println(msg)
    msg = "Hello world 2"
    println(msg)
}

### 3. 基本型
Double: 64ビット浮動小数点
Float: 32ビット浮動小数点
Long: 64ビット符号付き整数
Int: 32ビット符号付き整数
Short: 16ビット符号付き整数
Byte: 8ビット符号付き隻数
Char: 1文字を表す文字列
Boolean: 真偽値
String: 文字列

数値定数

val digits = 1234 // 10進数
val longInt = 1234L // Long
val hex = 0x1F // 16進数
val bin = 0b00001011 // 2進数
val dbl = 1234.5 // デフォルトはdouble
val withE = 123.4e10 // 123.4 * 10^10
val flt = 123.4f // Float

文字と文字列

// Char型はシングルクォート
val c = '0'
val n = '\n'
val u = '\uFF00'

// ダブルクォートの文字列も使える
val s = "Hello, world!\n"

val text = """
文字列を記入する。
	インデントもそのまま。
"""

// 文字列の中に変数を埋め込む
val i = 10
val str = "i = $i, i x 2 = ${i * 2}"

// stringはimmutableで構成要素はchar
val c0 = str[0]
for (chr in str){
	println(chr)
}

fun main(args: Array<String>){
    val msg: String = "hello world"
    val c: Char = 'a'
    
    val i: Int = 100
    val l: Long = 55555555555555L
    
    val d: Double = 234.523 
    val f: Float = 12.344F
    
    val flag: Boolean = true 
}

WebViewとは?

Webviewとは?
-> HTMLコンテンツをアプリ内で見れるようにすること
-> SafariやChromeで見られる枠組みをアプリ内に作ることができる
-> HTMLの更新をすれば良いので、アプリストアへの申請や審査、アップデートは必要ない
-> iOS, AndroidともにWebviewに対応している
-> ユーザ体験、操作性はネイティブアプリの方が優れている
-> 全てをWebviewにするのではなく、ヘッダ、フッタの調整などを行うことが多い
-> Webブラウザのレンダリングエンジンを呼び出しているが、ブラウザ自体を起動している訳ではない。そのため、設定やCookieなどは別で管理される

アプリ(Webview)のメリット・デメリット
– push通知を送信できる
– ネイティブを開発するよりも開発・運用コストを抑制できる
– Webとの違いを出しずらい

### Android
– Android System Webview
1.GUIコンポーネントのWebviewを使用する

<WebView
android:id=”@+id/webView″
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:layout_alignParentLeft=”true” />

2. マニュフェストにインターネットアクセスを許可するパーミッション追加
3. インクをクリックしたときに標準ブラウザを起動しないようにする

WebView myWebView = (WebView) findViewById(R.id.webView);
myWebView.setWebViewClient(new WebViewClient());
myWebView.loadUrl(“https://www.google.com/”);

### iOS
– SFSafariView、WKWebView、(UIWebView(非推奨))などを使う
UIApplication classを使う

import UIKit
 
class ViewController: UIViewController , UIWebViewDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let url = URL(string: "https://hoge.com/")!
        
        if #available(iOS 10.0, *) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        } else {
            UIApplication.shared.openURL(url)
        }
        
    }
}

SFSafariViewController

import UIKit
import SafariServices
 
class ViewController: UIViewController {
 
    override func viewDidLoad() {
        super.viewDidLoad()
 
    }
 
    override func viewDidAppear(_ animated: Bool) {
        let webPage = "https://hoge.com/"
        let safariVC = SFSafariViewController(url: NSURL(string: webPage)! as URL)
        present(safariVC, animated: true, completion: nil)
    }
}

EC2のautoscalingの設定

Auto Scalingの仕組みを構築するには二つの作業が必要
1. 起動設定の作成
2. Auto Scalingグループの作成

自動で作成されるEC2がどのAMIを使うか、インスタンスタイプは何にするか、ボリュームサイズはどうするかなどを設定する

### 1.Launch Configurations
– EC2左メニューのLaunch Configurations
– Create launch configuration
– EBS, IAM role, Security Groupは通常のインスタンス作成時と同様
– Advance Detailsで「Assign a public IP address to every instance.」を選択する

### 2. Auto Scalingグループの作成
– 最大の台数と最小の台数を決定する
– Create Auto Scaling Group
– 1で作成したconfigを選択
– group name: autosacling-group
– Start with 1 instance
– Netwrok(VPC)とSubnetを1で構築したインスタント同様のものを選択
– [Keep this group at its initial size]は、障害時に同様のインスタンスを保つ
– [Use scaling policies to adjust the capacity of this group]はサーバ負荷に応じて増減する
— Scale between ${min} and ${max} instances
— Name: AutoScaling-group-size
— Metric type: Average CPU Utilization
— Target value: 70(%)
— Instances need: 300 seconds to warm up after scaling
->作成すると、EC2一覧で、auto scaleインスタンスが新規に作成される

### スケールアウトテスト
1.ターミナルを二つ起動
2.ssh login
$ ssh ec2-user@**.***.***.** -i ~/.ssh/*.pem

topコマンドで%Cpu(s)でCPU使用率を確認
$ top

top - 20:19:08 up 8 min,  2 users,  load average: 0.00, 0.01, 0.00
Tasks:  85 total,   1 running,  48 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   490884 total,   107768 free,    68180 used,   314936 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   409824 avail Mem 

もう一方のターミナルでサーバに負荷をかける
$ yes > /dev/null
-> %Cpu(s)が99近くに上昇

top - 20:21:38 up 11 min,  2 users,  load average: 0.44, 0.11, 0.04
Tasks:  86 total,   2 running,  48 sleeping,   0 stopped,   0 zombie
%Cpu(s): 99.3 us,  0.7 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   490884 total,   108424 free,    67140 used,   315320 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   410864 avail Mem

300秒(5分)程度、待ちます。
すると、自動的にインスタンスが作成されます。VPC, subnet, IAM-roleなどはconfigurationで設定した内容

### スケールインテスト
$ ps -a
CMDがyesをkillする

すると、%Cpu(s)が99%から0に急減します。

top - 20:35:06 up 24 min,  3 users,  load average: 0.85, 0.92, 0.61
Tasks:  88 total,   1 running,  51 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   490884 total,   104732 free,    70548 used,   315604 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   407424 avail Mem 

この状態で再度、300秒(5分)程度、待ちます。
※auto scaling groupのDesired Capacityが2だと、CPU使用率が下がっても、scale inしません。

すると、古い方のinstanceがterminateされました。
Last In First Outか、First In First Outかどちらか気になりましたが、FIFOのようです。
auto scalingは仕組みとして面白いです。

New Relicを使ってみる

メニューが色々あるが、まずはAPMを使ってみる
環境: Amazon Linux2(vagrant)

1.license key: *******
2.Install the PHP agent
RPM-based (Redhat, Centos, etc.) 64-bit

$ sudo rpm -Uvh http://yum.newrelic.com/pub/newrelic/el5/x86_64/newrelic-repo-5-3.noarch.rpm
$ sudo yum install newrelic-php5

3.Add PHP license key
/etc/php.d/newrelic.ini

newrelic.license="***"

newrelicをインストールしたタイミングで、newrelic.iniにlicenseが入っている

New Relic APMのセットアップの方法まではわかりました。