無限大な夢のあと

テニスとアニメが大好きな厨二病SEのブログ

ドワンゴの新卒エンジニア向けの研修資料でScalaに入門 その4(オブジェクト)

関数型のパラダイムを学んで業務に活かそうということで、以下のドワンゴオリジナルの新卒エンジニア向けの研修資料でScalaを本格的に勉強してみることにした。
dwango.github.io
※Java8でごにょごにょしないのは、Scalaを趣味でやりたいという意図があるだけです。

どうせなら、Scalaの言語仕様からガッツリ学んで自分のものにしたい。
また、可能な限りGolangとの比較も入れていきます。

学んだことをとにかく走り書きしていきます。
【オブジェクト】
・オブジェクトに関して

Scalaでは、全ての値がオブジェクトです。また、全てのメソッドは何らかのオブジェクトに所属しています。そのため、Javaのようにクラスに属するstaticフィールドやstaticメソッドといったものを作成することができません。その代わりというと若干語弊があるのですが、objectキーワードによって、同じ名前のシングルトンオブジェクトをグローバルな名前空間に1つ定義することができます。objectキーワードによって定義したオブジェクトもオブジェクトであるため、メソッドやフィールドを定義することができます。

全ての値がオブジェクトであるのは、Rubyなどと一緒なので、よしとするが、staticフィールドやstaticメソッドが作成できないのか。
staticの代わり?にobjectキーワードで作成されたシングルトンオブジェクト内に定義するイメージか。
・object構文の主な用途

object構文の主な用途としては、

・ユーティリティメソッドやグローバルな状態の置き場所(Javaで言うstaticメソッドやフィールド)
・オブジェクトのファクトリメソッド
・Singletonパターン
3つが挙げられます。とはいえ、Singletonパターンを実現するために使われることはほとんどなく、もっぱら最初の 2つの用途で使われます。

objectの基本構文はクラスとほとんど同じで、

object オブジェクト名 extends クラス名 with トレイト名1 with トレイト名2 ... {
  本体
}

のようになります。Scalaでは標準でPredefというobjectが定義・インポートされており、これは最初の使い方に当てはまります。たとえば、println()などとなにげなく使っていたメソッドも実はPredef objectのメソッドなのです。

Object構文の主な用途が3つというのはなんとなくイメージできた。
Predefオブジェクトの話は、コップ本に書いていたから理解済み。

一方、2番めの使い方について考えてみます。点を表すPointクラスのファクトリを objectで作ろうとすると、次のようになります。applyという名前のメソッドはScala処理系によって特別に扱われ、Point(x)のような記述があった場合で、Point objectにapplyという名前のメソッドが定義されていた場合、Point.apply(x)と解釈されます。これを利用してPoint objectの applyメソッドでオブジェクトを生成するようにすることで、Point(3, 5)のような記述でオブジェクトを生成できるようになります。

scala> class Point(val x:Int, val y:Int)
defined class Point

scala> object Point {
     |   def apply(x: Int, y: Int): Point = new Point(x, y)
     | }
defined object Point
warning: previously defined class Point is not a companion to object Point.
Companions must be defined together; you may wish to use :paste mode for this.

これは、new Point()で直接Pointオブジェクトを生成するのに比べて、
・クラス(Point)の実装詳細を内部に隠しておける(インタフェースのみを外部に公開する)
・Pointではなく、そのサブクラスのインスタンスを返すことができる
といったメリットがあります。

サブクラスのインスタンスを返すことができるというのが、イマイチまだピンと来ていないが、他は大まかに理解。

なお、上記の記述はケースクラスを用いてもっと簡単に

scala> case class Point(x: Int, y: Int)
defined class Point

と書けます。ケースクラスは後述するパターンマッチのところでも出てきますが、ここではその使い方については触れません。簡単に言うとケースクラスは、それをつけたクラスのプライマリコンストラクタ全てのフィールドを公開し、equals()・hashCode()・toString()などのオブジェクトの基本的なメソッドを持ったクラスを生成し、また、そのクラスのインスタンスを生成するためのファクトリメソッドを生成するものです。たとえば、 case class Point(x: Int, y: Int)で定義した Point クラスは equals() メソッドを明示的に定義してはいませんが、

Point(1, 2).equals(Point(1, 2))

を評価した値はtrueになります。

ケースクラスにした場合は、Javaでいう自分でクラスを作成した時に作るequals、hashCode、toStringを作ってくれるのか。
これは便利。
フィールドが公開となっているのは、case classでmatch文を使う時にgetter/setterを書いていると冗長になるからかな。

・コンパニオンオブジェクトに関して

クラス名と同じ名前のシングルトンオブジェクトはコンパニオンオブジェクトと呼ばれます。コンパニオンオブジェクトは対応するクラスに対して特権的なアクセス権を持っています。たとえば、 weightをprivateにした場合、

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

object Hoge {
  val taro = new Person("Taro", 20, 70)
  println(taro.weight)
}

はNGですが、

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

object Person {
  val taro = new Person("Taro", 20, 70)
  println(taro.weight)
}

はOKです。なお、コンパニオンオブジェクトでも、private[this](そのオブジェクト内からのみアクセス可能)なクラスのメンバーに対してはアクセスできません。単にprivateとした場合、コンパニオンオブジェクトからアクセスできるようになります。

class Point(val x: Int, val y: Int) {
  def +(p: Point): Point = {
    new Point(x + p.x, y + p.y)
  }
  override def toString(): String = "(" + x + ", " + y + ")"
}

上記のような感じでメソッド定義の中から直接コンストラクタ引数を参照できるそうです。

ドワンゴの新卒エンジニア向けの研修資料でScalaに入門 その3(クラス)

関数型のパラダイムを学んで業務に活かそうということで、以下のドワンゴオリジナルの新卒エンジニア向けの研修資料でScalaを本格的に勉強してみることにした。
dwango.github.io
※Java8でごにょごにょしないのは、Scalaを趣味でやりたいという意図があるだけです。

どうせなら、Scalaの言語仕様からガッツリ学んで自分のものにしたい。
また、可能な限りGolangとの比較も入れていきます。

学んだことをとにかく走り書きしていきます。
【クラス】
・クラス定義
気になった部分を以下に記載

まず、最初の点ですが、Scalaでは1クラスに付き、基本的には1つのコンストラクタしか使いません。文法上は複数のコンストラクタを定義できるようになっていますが、実際に使うことはまずないので覚える必要はないでしょう。一応、Scalaでは複数のコンストラクタが定義できるので、この最初の1つのコンストラクタをプライマリコンストラクタとして特別に扱っています。

確かにコップ本では複数のコンストラクタを定義する例は書いてたけど、実際には使うことはまずないのか。
なぜかは置いておき、一旦そういうものだということにしておこう。

プライマリコンストラクタの引数にval/varをつけるとそのフィールドは公開され、外部からアクセスできるようになります。なお、コンストラクタ引数のスコープはクラス定義全体におよびます。

class Point(val x: Int, val y: Int) {
  def +(p: Point): Point = {
    new Point(x + p.x, y + p.y)
  }
  override def toString(): String = "(" + x + ", " + y + ")"
}

上記のような感じでメソッド定義の中から直接コンストラクタ引数を参照できるそうです。

・メソッド定義

先ほど既にメソッド定義の例として+メソッドの定義が出てきましたが、一般的には、

(private[this]/protected[package名]) def メソッド名(引数名1: 引数1の型, 引数名2: 引数2の型, ...): 返り値の型 = {
  本体のコード
}

という形をとります。ちなみに、メソッド本体が1つの式だけからなる場合は、

(private[this]/protected[package名]) def メソッド名(引数名1: 引数1の型, 引数名2: 引数2の型, ...): 返り値の型 = 本体のコード

と書けます(実際には、こちらの方が基本形で、= {}を使ったスタイルの方が{}内に複数の式を並べて書けることを利用した派生形になりますが、前者のパターンを使うことが多いでしょう)。
返り値の型は省略しても特別な場合以外型推論してくれますが、読みやすさのために、返り値の型は明記する習慣を付けるようにしましょう。
また、privateを付けるとそのクラス内だけから、protectedを付けるとそのクラスの派生クラスからのみアクセスできるフィールドになります。さらに、 private[this] をつけると、同じオブジェクトからのみ、 protected[パッケージ名] をつけると、追加で同じパッケージに所属しているもの全てからアクセスできるようになります。privateもprotectedも付けない場合、そのフィールドはpublicとみなされます。

private[this]という定義方法があるのか。
返り値の明示的に書くということは、いくら型推論してくれるからとはいえ、確かに心がけたいところ。

複数の引数リストを持つメソッドには、Scalaの糖衣構文と組み合わせて流暢なAPIを作ったり、後述するimplicit parameterのために必要になったり、型推論を補助するために使われたりといった用途があります

implicit parameterは名前だけ聞いたことあるが、まだわからん。
デフォルト引数のようなものかな。

何はともあれ、複数の引数リストを持つ加算メソッドを定義してみましょう。

scala> class Adder {
     |   def add(x: Int)(y: Int): Int = x + y
     | }
defined class Adder

scala> val adder = new Adder()
adder: Adder = Adder@7263d8eb

scala> adder.add(2)(3)
res1: Int = 5

scala> adder.add(2) _
res2: Int => Int = <function1>

複数の引数リストを持つメソッドはobj.m(x, y)の形式でなくobj.m(x)(y)の形式で呼びだすことになります。また、一番下の例のように最初の引数だけを適用して新しい関数を作る(部分適用)こともできます。

obj.m(x, y)の形式でなくobj.m(x)(y)の形式で呼びだすのかー。
JavaScriptで学ぶ関数型言語の時に、undersocre.jsでそのような指定の仕方があったような気がする、ちょい違和感ある。
引数を一つだけ渡して、部分適用するのは自分の頭の中では違和感なし。

・フィールド定義
特に言及するポイントなし。

・継承

クラスのもう1つの機能は、継承です。継承には2つの目的があります。 1つは継承によりスーパークラスの実装をサブクラスでも使うことで実装を再利用することです。もう1つは複数のサブクラスが共通のスーパークラスのインタフェースを継承することで処理を共通化することです1。

実装の継承には複数の継承によりメソッドやフィールドの名前が衝突する場合の振舞いなどに問題があることが知られており、Javaでは実装継承が1つだけに限定されています。 Java 8ではインタフェースにデフォルトの実装を持たせられるようになりましたが、変数は持たせられないなどの制約があります。 Scalaではトレイトという仕組みで複数の実装の継承を実現していますが、トレイトについては別の節で説明します。

1. このように継承などにより型に親子関係を作り、複数の型に共通のインタフェースを持たせることをサブタイピング・ポリモーフィズムと呼びます。Scalaでは他にも構造的部分型というサブタイピング・ポリモーフィズムの機能がありますが、実際に使われることが少ないため、このテキストでは説明を省略しています

多重継承問題を取り上げていて、良い資料だなと感じました。

基本的に、継承のはたらきはJavaのクラスと同じですが、既存のメソッドをオーバーライドするときはoverrideキーワードを使わなければならない点が異なります。たとえば、

scala> class APrinter() {
     |   def print(): Unit = {
     |     println("A")
     |   }
     | }
defined class APrinter

scala> class BPrinter() extends APrinter {
     |   override def print(): Unit = {
     |     println("B")
     |   }
     | }
defined class BPrinter

scala> new APrinter().print
A

scala> new BPrinter().print
B

のようにすることができます。ここでoverrideキーワードをはずすと、

scala> class BPrinter() extends APrinter {
     |   def print(): Unit = {
     |     println("B")
     |   }
     | }
<console>:14: error: overriding method print in class APrinter of type ()Unit;
 method print needs `override' modifier
         def print(): Unit = {
             ^

のようにメッセージを出力して、コンパイルエラーになります。Javaではしばしば、気付かずに既存のメソッドをオーバーライドするつもりで新しいメソッドを定義してしまうというミスがありましたが、Scalaではoverrideキーワードを使って言語レベルでこの問題に対処しているのです。

継承時にメソッドをoverrideする時はJavaでやるようなoverrideアノテーションではなく、言語機能としてoverrideキーワードを使用するそうです。
overrideキーワードを使わないとコンパイルエラーになるなんて、良い仕様だな。

ちなみに、Goはクラスではなく、すべてInterfaceや構造体で継承のようなことをやるので、今回は全体的に記述なし。


Programming in Scala: Updated for Scala 2.12

Programming in Scala: Updated for Scala 2.12

Scalaパズル 36の罠から学ぶベストプラクティス

Scalaパズル 36の罠から学ぶベストプラクティス

SCALAプログラミング入門

SCALAプログラミング入門

ドワンゴの新卒エンジニア向けの研修資料でScalaに入門 その2(制御構文)

関数型のパラダイムを学んで業務に活かそうということで、以下のドワンゴオリジナルの新卒エンジニア向けの研修資料でScalaを本格的に勉強してみることにした。
dwango.github.io
※Java8でごにょごにょしないのは、Scalaを趣味でやりたいという意図があるだけです。

どうせなら、Scalaの言語仕様からガッツリ学んで自分のものにしたい。
また、可能な限りGolangとの比較も入れていきます。

学んだことをとにかく走り書きしていきます。

構文(Syntax)
→そのプログラミング言語内でプログラムが構造を持つためのルールです。

「式(Expression)」
→プログラムを構成する部分のうち、評価することで値になるものです。
たとえば1や1 + 2、"hoge"などです。これらは評価することにより、数値や文字列の値になります。

「文(Statement)」
→式とは対照的にプログラムを構成する部分のうち、評価しても値にならないものです。たとえば変数の定義であるval i = 1は評価しても変数iが定義され、iの値が1になりますが、この定義全体としては値を持ちません。よって、これは文です。


・{}式
一般形

{ exp1; exp2; ... expN; }

{}式はexp1からexpNを順番に評価し、expNを評価した値

・制御構造
if式はJavaとは違い、値を返す。

if式は3項演算子のような形で使えるイメージ

object Expression {
  def main(args: Array[String]): Unit = {
    var age: Int = 5
    var isSchoolStandard: Boolean = false
    println(if (isSchoolStandard && 1 <= age && age < 6) "幼児ではありません" else "幼児です")
  }
}

while式
Unit型(Javaでいうvoid相当を返す)ので、Javaのwhile文とあまり変わらないイメージ。

for式
本当の力を理解するには、flatMap, map, withFilter, foreachといったメソッドについて知る必要があるとのこと。
1 to 10は1から10まで(10を含む)の範囲で、1 until 10は1から10まで(10を含まない)の範囲でループを回せる。
また、今自分がわかっているのは、コップ本に書かれていたyieldと組み合わせるとmap処理と同様の処理を実行できること。
多重ループみたいなことをしたい時にはmapメソッドを使うより便利とのこと(まだ聞いただけで書いてない)
→特にyieldキーワードを使ったfor式を特別に for-comprehensionと呼ぶことがあるそうです。

以下、サンプル。

scala> for(e <- List("A", "B", "C", "D", "E")) yield {
     | "Pre" + e
     | }
res4: List[String] = List(PreA, PreB, PreC, PreD, PreE)

練習問題解答

scala> for (x <- 1 to 1000; y <- 1 to 1000; z <- 1 to 1000; if ((x * x) == (y * y + z * z))) println(x, y, z)
(出力結果は省略)

match式
Javaのswitch文のようなイメージ。
JavaJavaScriptのswitch文にあるようなフォールスルーはない。

scala> "abc" match {
     |   case "abc" => println("first")   // ここで処理が終了
     |   case "def" => println("second") // こっちは表示されない
     | }
first

ちなみに、Golangもフォールスルーはありません。
Golangでフォールスルー動作を使用したい場合は、fallthroughステートメントを指定すると使用できる

k := 6
switch k {
case 4: fmt.Println("was <= 4"); fallthrough;
case 5: fmt.Println("was <= 5"); fallthrough;
case 6: fmt.Println("was <= 6"); fallthrough;
case 7: fmt.Println("was <= 7"); fallthrough;
case 8: fmt.Println("was <= 8"); fallthrough;
default: fmt.Println("default case") 
}

Javaでのswitch-case文は、int、enum、String(Java7から)にマッチすることができます。
Scalaのmatch式では、JavaのSwitchより強力で、コレクションの要素の一部にマッチさせる使い方があります。

scala> val lst = List("A", "B", "C", "D", "E")
lst: List[String] = List(A, B, C, D, E)

scala> lst match {
     |   case List("A", b, c, d, e) =>
     |     println("b = " + b)
     |     println("c = " + c)
     |     println("d = " + d)
     |     println("e = " + e)
     |   case _ =>
     |     println("nothing")
     | }
b = B
c = C
d = D
e = E

また、Javaのswitch-case文は、定数式である必要がありますが、Scalaのmatch式もScalaの場合はそうでなくても処理できるようです。

scala>   def count(n: Int, arg: Int) = n match {
     |     case 1 => "one"
     |     case 2 => "two"
     |     case arg => "m"
     |   }
count: (n: Int, arg: Int)String

scala> count(3,3)
res8: String = m

ちなみに、GolangのSwitch文では文字列、数値やインタフェース変数の動的な型まで対応している。
また、Scalaと同様に、定数や整数である必要はありません。
実践Go言語(part5) - golang.jp

パターンマッチではガード式を用いて、パターンにマッチして、かつ、ガード式(Boolean型でなければならない)にもマッチしなければ右辺の式が評価されないような使い方もできます。

scala> val lst = List("A", "B", "C", "D", "E")
lst: List[String] = List(A, B, C, D, E)

scala> lst match {
     |   case List("A", b, c, d, e) if b != "B" =>
     |     println("b = " + b)
     |     println("c = " + c)
     |     println("d = " + d)
     |     println("e = " + e)
     |   case _ =>
     |     println("nothing")
     | }
nothing

また、パターンマッチのパターンはネストが可能です。先ほどのプログラムを少し改変して、先頭がList("A")であるようなListにマッチさせてみましょう。

scala> val lst = List(List("A"), List("B", "C", "D", "E"))
lst: List[List[String]] = List(List(A), List(B, C, D, E))

scala> lst match {
     |   case List(a@List("A"), x) =>
     |   println(a)
     |   println(x)
     |   case _ => println("nothing")
     | }
List(A)
List(B, C, D, E)

パターンの前に@がついているのはasパターンと呼ばれるもので、@の後に続くパターンにマッチする式を@の前の変数(ここではa)に束縛します。asパターンはパターンが複雑なときにパターンの一部だけを切り取りたい時に便利です。
→asパターン覚えよう。

型によるパターンマッチもあり、かなり強力な模様。

scala> import java.util.Locale
import java.util.Locale

scala> val obj: AnyRef = "String Literal"
obj: AnyRef = String Literal

scala> obj match {
     |   case v:java.lang.Integer =>
     |     println("Integer!")
     |   case v:String =>
     |     println(v.toUpperCase(Locale.ENGLISH))
     | }
STRING LITERAL

練習問題2つ目はこんな感じ。

for(i <- 1 to 1000) {
  val s = new scala.util.Random(new java.security.SecureRandom()).alphanumeric.take(5).toList match {
    case List(a,b,c,d,_) => List(a,b,c,d,a).mkString
  }
  println(s)
}

Programming in Scala: Updated for Scala 2.12

Programming in Scala: Updated for Scala 2.12

Scalaパズル 36の罠から学ぶベストプラクティス

Scalaパズル 36の罠から学ぶベストプラクティス

SCALAプログラミング入門

SCALAプログラミング入門

ドワンゴの新卒エンジニア向けの研修資料でScalaに入門 その1(〜Scalaの基本)

関数型のパラダイムを学んで業務に活かそうということで、以下のドワンゴオリジナルの新卒エンジニア向けの研修資料でScalaを本格的に勉強してみることにした。
dwango.github.io
※Java8でごにょごにょしないのでは、多少趣味でやりたいという意図があるだけです。

どうせなら、Scalaの言語仕様からガッツリ学んで自分のものにしたい。
また、可能な限りGolangとの比較も入れていきます。

学んだことをとにかく走り書きしていきます。
・0xffはInt型→0xは16進数表記。16進数でffは255。 Int型は符号あり 32-ビット 整数

scala> 0xff
res1: Int = 255
[http://www16.plala.or.jp/fm677/16hex.htm:title]

・1e308はDouble型→64bit浮動小数点数

scala> 1e308
res2: Double = 1.0E308

・9223372036854775807LはLong型→特に言及することはなし

scala> 9223372036854775807L
res3: Long = 9223372036854775807

・9223372036854775808L→Longの最大値を超える模様。

scala> 9223372036854775808L
<console>:1: error: integer number too large
       9223372036854775808L

・"\u3042"はString型→Unicodeのコードポイントを与えてあげると、自動的に文字列変換される模様。Scalaでも、コードポイントが 16ビットに収まらない文字は以下みたいな感じでサロゲートペア で指定する必要がある。

scala>  "\uD840\uDC0B"
res7: String =𠀋はてなブログでは表示されない文字

・%は符号がある際に、言語によって実装が違う。Scalaでの実装は以下のような感じ。

scala> 4 % -3
res11: Int = 1

scala> 4 % 3
res12: Int = 1

scala> -4 % 3
res13: Int = -1

scala> -4 % -3
res14: Int = -1

4 % -3が違和感あるが、Golangでも同じ動き。
The Go Playground

Double型からInt型へのキャスト

scala> 1.1 + 2.2
res15: Double = 3.3000000000000003(誤差)

scala> res15.asInstanceOf[Int]
res16: Int = 3

scala> res15.toInt
res17: Int = 3

Intの範囲超えの場合、オーバーフローしたのに例外が発生しないだと。。

scala> 2147483647 + 1
res18: Int = -2147483648

ちなみにGolangでは、オーバフローした場合は例外を吐きます。

prog.go:8: constant 2147483648 overflows int

The Go Playground

Longも同様の模様。言語実装の意図としては、どういう意図があるのだろうか。

scala> 9223372036854775807L + 1
res20: Long = -9223372036854775808

もちろん、Golangは例外発生。

prog.go:8: constant 9223372036854775808 overflows int64

The Go Playground

1e308 + 1はあまりに小さい値は無視される模様。

scala> 1e308 + 1
res21: Double = 1.0E308
scala> 1 + 0.0000000000000000001
res22: Double = 1.0

引き算系は直感と変わらず。

scala> 1 - 1
res23: Int = 0

scala> 1 - 0.1
res24: Double = 0.9

scala> 0.1 - 1
res25: Double = -0.9

scala> 0.1 - 0.1
res26: Double = 0.0

scala> 0.0000000000000000001 - 1
res27: Double = -1.0

Golangでも0.1-0.1は0として、表示はされているが、float64型なので、64-ビット浮動小数値でScalaのDouble型と一緒だということがわかる。
The Go Playground


掛け算、割り算系は特に違和感なし。

scala> 0.1 * 0.1
res28: Double = 0.010000000000000002

scala> 20 * 0.1
res29: Double = 2.0

scala> 1 / 3
res30: Int = 0

scala> 1.0 / 3
res31: Double = 0.3333333333333333

scala> 1 / 3.0
res32: Double = 0.3333333333333333

scala> 3.0 / 3.0
res33: Double = 1.0

scala> 1.0 / 10 * 1 / 10
res34: Double = 0.01

scala> 1 / 10 * 1 / 10.0
res35: Double = 0.0

The Go Playground

練習問題
Q. ¥3,950,000を年利率2.3%の単利で8か月間借り入れた場合の利息はいくらか(円未満切り捨て)

scala> 3950000
res36: Int = 3950000

scala> 2.3
res37: Double = 2.3

scala> res36 * res37 * 8 /100/12
res38: Double = 60566.666666666664

scala> res38.toInt
res39: Int = 60566

Q. 定価¥1,980,000の商品を値引きして販売したところ、原価1.6%にあたる¥26,400の損失となった。割引額は定価の何パーセントであったか

scala> 1980000.0
res40: Double = 1980000.0

scala> 26400.0 * 1000 /16
res41: Double = 1650000.0
//割引額を求める式 定価-原価+損失額

scala> (res40-res41+26400)/res40
res42: Double = 0.18


Programming in Scala: Updated for Scala 2.12

Programming in Scala: Updated for Scala 2.12

Scalaパズル 36の罠から学ぶベストプラクティス

Scalaパズル 36の罠から学ぶベストプラクティス

SCALAプログラミング入門

SCALAプログラミング入門

JJUG EclipseCollectionsで学ぶコード品質向上の勘所に参加してきた。 #ccc_gh2 #jjug_ccc

本日、参加したJJUGのセッションで、品質と言う面で色々考えさせられたセッション。

GSの伊藤さんが発表された資料はこちらになります。
http://www.goldmansachs.com/gs-collections/documents/2016-05-21_JJUG_CCC.pdf

今回は、品質向上という観点での話がメイン。
EclipseCollectionsの使い方ではない。

EclipseCollections
Eclipse Collections - Features you want with the collections you need. (日本語ページ)

特に刺さった部分を、走り書きですが、幾つかまとめます。

コードの品質とは?

ソフトウェアの品質とコードの品質はイコールではない。→ 実装時点で直接ソフトウェアの価値に影響を与えるコード品質
・インタフェースの品質(UI、API
・実装の要求適合性・バグの存在
・実装のパフォーマンス(メモリ使用量、実行速度)

実装時点では必ずしもソフトフェアの価値に影響を与えないが、時間軸に沿ったソフトウェアの価値の増加率(生産性)に影響を与えるコード品質

・保守性(可読性、一貫性、簡潔性、等々)
・拡張性、再利用性
・テストカバレッジ

技術的負債

・コードの品質と引き換えにソフトウェアをリリースするスピードを重視した実装
・時間を経るにつれ、利子を払うかのごとく開発生産性を圧迫する
・技術的負債は必ずしも悪いわけではない(会計のB/Sで例を示した)

コードの品質のバランス

・ソフトウェアの特性によってどこの品質に重きを置くかは変わってくる
・コードの品質を議論する際には文化的な側面も多く、開発チームで「良いコード」「悪いコード」の認識を共有することも非常に重要
  ・組織のエンジニアリング文化
  ・プロジェクトチームのエンジニアリング文化
  ・個人がエンジニアとして育ってきた環境)

技術的負債とのつきあい方

技術的負債を完全になくすのは、ある程度の規模のソフトウェア開発に
おいてはほぼ不可能といえる
良いソフトウェアは技術的負債を「コントロール」する
・費用対効果を見積もる
・優先順位をつけ、技術的負債を戦略的に採用する
・返済計画を立てる

• 例:UnifiedSetとUnifiedSetWithHashingStrategyの重複
– UnifiedSetWithHashingStrategyは初期実装時点でUnifiedSetとのコード重複
が多く存在
– 戦略的に反DRYを許容
・ そもそもの実装の複雑性から、重複の排除には時間がかかる
・ 重複は2クラスのみにしか存在せず、保守性への影響は限定的
・テストカバレッジを保障することで将来のリファクタリングは安全に実施できる
・すぐに重複を排除するよりも他の機能にリソースを投資したほうがライブラリにとっての価値が高い
– Issue Trackerに登録し、フォローアップ
– バージョン7.0のリリースでは重複を排除

文化の違いなどは、受け入れた上でコードレビューに臨むべきだということ。
実践編の技術的負債の付き合い方などの話は、今まで言語化できなかった部分が言語化されていて良い資料だと思いました。
すごく良いセッションだったので、是非資料を見てみてください。

スッキリわかるJava入門 第2版 (スッキリシリーズ)

スッキリわかるJava入門 第2版 (スッキリシリーズ)

[改訂新版]Javaポケットリファレンス

[改訂新版]Javaポケットリファレンス

EFFECTIVE JAVA 第2版 (The Java Series)

EFFECTIVE JAVA 第2版 (The Java Series)

改訂2版 パーフェクトJava

改訂2版 パーフェクトJava

The Go Programming Language 輪読会 #03 に参加してきました。

こちらのイベントに参加させて頂きました。
#03eure.connpass.com

輪読対象は下記の書籍です。

The Go Programming Language (Addison-Wesley Professional Computing Series)

The Go Programming Language (Addison-Wesley Professional Computing Series)


今回の輪読した章は「3. Basic Data Type(基本型)」

今回学べたことを走り書き。

整数型
・%演算子は左辺/右辺どちらとも整数でなければいけない
・-5/3 、-5/-3 の結果は、ともに-2である。(言語によっては動きが違うそう)
・^&演算子とは? →左辺かつ右辺の数を含まないものをあらわす。
・>> << はビットシフトだが、右は符号なしでなければいけない。
・符号なし整数で十分に見えるケースでも、符号付き整数を使うべき。

浮動小数点型
・Nanとの比較は常にfalseを返す。

複素数
・組み込み型で、複素数型が実装されているのはGolangPythonのみ。他の言語では標準ライブラリなどで使えるようになっているものはある。
→この実装の意図は、Cを意識しているのかな?という話になった。
複素数型 - Wikipedia


bool
・&&は、||より優先順いが高いので、以下のようなコードでは丸括弧は不要である。
 if 'a' <= c && c <= "z" || 'A' <= C && C <= 'Z'

その他
・go tool vet -- shadowは使える。
・以下のブログは勉強になる。
To Go Beartrap Lying in the Shadows - Qureet.com Qureet.com


すごくアットホームな勉強会だったので、今後も参加してきたいです。
ちなみに、私は5章 Functionの輪読担当となりました。
初めての洋書の翻訳頑張ってみよう。

Go言語によるWebアプリケーション開発

Go言語によるWebアプリケーション開発

スターティングGo言語

スターティングGo言語

改訂2版 基礎からわかる Go言語

改訂2版 基礎からわかる Go言語

Angular2+ng2-bootstrapを使用し、カレンダーUIのサンプルを動かしてみる

Webサービス開発に向けて、まずは使用するライブラリのサンプルを動かしたりするところから始めています。

Bootstrapを使いたかったので、Angular2でうまく使えるものがないか探した結果、以下のng2-bootstrapが見つかりました。
github.com

早速上記を適用してみようということで、前回の記事のハンズオンで作成したところに、機能追加してみようと思います。
dke-msy-node.hatenablog.com

具体的には、ng2-bootstrapのカレンダーUI(DatepickerのExample)を機能追加して動かすまでの備忘録として、本記事を書きます。

ここから修正内容の本題です。
(1)以下のチュートリアルに従い、npmからng2-bootstrapをインストールします。
Angular2 Bootstrap

npm install --save ng2-bootstrap


(2)componentsフォルダに、calendarフォルダを作成します。

(3)calendarフォルダ配下にcalendar.htmlを作成します。
こちらは、DatepickerのExapmleそのままなので、特に注意点はなしです。

gist85ca66808fc57e21e5470f468dd7a8d6

(4)calendarフォルダ配下にcalendar.tsを作成します。
こちらは、サンプルをそのまま使用するだけだと動かないので、注意ポイントがいくつかあります。
先に完成形のコードを載せます。

gist501d330392c7cc90de94d168744efc71

(4-1) DATEPICKER_DIRECTIVESの読み込みパスを変更。
サンプルの構造と違うので、以下のように変更する必要があります。

(変更前)

import {DATEPICKER_DIRECTIVES} from '../../../ng2-bootstrap';

(変更後)

import {DATEPICKER_DIRECTIVES} from 'ng2-bootstrap';

(4-2)外部htmlの指定方法を変更。

WebPackを使用していない場合は、外部HTMLの読み込みはrequireを使用するとエラーが発生するので、読み込み方法を変更。
Template→TemplateUrlとし、直接指定とします。
また、指定するHTMLは先ほど作成したcalendar.htmlとします。

(変更前)

// webpack html imports
let template = require('./datepicker-demo.html');

@Component({
  selector: 'datepicker-demo',
  template: template,

(変更後)

@Component({
    selector: 'calendar-demo',
    templateUrl: 'components/calendar/calendar.html',

(4-3)selectorの名前を変更
(変更前)

@Component({
  selector: 'datepicker-demo',

(変更後)

@Component({
    selector: 'calendar-demo',

(4-4)Componentの名前を変更
(変更前)

export class DatepickerDemoComponent {

(変更後)

export class CalendarComponent {


(5)main.tsで、CalendarComponentを読み込む。

gistd7521928e685b81e2014cbf0ef456ccc

(6)index.htmlを変更。
ここが、一番多くの罠がいたので、注意点を記載していきます。
まずは、先に完成形を載せます。

gist8b09910fae59a15052da920667ed1861

(6-1)body以下にあるタグ名を自作のタグ名に変更
(変更前)

<my-app>Loading...</my-app>

(変更後)

<calendar-demo>Loading...</calendar-demo>

(6-2)ng2-bootsrapを読み込む。
bootstrap4はレイアウトが崩れるので、bootstrap3としました。

(追加した記述)

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<script src="node_modules/ng2-bootstrap/bundles/ng2-bootstrap.min.js"></script>

(6-3)SystemJSでのライブラリの読み込みを追加
momentはJavaScriptで扱う日付ライブラリです。

(追加した記述)

            "node_modules/ng2-bootstrap": {
                "defaultExtension": "js"
            },
            "node_modules/moment": {
                defaultExtension: 'js'
            }

(6-4)SystemJSでのライブラリの読み込みパスの別名をつけます。これにより、TypeScriptファイルからのimportの記述が短くなります。

(追加した記述)

       paths: {
            "ng2-bootstrap": "node_modules/ng2-bootstrap/ng2-bootstrap",
            "moment": "node_modules/moment/moment"
        }

これで、カレンダーUIのサンプルが動くはずです。
Angular2の基本的なセットアップは、下記の書籍をご参考に構築してみてください。

シェルスクリプトマガジン vol.37

シェルスクリプトマガジン vol.37

  • 作者: 當仲寛哲,岡田健,佐川夫美雄,大岩元,松浦智之,後藤大地,白羽玲子,水間丈博,濱口誠一,すずきひろのぶ,花川直己,しょっさん,法林浩之,熊野憲辰,桑原滝弥,USP研究所,ジーズバンク
  • 出版社/メーカー: USP研究所
  • 発売日: 2016/04/25
  • メディア: 雑誌
  • この商品を含むブログを見る

あるいは、途中までであれば、私の前回の記事も参考にしてみてください。
dke-msy-node.hatenablog.com