OmniAICreator/Qiita-1.07M huggingface dataset:
【最新まとめ】未経験からエンジニアになった人エントリまとめ


#前提
本エントリは技術に関するエントリではありません。
対象としては、
　・未経験就職できるのか不安な非エンジニア
　・エンジニア募集中の企業のひと
　・プログラミングスクールや人材派遣事業、2018年のエンジニア就職事情を知りたいひと
あたりかと思っています。

あ、ちなみに`執筆者やブロガーさんから被リンク料もらってまとめてない`です。

#まとめて思ったこと

**・いろんな未経験転職がある、ということ**
**・本を読む、Progateをやる、だけでは不十分**
**・就業前に完璧な知識を身につけることはほぼ不可能なのでまずは就業**
**・スクールを経由してエンジニアにならないルートの方が自立しそう**
**・就業前にやるべきことは「何か１つでもアウトプットとなるサービスを作ること」**

#まとめ

### 1. 未経験からエンジニアとして働くようになるまでにやったこと、思ったこと

**【要約】**
・プログラミングは書かないと覚えられない
・休みの日だけ勉強しても効果は得られない
・技術書を読んでGithubでもQiitaでもいいからアウトプットをしよう
・英語のドキュメントに臆さないことが大事

記事はコチラ：
https://qiita.com/suy0n9/items/d1bfbd823d8b6dc562be


### 2. 未経験エンジニアがWantedlyとTwitterで転職活動を行う[登録編]

**【要約】**
・サービスをローンチした経験あり
・Wantedlyのスコアをあげる
・Twitterでポートフォリオをあげて仕事募集する
・数名の方と会うことができた

記事はコチラ：
https://note.mu/natsukingdom/n/n639114c72f93

### 3. 未経験からWebエンジニアになった方法

**【要約】**
・物販の手作業を自動化するためにVBA、プログラミングを始める
・就業してPHPやJSなどを学び始める
・仕事にすることで独学のスピードが上がる
・目標があるなら計画を立てるべき

記事はコチラ：
https://kengotakimoto.com/post-2687/

### 4. 未経験からのエンジニア参入の過酷さ・・・。

**【要約】**
・Ruby on Rails、Swift、Pythonあたりを学ぶ
・独学は厳しい
・実際の案件を通して学ぶことが多いので、スクールはほぼ無意味
・スクールのうたい文句「早い、安い、うまい」は有りえない

記事はコチラ：
http://www.webish-developer.com/entry/2018/03/31/151540

### 5. 【体験談】未経験者がエンジニアになるために転職活動してわかったこと

**【要約】**
・プログラミングスクール経由で未経験エンジニア転職
・SIerやSESなども面接で受けられる
・就活前にプログラミングの学習で学んだことや経験が沢山あると良い
・スクール経由であれば活用すべき

記事はコチラ：
https://www.mayuowl.com/switch_jobs/

### 6. 未経験のエンジニアは働き始めてからが大変です

**【要約】**
・就業前学習だけでは不十分で、仕事をするなかで覚えることがいっぱい
・常に新しいスキルや知識を学んでいかないといけないプレッシャー
・エンジニア独特の文化が存在するため、他業種からだとはじめとまどう
・アウトプットが見える化されているので常に評価される気持ちがつきまとう

記事はコチラ：
http://hana1009.com/2018/05/14/being-engineer-tough/

### 7. 未経験からＩＴエンジニアに転職して1ヵ月！現在の状況と変化をまとめてみた

**【要約】**
・回線の運用保守などのエンジニアに派遣社員として転職
・身体的負担が少なく、人間関係も良好な組織になった
・一方で受け身な仕事であるため、減点評価であることが不満

記事はコチラ：
https://honnyomu.com/tensyoku-1month

### 8. 【目指せノマド】未経験からリモートワークエンジニアになるために抑えるべきこと＋会社の選び方

**【要約】**
・ノマドフリーランスエンジニアになる方法とその経験
・Web系の会社、言語(PHP推奨)を選ぶべし

記事はコチラ：
https://showtaki.com/nomad-remote/

### 9. 【35歳プログラミング未経験者】が暗号通貨エンジニアに転職するためにしたこと

**【要約】**
・35歳になるまでプログラミング未経験から、Bitcoinにハマる
・勉強はもちろん、業界の方や会社にコンタクトをとって情報を取りに行く
・メンターを見つけて、勉強をすると同時にアウトプットをGithubにあげて人に見てもらった
・35歳でもなんとかなる

記事はコチラ：
https://qiita.com/adrenaline0206/items/24157ed2a4587cec3c40

### 10. 未経験の文系サラリーマンが30歳手前からエンジニアになるまでにやって良かった5つのこと

**【要約】**
・雑誌の編集ライターさんからエンジニアへ転職
・初めは、実際に動くものを作って公開してみることで成長する
・知識を体系化して、勉強会を主催することで横のつながりを得ることができる
・スマホのネイティブアプリを作ることがオススメ

記事はコチラ：
https://qiita.com/shunsugai@github/items/6e5ff25c4433e00fee76

#最後に

「未経験　エンジニア」でググると、スクールの記事が非常に多い。未経験転職希望者が読むべきはスクールの記事ではなく、こうした未経験転職者のブログや記事だったりする。

そして、エンジニアになってブログ解説してプログラミングスクールの記事書く人多い問題。
matplotlibで土日に線を入れる

x軸が日付のとき、グラフの推移に曜日が関係していることがあります。
土曜日と日曜日がどの辺りなのか分かりやすいように色をつける方法を考えました。

ライブラリのインポートと、サンプルデータの用意をします。

```python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime
%matplotlib inline

df = pd.DataFrame()
for day in (datetime.date(2018, 9, 1) + datetime.timedelta(x) for x in range(30)):
    df = df.append(pd.DataFrame([[day, np.random.rand()]],
                                columns = ['date','value']), ignore_index=True, sort=True)
df.head()
```

| date | value |
|--:|:--|
| 0 | 2018-09-01 | 0.750244 |
| 1 | 2018-09-02 | 0.724386 |
| 2 | 2018-09-03 | 0.292364 |
| 3 | 2018-09-04 | 0.608857 |
| 4 | 2018-09-05 | 0.863070 |

そのままプロットするとこんな感じです。

```python
df.plot('date', 'value', figsize=(10,5))
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/2543/5d941913-15d8-ebda-7724-ba60a3f09720.png)

x軸が土曜日か日曜日の時だけ線を入れるように関数を作ります。

```python
def weekend_marker(start, end):
    num = (end - start).days + 1
    for day in (start + datetime.timedelta(x) for x in range(num)):
        if day.weekday() == 5:
            plt.axvline(x=day, linewidth=4, color='lightblue')
        elif day.weekday() == 6:
            plt.axvline(x=day, linewidth=4, color='pink')
```

開始日と終了日を渡せば線が表示されるようになりました。

```python
df.plot('date', 'value', figsize=(10,5))
weekend_marker(datetime.date(2018, 9, 1), datetime.date(2018,9,30))
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/2543/a332d729-2c72-fed3-45e7-169083c33117.png)
Javascript：日付を超える度に処理を行う

#はじめに
毎日データを更新するような処理をNode.jsでさせたかったのですが，あまり実装例が見つからなかったので作ってみました．

#ソース
```javascript
//協定世界時を取得（サーバーがどこにあっても良いように）
var utc = new Date();
var offset = utc.getTimezoneOffset() * 60 * 1000;
utc = new Date(utc.getTime() + offset);
//日本時間の今日のDateを取得
var jp_current = new Date(utc.getTime() + 9 * 60 * 60 * 1000);
//日本時間の翌日の０時のDateを取得
var jp_tomorrow = new Date(utc.getTime() + 9 * 60 * 60 * 1000);
jp_tomorrow.setDate(jp_current.getDate() + 1);
jp_tomorrow.setHours(0);
jp_tomorrow.setMinutes(0);
jp_tomorrow.setSeconds(0);
//一回目のタイマー更新処理発火までの時間をミリ秒で取得
var interval = jp_tomorrow.getTime() - jp_current.getTime();

//一回目のタイマー発火
setTimeout(function() {
    update();
    //定期的な処理
    setInterval(update(), 24 * 60 * 60 * 1000); //24時間ごとに発火
}, interval);

function update() {
    //更新の処理
}
```

理論上はこれで動くはず．
サーバーが落ちても復活した時にまたタイマーを設定し直すので日付を超えるタイミングで処理されるはず．

#コメントを受けての追記
node-scheduleというライブラリを使ったパターン

```javascript:
var sch = require("node-schedule");

var job = sch.scheduleJob({hour : 0, minute: 0}, function() {
    //更新の処理
});
```

これだけでいいみたいです．
MacでIchigoJamのSDカードを作る

IchigoJamをRaspberry Pi上で動かすためのSDカードを作る手順です。この手順で、今の所3種類のSDカード(Transend,Toshiba,Team)に書き込みが出来ていますが、同一メーカーでもものによって起動しないものが出たりして、何らかの相性問題がどうも残ってはいるようです。（追記：Teamは成功例もありますが、どうしてもうまくいかないケースもありました）

まず、MacでSDカードをフォーマットする際の注意点が、EFIパーティションです。GUIのディスクユーティリティのデフォルト設定では、見ることが出来ないため、指示通りにファイルをコピーしたのに動かない、という場合はこちらをチェックします。 `diskutil list` でSDカードの構成をチェックし、EFIが出来てたらフォーマット失敗です。

```
/dev/disk2 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *7.9 GB     disk2
   1:                        EFI EFI                     209.7 MB   disk2s1
   2:       Microsoft Basic Data ICHIGOJAM               7.7 GB     disk2s2
```

以下のコマンドでEFIパーティションの無いカードを作成します。**ディスク番号`/dev/disk2`は、環境によって異なります。絶対にこのままコピー＆ペーストせず、ご自身の環境に合わせて修正してください！！**

```
$ sudo diskutil partitionDisk /dev/disk2 MBR FAT32 ICHIGOJAM 0
Started partitioning on disk2
Unmounting disk
Creating the partition map
Waiting for partitions to activate
Formatting disk2s1 as MS-DOS (FAT32) with name ICHIGOJAM
512 bytes per physical sector
/dev/rdisk2s1: 15444488 sectors in 1930561 FAT32 clusters (4096 bytes/cluster)
bps=512 spc=8 res=32 nft=2 mid=0xf8 spt=32 hds=255 hid=8192 drv=0x80 bsec=15474688 bspf=15083 rdcl=2 infs=1 bkbs=6
Mounting disk
Finished partitioning on disk2
/dev/disk2 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *7.9 GB     disk2
   1:                 DOS_FAT_32 ICHIGOJAM               7.9 GB     disk2s1
```

上記のようにFAT32のパーティションだけが存在していれば、OKです。

IchigoJamのイメージ(ファイル)は下記のサイトから入手可能です。

https://ichigojam.github.io/RPi/

zipを展開した中身をSDカードにコピーします。

```
$ rsync -avz ichigojam-rpi-1.2.6/ /Volumes/ICHIGOJAM/
```

ディスクをアンマウントして取り出したら完成です。

```
$ diskutil umountDisk /dev/disk2
Unmount of all volumes on disk2 was successful
```
Segues initiated directly from view controllers must have an identifier

XCode 9.4.1 (9F2000)

iOSのStoryboradで以下の警告が発生した。

```
~/ProjectName/ProjectName/Base.lproj/Main.storyboard:
Segues initiated directly from view controllers must have an identifier
```

Segies は View Controller からそのまま別の View Controller につけるときに ID が必須とのこと。

Segue を選択して Attirbute inspector から Identifier を設定すると警告が消える。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/13754/1e43032a-27d5-7ef9-f91d-8d94049c0635.png)

「Segueを利用するならID必須だから名前をつけろよ」ということかと
Angular Materialでファイル選択ボタン

小ネタです。
Angular Materialを使ったプロジェクトで、ファイル選択input `<input type="file" />` を使うときにボタンをmat-buttonにする方法を紹介します。

![スクリーンショット_2018-09-17_18_15_24.png](https://qiita-image-store.s3.amazonaws.com/0/79414/3b9a5fce-1aae-e5c7-f344-79d725f24667.png)


## HTML

```html
<input type="file" style="display: none" #fileInput accept="image/*" (change)="onChangeFileInput()" />
<button mat-raised-button color="primary" class="file-select-button" (click)="onClickFileInputButton()">
 <mat-icon>attach_file</mat-icon>
  ファイルを選択
</button>

<p class="file-name" *ngIf="!file; else fileName">ファイルが選択されていません</p>
<ng-template #fileName>
  <p class="file-name">{{ file?.name }}</p>
</ng-template>
```

- 1行目: 通常のinputコントロールに対して `#fileInput` という形でテンプレートリファレンスを追加。 また、このコントロールはmat-buttonに置き換える予定なので、 `display: none` で非表示にする
- 2-4行目: inputの代わりになるmat-button、 クリックした際に発火するイベントハンドラを設定
- 7行目以降: 選択したファイル名の表示

## TypeScript

```typescript
import { Component, ViewChild } from '@angular/core';  // ViewChildをimport
// ... 中略 ...
export class FileInputComponent  {
  @ViewChild('fileInput')
  fileInput;

  file: File | null = null;

  onClickFileInputButton(): void {
    this.fileInput.nativeElement.click();
  }

  onChangeFileInput(): void {
    const files: { [key: string]: File } = this.fileInput.nativeElement.files;
    this.file = files[0];
  }
}
```

- 1行目: テンプレートリファレンスを使って、コンポーネントのクラス側からinputにアクセスするために `ViewChild` をimportしておく
- 4行目: テンプレートリファレンスを使ってinput要素を取得しておく
- 9行目: mat-buttonが押さたイベントをinput要素に伝える処理
- 13行目以降: inputのchangeイベントの発火を受けて、file変数にファイル内容を格納する処理

## サンプル

stackblitzにサンプルを用意しました。
https://stackblitz.com/edit/angular-material-file-select
scalaでFactoryMethodPattern

最近、デザインパターンを学習しています。
学習に使っているブログはこちらです。
http://d.hatena.ne.jp/shimooka/20141211/1418298136

普段はphpを使用していますが、scalaにも手を出し始めたことですしせっかくなのでscalaでデザインパターンのひとつ。"FactoryMethodパターン"を実装していきたいと思います。

まずFactoryMethodパターンとはどういったものでしょうか？
上記のサイトやGOF本にはこう記されています。

>オブジェクトを生成するときのインタフェースだけを規定して、実際にどのクラスをインスタンス化するかはサブクラスが決めるようにする。Factory Methodパターンは、インスタンス化をサブクラスに任せる。

もう少し簡略化すると
>「オブジェクト生成側」と「オブジェクトの利用側」を分離するパターン

ということらしいです。

このデザインパターンを実装することで何がメリットなのか?分離してどうなるのか?

一番わかりやすい例としては
・ FactoryMethodパターンを利用している側にいちいちnewを書かなくていい
が挙げられます。

オブジェクトを利用する側は、オブジェクト生成側が返してくれるインスタンスを利用するだけでいい。
後々のメンテナンスでも便利です。分離しているおかげでオブジェクトの生成側に問題がある場合でも利用する側はコードの変更がなくて済みます。

それではscalaで実装していきます。

```Factory.scala
trait Factory {
  def create(): Character

}

object CharacterFactory extends Factory {
  override def create(): Character = {
    val character = new Character
    return character
  }
}

object MonsterFactory extends Factory {
  override def create(): Character = {
    val monster = new Monster
    return monster
  }
}

```
```Main.scala

object Main {

  def main(args: Array[String]): Unit = {
    val name = io.StdIn.readLine()
    val character = CharacterFactory.create()
    val monster = MonsterFactory.create()
  }

}
```

分離できているので利用側ではインスタンスを生成する際にnewをしていませんね。メンテナンスしやすそうです。

###参考
http://d.hatena.ne.jp/shimooka/20141211/1418298136
https://qiita.com/shoheiyokoyama/items/d752834a6a2e208b90ca
at coder beginner 016　グラフ問題

B
高橋くんはプログラミングコンテストで A+B を出力するプログラムを書いたつもりでしたが、 A-B を出力するプログラムを書いたような気がしてきて不安になりました。高橋くんは書いたプログラムをうっかり消してしまって入出力しか残っていません。高橋くんが書いたプログラムが A+B なのか、 A-B なのか、どちらの可能性もあるか、どちらでもないかを判定してください。
ただし、 A+B と A-B のどちらかの可能性しかない場合、そのプログラムを書いたと判定します。例えば 1 1 という入力に対して 2 を出力しているなら、 A+B の可能性はあるが A-B の可能性はないので、高橋くんは A+B を書いたと判定してください。

```
#include <iostream>
using namespace std;
int main(){
	int A, B, C;
	cin >> A >> B >> C;
	if (A + B == C && A - B == C) {
		cout << "?" << endl;
	}
	else if (A + B == C) {
		cout << "+" << endl;
	}
	else if (A - B == C) {
		cout << "-" << endl;
	}
	else {
		cout << "!" << endl;
	}
	return 0;
}
```

C

```
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<list>
#include<cmath>
#include<map>
using namespace std;
using ll = long long;
const int INF = 1e9;
#define rep(i,n)for(int i=0;i<n;++i)
#define p pair<int,int>
vector<int>G[11];
int main() {
	int N, M;
	cin >> N >> M;
	for (int i = 0; i < M; ++i) {
		int a, b;
		cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	for (int i = 1; i <= N; ++i) {
		int used[11] = {};
		for (int j = 0; j < G[i].size(); ++j) {
			used[G[i][j]] = 1;
		}
		used[i] = 1;
		int ans = 0;
		for (int j = 0; j < G[i].size(); ++j) {
			int t = G[i][j];
			for (int k = 0; k < G[t].size(); ++k) {
				if (used[G[t][k]])continue;
				used[G[t][k]] = 1;
				ans++;
			}
		}
		cout << ans << endl;
	}
	return 0;
}
```
Item 83: Use lazy initialization judiciously

# 83.遅延初期化は注意して使うべし

* 遅延初期化とは、値が必要となった時に初めて初期化させる動作のことをいう。遅延初期化は主に処理性能を上げるために行われるが、害をもたらすこともある。
* 遅延初期化はクラスの初期化やインスタンス生成のコストを省いてくれるが、遅延初期化を行うフィールドへのアクセスコストは増加する。
* 遅延初期化を行う該当のフィールドが、該当クラスのインスタンスのたった一部のフィールドであり、かつ、そのフィールドの初期化コストが高い場合には、遅延初期化の効果があるかもしれない。効果を確かめる唯一の方法は遅延初期化しない場合と性能差を比べるしかない。
* マルチスレッド環境下での遅延初期化はトリッキーなものとなる。本章で述べられる初期化テクニックはスレッドセーフなものである。
* たいていの状況では、普通の初期化の方が遅延初期化よりも好ましい。以下通常の初期化例。

```java
// Normal initialization of an instance field
private final FieldType field = computeFieldValue();
```

* 遅延初期化を使って、初期化循環を防ぐにあたっては、シンプルで明確であるという理由から、synchronizedアクセサを使用するべきである。

```java
// Lazy initialization of instance field - synchronized accessor
private FieldType field;
 private synchronized FieldType getField() {
    if (field == null)
        field = computeFieldValue();
    return field;
}
```

* 上記2つの書き方は、フィールドがstaticであっても変わらない（フィールドとアクセサメソッド両方がstaticである場合は除く）。
* 遅延初期化をstaticフィールドに対して、パフォーマンス向上のために使用するのであれば、以下のような書き方があり得る（lazy initialization holder class idiom）。


```java
// Lazy initialization holder class idiom for static fields
private static class FieldHolder {
  static final FieldType field = computeFieldValue();
}
private static FieldType getField() { return FieldHolder.field; }
```

* 遅延初期化をインスタンスフィールドに対して、パフォーマンス向上のためにやるのであれば、以下のような書き方がある（double-check idiom）。
この書き方では、初期化済みであった場合には、ロックを取らないようにしている。
書き方の説明をすると、ここではフィールド変数に対して2回のチェックロジックがはしっている。1回目はロックせずにチェックをし、チェックの結果として初期化がまだであれば、ロックをしてもう一度チェックをする。2度目のチェックでも初期化がまだだったら初期化のメソッドを走らせる。
一度初期化されるとロックを用いた処理ではなくなるので、フィールドはvolatileで宣言しておかねばならない。

```java
// Double-check idiom for lazy initialization of instance fields
private volatile FieldType field;
 private FieldType getField() {
    FieldType result = field;
    if (result == null) {  // First check (no locking)
        synchronized(this) {
            if (field == null)  // Second check (with locking)
                field = result = computeFieldValue();
        }
    }
    return result;
}
```

* 上記のコードのresultはいらないように見えるが、これがあるとない場合より1.4倍くらい速くなるらしい（**速くなる理屈はよくわからず**）。
* double-check idiomはstatic フィールドにも適用できるが、lazy initialization holder class idiom の方がベターである。
* double-check idiom に関して、複数回の初期化にも耐えられるようにするには2つ目のチェックを除けばよい（single-check idiom）。
（**複数回の初期化に耐えられるようにするのに、なぜsingle-check idiomが適しているのかわからない。。**）

```java
// Single-check idiom - can cause repeated initialization!
private volatile FieldType field;
 private FieldType getField() {
    FieldType result = field;
    if (result == null)
        field = result = computeFieldValue();
    return result;
}
```
Item 82: Document thread safety

# 82.スレッドセーフティについてドキュメントすべし

* 提供するメソッドを並列実行させた時の挙動は、クライアントとの重要な約束事であり、ドキュメントとして明記しないとエラーを招くこととなる。
* sychronized句の有無でスレッドセーフであるかを見分けることはできない。
* スレッドセーフという性質はオールオアナッシングなものではなく、数段階のレベルがあるものである。以下、スレッドセーフの各レベルを要約する。
  * Immutable：状態は常に一貫しており、外部での同期は必要ない。
ex)String,Long,BigInteger
  * Unconditionally thread-safe：mutableなインスタンスであるが、内部で十分に同期がとれているので、外部での同期は必要ない。
ex)AtomicLong,ConcurrentHashMap
  * Conditionally thread-safe：Unconditionally thread-safeに似ているが、一部のメソッドでは外部での同期が必要となる。
ex)Collections.synchronized のラッパークラス。これらのiterators は外部の同期が必要となる。
  * Not thread-safe：並列処理をしようと思ったら必ず外部で同期が必要となる。
ex)ArrayList,HashMap
  * Thread-hostile：外部で同期をかけてもスレッドセーフにならない。たいていはstaticなデータを同期なしで変更していることによる。
ex)Item78のgeneralSerialNumber メソッド

* クラスのスレッドセーフティについてはクラスのJavadocに書くべきで、スレッドセーフティに関して特別な考慮が必要なメソッドには、そのJavadocに記述する。以下の```Collections.synchronizedMap```が好例。

```java
    /**
     * It is imperative that the user manually synchronize on the returned
     * map when traversing any of its collection views via {@link Iterator},
     * {@link Spliterator} or {@link Stream}:
     * <pre>
     *  Map m = Collections.synchronizedMap(new HashMap());
     *      ...
     *  Set s = m.keySet();  // Needn't be in synchronized block
     *      ...
     *  synchronized (m) {  // Synchronizing on m, not s!
     *      Iterator i = s.iterator(); // Must be in synchronized block
     *      while (i.hasNext())
     *          foo(i.next());
     *  }
     * </pre>
     */
    public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
        return new SynchronizedMap<>(m);
    }
```

* Unconditionally thread-safe なクラスを書くにあたっては、synchronized なメソッドの代わりにprivate lockを使う手法がある。これによって、クライアント、サブクラスからの悪意ある同期から守ることができる。（**DOSの例を挙げていたが、どうやって起こすのかいまいちわからない**）
Item 81: Prefer concurrency utilities to wait and notify

#81 wait と notify よりコンカレンシーユティリティを選ぶべし

* Java5以降、以前はwaitやnotifyで行っていた処理が高レベルなコンカレンシーユーティリティでできるようになった。これらを代わりに使うべきである。
* 高レベルなコンカレンシーユーティリティは3つに分けられる。
  * Executor フレームワーク（Item80）
  * concurrent collection。List、Map、Queueに並列処理がうまくできるように実装されたものがこれに当たる。これらは内部で同期がなされるため、ロックしても単に処理が遅くなるだけである。この部品は状態に依存する変更処理（state-dependent modify operations）に適している。concurrent collections の登場によって、synchronized collections はお払い箱となった。
  * synchronizers。synchronizers は他のスレッドの処理完了を待つなど、他と強調した動きを可能にする。有名なのは、CountDownLatch、Semaphore、CyclicBarrier、Exchanger、Phaserなど。
* CountDownLatch を使用したコードは以下のようになる。timeメソッドについて説明すると、ready が3回 countDown されると、ready のawait が解けて、startNanosが計測されて、start の countDown が1回なされて actionが走り、そして、各スレッドで done の countDown がなされて、3つすべてでcountDownされたらdoneのawaitが解けて、かかった時間が返される仕組み。このメソッドはスレッド数が第2引数で指定されていた数より少ない場合は処理が終わらない（thread starvation deadlock）。	

```java
package tryAny.effectiveJava;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class CountDownLatchTest {
    public static void main(String[] args) throws InterruptedException {
        Executor e = Executors.newFixedThreadPool(3); // ここの引数をtimeの第2引数の値未満にすると処理が終わらない。

        System.out.println(time(e, 3, () -> System.out.println("a")));

    }

    // Simple framework for timing concurrent execution
    public static long time(Executor executor, int concurrency, Runnable action) throws InterruptedException {
        CountDownLatch ready = new CountDownLatch(concurrency);
        CountDownLatch start = new CountDownLatch(1);
        CountDownLatch done = new CountDownLatch(concurrency);
        for (int i = 0; i < concurrency; i++) {
            executor.execute(() -> {
                ready.countDown(); // Tell timer we're ready
                try {
                    start.await(); // Wait till peers are ready
                    action.run();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    done.countDown(); // Tell timer we're done
                }
            });
        }
        ready.await(); // Wait for all workers to be ready
        long startNanos = System.nanoTime();
        start.countDown(); // And they're off!
        done.await(); // Wait for all workers to finish
        return System.nanoTime() - startNanos;

    }
}
```

* wait と notify についてはもはや新しく書かれたコードで見ることはない。レガシーなコードの保守で見ることはあるかもしれない。
* wait と notify についての要約だけ書くと、
  * waitはwhile ループの中で使うこと。
  * notifyよりnotifyAllを使うべき。notifyを使うときは、スレッドの生存に気を付けて使用せねばならない。
【Unity】GrabPassを用いた屈折(Refraction)シェーダー

Unityのシェーダーで、GrabPassを用いてガラスのような物体を疑似的に表現する方法です。

![fast.gif](https://qiita-image-store.s3.amazonaws.com/0/61569/7212afda-d409-f684-ce1f-f18ff0ce30d8.gif)

まず、`"Queue"="Transparent"`でGrabPassを行うことで、不透明なオブジェクトやスカイボックスをレンダリングした背面をテクスチャ`_BackgroundTexture`に書き込んでおきます。
フラグメントシェーダーでは組込関数`refract`を用いて計算した屈折方向に適当にレイを進めてから、`_BackgroundTexture`からサンプリングすることで屈折を再現しています。

シェーダー内ではSchlickの近似式を用いてフレネル反射係数を計算し、反射光と屈折光をブレンドしていますが、これは屈折係数が小さい場合見た目にあまり影響がないので必要ないかもしれません。

```Refraction.Shader
Shader "Refraction"
{
	Properties
	{
		_RefractionIndex("Refraction Index", Range(1.0, 3.0)) = 1.33
		_Distance("Distance", Float) = 10.0
		_Tint("Tint", Color) = (0.8, 0.5, 0.5)
		_SpecularColor ("Specular Color", Color) = (1, 1, 1)
		_Shiness ("Shiness", Float) = 10.0
	}
	SubShader
	{
		Tags {
			"RenderType" = "Transparent"
			"Queue" = "Transparent"
		}

		GrabPass
		{
			"_BackgroundTexture"
		}

		Pass
		{
			Tags {"LightMode" = "ForwardBase"}

			ZWrite Off

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"
			#include "Lighting.cginc"

			struct appdata
			{
				float4 pos : POSITION;
				float3 normal : NORMAL;
			};

			struct v2f
			{
				float4 pos : SV_POSITION;
				float3 worldPos : TEXCOORD0;
				float3 normal : TEXCOORD1;
			};

			float _RefractionIndex;
			float _Distance;
			float3 _Tint;
			float3 _SpecularColor;
			float _Shiness;
			sampler2D _BackgroundTexture;

			v2f vert (appdata v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.pos);
				o.worldPos = mul(unity_ObjectToWorld, v.pos).xyz;
				o.normal = UnityObjectToWorldNormal(v.normal);
				return o;
			}

			float schlickFresnel(float cosine) {
				float r0 = (1 - _RefractionIndex) / (1 + _RefractionIndex);
				r0 = r0 * r0;
				return r0 + (1 - r0) * pow(1 - cosine, 5);
			}

			fixed4 frag (v2f i) : SV_Target
			{
				float3 normal = normalize(i.normal);
				float3 viewDir = normalize(i.worldPos - _WorldSpaceCameraPos.xyz);

				float3 reflectDir = reflect(viewDir, normal);
				float3 reflectCol = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, reflectDir);

				float3 refractDir = refract(viewDir, normal, 1.0 / _RefractionIndex);
				float3 refractPos = i.worldPos + refractDir * _Distance;
				float4 refractScreenPos = mul(UNITY_MATRIX_VP, float4(refractPos, 1.0));
				float2 screenUv = (refractScreenPos.xy / refractScreenPos.w) * 0.5 + 0.5;
				#if UNITY_UV_STARTS_AT_TOP
				screenUv.y = 1.0 - screenUv.y;
				#endif

				float3 refractCol = tex2D(_BackgroundTexture, screenUv).xyz;
				float3 spec = pow(max(0.0, dot(normalize(_WorldSpaceLightPos0.xyz), reflectDir)), _Shiness) * _SpecularColor * _LightColor0;

				float f = schlickFresnel(max(0.0, dot(-viewDir, normal)));

				float3 c = (1.0 - f) * refractCol * _Tint + f * (reflectCol + spec);
				
				return float4(c, 1.0);
			}
			ENDCG
		}
	}
}
```
[cocoa][swift]AppleScriptとは何ぞや

<p>スマートフォン・エンジニアにとって、macOSはOfficeが動くUNIXという利点があり、シェル・スクリプトを利用した自動化に威力を発揮している。ただ、macOSにはMacintosh時代からのAPpleScriptがあり、これを利用しない手はない。<br />
自動化したけど、アラートが表示されていて失敗したという悲しいトラブルも、これで回避できるかも！？</p>

<p>シェルスクリプトとして実行する</p>

<pre><code>#!/usr/bin/osascript
display dialog "Welcome to AppleScript."
</code></pre>

<p>シェルスクリプトからAppleScriptをよぶ</p>

<pre><code>#!/bin/sh
osascript -e 'display dialog "Welcome to AppleScript."'
</code></pre>

<p>AppleScriptからシェルスクリプトを呼ぶ</p>

<pre><code>set fileInfo to do shell script "cd ~; ls" 
display dialog fileInfo 
</code></pre>

<p>最前面のアプリを終了させる</p>

<pre><code>#!/usr/bin/osascript
 
tell application "System Events"
    set fullname to name of (path to frontmost application)
end tell
 
set savedDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to "."
set front_app to items 1 thru -2 of text items of fullname as text
set AppleScript's text item delimiters to savedDelimiters
 
if front_app is "Firefox" then
    tell application "Firefox"
        quit
    end tell
end if
</code></pre>

<p>最前面のアプリのダイアログを改行キーで閉じる</p>

<pre><code>#!/usr/bin/osascript
 
tell application "System Events"
    set fullname to name of (path to frontmost application)
end tell
 
set savedDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to "."
set front_app to items 1 thru -2 of text items of fullname as text
set AppleScript's text item delimiters to savedDelimiters
 
if front_app is "Firefox" then
    tell application "System Events"
        keystroke return
    end tell
end if
</code></pre>

【関連情報】
<a href="https://ashole.connpass.com/event/100082/">Think AppleScript 2018.9</a><br />
<a href="https://cocoa-kanto.connpass.com/event/97193/">Cocoa.swift 2018-09</a><br />
<a href="https://cocoa-kanto.connpass.com/event/101034/">Cocoa.swift 2018-10</a><br />
<a href="https://cocoa-kanto.connpass.com/">Cocoa.swift</a><br />
<a href="https://www.facebook.com/groups/cocoa.kanto/">Cocoa勉強会 関東</a><br />
<a href="http://www.bitz.co.jp/weblog/">Cocoa練習帳</a><br />
<a href="https://qiita.com/m_yukio">Qiita</a><br />
Item 78: Synchronize access to shared mutable data

# 78.共有されるmutableなデータには、同期したアクセスをすべし
* 同期化の一つの役割は、排他制御であり、変数を矛盾した状態で読み取らせないようにすることにある。また、他スレッドが行った変更を見ることができるようにするのも同期化の役割である（**後半いまいちわからん**）。
* 排他制御だけでなく、スレッド間の信頼ある通信のためにも同期化は必要である。
* Thread#stop()は使ってはいけない。使うとデータが壊れてしまう。
* 以下のコードは一見、1秒で止まるように見えるが、実際には止まらない。バックグラウンドで動作するスレッドがいつstopRequestedを見に行くか、同期が保証されていないので、JVMは

```java
    while (!stopRequested)
        i++;
```
を

```java
if (!stopRequested)
    while (true)
        i++;
```
のように変換する。この最適化はhoistingと呼ばれる。（「**liveness failure**:プログラムがそれ以上先に進めなくなるエラー」の例）


```java
package tryAny.effectiveJava;

import java.util.concurrent.TimeUnit;

public class StopThread {
    private static boolean stopRequested;

    public static void main(String[] args) throws InterruptedException {
        Thread backgroundThead = new Thread(() -> {
            int i = 0;
            while (!stopRequested) {
                i++;
            }
        });

        backgroundThead.start();

        TimeUnit.SECONDS.sleep(1);

        stopRequested = true;
    }
}
```

* 以下のように、stopRequested の読み込み、書き込みともに同期化してやれば期待通りに1秒で止まる。

```java
package tryAny.effectiveJava;

import java.util.concurrent.TimeUnit;

public class StopThread2 {
    private static boolean stopRequested;

    private static synchronized void requestStop() {
        stopRequested = true;
    }

    private static synchronized boolean stopRequested() {
        return stopRequested;
    }

    public static void main(String[] args) throws InterruptedException {
        Thread backgroundThead = new Thread(() -> {
            int i = 0;
            while (!stopRequested()) {
                i++;
            }
        });

        backgroundThead.start();

        TimeUnit.SECONDS.sleep(1);

        requestStop();
    }
}
```

* 以下のように、stopRequestedにvolatile修飾子をつけてやれば、一番新しく書き込まれた値を読むことを保証できるので、期待通りに1秒で止まる。

```java
package tryAny.effectiveJava;

import java.util.concurrent.TimeUnit;

public class StopThread3 {
    private static volatile boolean stopRequested;

    public static void main(String[] args) throws InterruptedException {
        Thread backgroundThead = new Thread(() -> {
            int i = 0;
            while (!stopRequested) {
                i++;
            }
        });

        backgroundThead.start();

        TimeUnit.SECONDS.sleep(1);

        stopRequested = true;
    }
}
```

* ++のインクリメント処理はアトミックなものではないので、以下のコードが1ずつ上昇していくユニークな値を返す保証はない。解消する場合には、AtomicLongを使うべき。（「**safety failure**：プログラムが誤った結果を返すエラー」の例）

```java
// safety failure
private static volatile int nextSerialNumber = 0;
public static int generateSerialNumber() {
    return nextSerialNumber++;
}
```

```java
private static final AtomicLong nextSerialNum = new AtomicLong();
 public static long generateSerialNumber() {
    return nextSerialNum.getAndIncrement();
}
```

* 本章で扱われている問題を避けるには、mutableなデータの処理は1つのスレッドに限定させておくようにする。
Item 77: Don’t ignore exceptions

# 77.例外を無視してはならない
* エラーを無視するのが適切な場合もありうるが、その場合はcatchブロックの中でなぜエラーを無視するかのコメントを入れ、catchするエラーの変数名を**ignored**にするべきである。
* 検査例外も非検査例外も等しくこのItem77を守るべき。
Item 76: Strive for failure atomicity

# 76.障害原子性（failure atomicity）が達成できるよう努めるべし
* オブジェクトに対してメソッド呼び出しをして、エラーを出力した後でも、そのオブジェクトがメソッド呼び出し前と同じ状態にある。このような特性をfailure atomicという。
* immutableオブジェクトのメソッド呼び出しであれば、自ずとfailure atomicityが実現できる。
* mutableオブジェクトのメソッド呼び出しにおいて、極力failure atomicity とするための方法は以下。
  * オペレーション実行前にバリデーションチェックを入れる。（状態が変わる前にエラーにさせる）
  * 状態を変えるオペレーションの実行前に演算を行う。例えば、TreeMap の put であれば、実際にMapに加える前にソート処理が走り、そこでComparableでないものだったら落とされる。
  * 一時的なコピーを作成して、そのコピーに対して処理をしていき、最後に該当のコンテンツに代入するようにする。これは性能面でも有効。
  * 処理の最中で失敗するようなことがあれば、ロールバックするようにして、オペレーション開始前の状態に戻す。
* failure atomicityを満たせない場合は、エラーが起きた場合にどのような状態が残るのか、ドキュメントに残しておくことが理想。
Item 75: Include failure-capture information in detail messages

# 75.詳細メッセージにエラー記録情報を含めるべし
* 例外の詳細メッセージ（スタックトレースに出てくるやつ）にはエラー解析に役立つ情報を含める。例えば、IndexOutOfBoundsException であれば、下限値、上限値、indexの値を含めるようにすべき。（実際にはJava9時点で以下のようにindexの値だけ出すコンストラクタがある）

```java
    /**
     * Constructs a new {@code IndexOutOfBoundsException} class with an
     * argument indicating the illegal index.
     *
     * <p>The index is included in this exception's detail message.  The
     * exact presentation format of the detail message is unspecified.
     *
     * @param index the illegal index.
     * @since 9
     */
    public IndexOutOfBoundsException(int index) {
        super("Index out of range: " + index);
    }
```

* スタックトレースは多くの人目に触れるため、詳細メッセージにパスワードや暗号化キー等を含めてはいけない。
Jetson TX1で9軸センサーを使ってみる

## 環境
- Jetson TX1
- HiLetgo MPU9250
- [RTIMULib2](https://github.com/RTIMULib/RTIMULib2)

## 参考
[らずぱいで、MPU-9250 - ９軸センサモジュール(３軸加速度＋３軸ジャイロ＋３軸コンパス)](https://qiita.com/mt08/items/2bbe57ce92f2ff661da6)

## 配線
VCC(3.3V)、GND、SCL、SDAを接続するだけ。Jetson TX1のI2Cは3.3Vなので、そのまま接続できます。

## インストール

```
$ sudo i2cdetect -y -r 1
[sudo] password for nvidia: 
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --     
```

```
$ sudo apt install libqt4-dev
$ git clone https://github.com/richards-tech/RTIMULib2.git
```

下記のIDを必要に応じて修正。

```:RTIMULib2/RTIMULib/IMUDrivers/RTIMUDefs.h
// #define MPU9150_ID               0x68
#define MPU9150_ID                  0x73
```

```
$ cd RTIMULib2/Linux
$ mkdir build & cd build
$ cmake ..
$ make -j4
```

## 動作確認
```
cd RTIMULibDemoGL
./RTIMULibDemoGL
```

![settings.png](https://qiita-image-store.s3.amazonaws.com/0/109483/a0a9d1aa-b27a-81cf-3ff8-9ef2fb240227.png)

![demo.png](https://qiita-image-store.s3.amazonaws.com/0/109483/8eef8fcc-fce0-0e11-cb6e-e187a2df2fff.png)
wicketでブラウザの戻るボタンが意図したとおりに動かない


### 環境

* Wicket 8.0.0

### 背景

ページ A は検索フォームを持つ一覧画面で、一覧から個々のレコードをクリックするとページ B の詳細画面に遷移する仕様になっている。

このとき、ページ B でブラウザの戻るボタンを押すと、ページ B に遷移する前の、ページ A の検索条件や、ページネーションの表示していたページを復元するようになっている（というかそうしたい）。

### 問題

しかし、ブラウザの戻るボタンを押しても、検索フォームや、ページネーションなどは復元せずに、常に初期化されてしまう。

### 原因

結果として、原因は PageParameters の使い方にあった。PageParameters を使った画面遷移は以下のように行うと思う。

```java
PageParameters pageParameters = new PageParameters();
pageParameters.set("id", threadData.getId());
setResponsePage(DetailPage.class, pageParameters);
```

しかし、今回のコードは以下のようになっていた。

```java
PageParameters pageParameters = getPageParameters();
pageParameters.set("id", threadData.getId());
setResponsePage(DetailPage.class, pageParameters);
```

new PageParameters() のところが、getPageParameters() となっており、新規でページパラーメータを作るのではなく、既存のページのページパラメータを取得していた。どちらも画面遷移は正常に行われるので、正直なところ、new PageParameters() と、getPageParameters() の影響の違いについて完全に無頓着だった。まさかと思って修正してみると、そのまさかだったわけである。

### 補足

wicket の公式ドキュメントは以下のとおりである。

> A new page version is created when a stateful page is requested for the first time or when an existing instance is modified (for example changing its component hierarchy).

[8.2. Stateful pages](https://ci.apache.org/projects/wicket/guide/8.x/single.html#_stateful_pages) より。


意訳すると、新しいページのバージョンが生成されるのは状態を持つページを初めてリクエストしたときか、あるいは、既存のインスタンスを変更したとき（例えばコンポーネントの階層を変更したときなど）である。

要するに、getPageParameters() を呼んで、パラメータを追加したりすることは、既存のインスタンスに変更を加えたことになるようだ。この状態でページ遷移し、戻るボタンを押すと、新しいページバージョンが生成されてしまう。

画面遷移のためのページパラメータは、きちんと new しようということである。

### 感想

Wicket のもっとも差別化された特徴は、Stateful というところにあると思う。今回はページパラメータが原因だったけど、ブラウザの戻るボタンで元の画面が復元されない原因はもっといろいろあると思う。でも、それらは結局のところ「既存のインスタンスを変更したとき」状態が復元できなくなるというところに集約されることになる。
Item 74: Document all exceptions thrown by each method

# 74.各メソッドからスローされる例外は全てドキュメントに残すべし
* 検査例外をスローするメソッドには、Javadoc内で@throwsタグを使って、どのような状況でスローされるのか書く。
* 非検査例外に関しても、Javadoc内で@throwsタグでどのような場合にスローされるのか書くべき。こうすることによって、API使用者は@throwsがあるのにthrows句がないことから、該当の例外が非検査例外であることを知る手掛かりとなる。
* 各メソッドがスローしうる非検査例外全てをドキュメントとして残すのが理想。（現実はそうもいかない）
* クラス内の多くのメソッドで、同じ理由でスローされる例外は、クラスのドキュメントに記すべきである。
Item 73: Throw exceptions appropriate to the abstraction 

# 73.抽象概念に適した例外をスローすべし

* 低層で送出された例外は、高層で具体的に行われているタスクとあまり関係がないように見えて困ることがある。また、低層で創出された例外は、高層のAPI実装に影響を与えうる（**あまりピンとこない**）。この問題を避けるために、低層で送出された例外をcatchし、高層の例外に翻訳する処理を加えることがある。



```java

// Exception Translation

try {

    ... // Use lower-level abstraction to do our bidding

} catch (LowerLevelException e) {

    throw new HigherLevelException(...);

}

```



* 低層から高層に例外翻訳する際に、低層での例外情報を保持するために、以下のようにchaining-aware constructor を書くことべき。



```java

// Exception Chaining

try {

    ... // Use lower-level abstraction to do our bidding

} catch (LowerLevelException cause) {

    throw new HigherLevelException(cause);

}

```



* 一番良いのは、そもそも低層で例外が起こらないようにすることであり、そのために渡すパラメータの値をバリデーションしたりすることを考える。
Item 72: Favor the use of standard exceptions

# 72.標準例外の使用を心掛けるべし

* Javaライブラリが提供している標準例外を用いることによるメリットは以下。

  * 慣習に従っているので、学びやすく理解しやすい

  * 見慣れない例外を使用していないので、読みやすい

* 以下、Javaライブラリにある例外をしるす。

  * IllegalArgumentException：nullでない、不適鉄な引数を受け取ったときスローされる

  * IllegalStateException：受け取るオブジェクトの状態が不適切な時スローされる。例えば、あるオブジェクトを適切に初期化する前に使用してしまった場合などにスローされる

  * NullPointerException：nullが禁止されているところでパラメータがnullとなる場合にスロー

  * IndexOutOfBoundsException：リスト等のパラメータの範囲外にアクセスした場合にスロー

  * ConcurrentModificationException：シングルスレッドで利用される前提で作られたオブジェクトが、並列実行を検知したときにスローされる

  * UnsupportedOperationException：該当オブジェクトがサポートしていないメソッドを使用した場合にスロー

* 例外を再利用するときは、その例外のドキュメントをみて、意図に沿っているか確認せねばならない
Item 71: Avoid unnecessary use of checked exceptions

# 71.不必要な検査例外の使用はさけるべし

* APIを適切に使用しても該当の例外的状況を避けられず、かつ、その例外が発生したときにAPI利用ユーザが何らかの有益なアクションを取れる場合にのみ検査例外の使用するべき。

* メソッドによってスローされる検査例外がただ一つである場合、実質的に実装者の負担は増える？。（**どういう理屈か理解できなかった**）

* 検査例外をスローする代わりに、空のOptionalを返す方法がある。このOptionalを返す方法のデメリットは望み通りの演算ができなかったことについての情報を呼び出し元に届けられない点にある。

* 検査例外スローを避ける手段として、常に成り立つわけではないが、状態を確かめる boolean を返すメソッドと、非検査例外を返すメソッドに分ける方法がある。



```java

// Invocation with state-testing method and unchecked exception

if (obj.actionPermitted(args)) {

    obj.action(args);

} else {

    ... // Handle exceptional condition

}

```
Item 70: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors

# 70.復帰可能な状況では検査例外を用い、プログラミングエラー？に対しては実行時例外を用いる

* 指針としては、呼び出し側が復帰できるような状況で出力される例外は、検査例外とする。復帰できないものは非検査例外。

* 復帰可能か否か判別がつかない場合は非検査例外とすべき。（item71で説明）

* Error クラスは慣習的にリソース欠乏時などにJVMによって出力されるものであり、Errorのサブクラスをプログラマーが作ることはまずない。そのため、非検査例外のうちでimplementsしうるのはRuntimeExceptionのみである。

* Throwablesを直接継承した例外を定義してはならない。検査例外を継承しないことによるメリットがないし、ユーザを混乱させてしまうため。
Item 69: Use exceptions only for exceptional conditions

# 69.例外的な状況にのみ、例外は用いるべし

* パフォーマンスを上げる目的で、通常のフローにもかかわらず、例外を用いたコードを書いてはならない。

* APIを作成するにあたっては、通常のフローで例外を使うようにさせない工夫がいる。以下のようなコードを生まないようにするには、hasNext 的なメソッドを用意するか、状態に応じて空のOptionalやnullを返すメソッドを用意するかのいずれかが考えられる。並列でアクセスされる可能性がある場合は後者を選ぶべき。性能的には後者のほうが良い。可読性と誤り検知のしやすさの観点では前者が勝る。



```java

// Do not use this hideous code for iteration over a collection!

try {

    Iterator<Foo> i = collection.iterator();

    while(true) {

        Foo foo = i.next();

        ...

    }

} catch (NoSuchElementException e) {

```
Item 68: Adhere to generally accepted naming conventions

# 68.命名慣習には従うべし
## 命名慣習
Javaの命名慣習はJLS6.1にうまくまとまっている。
大雑把にいって、命名慣習は表記的なもの（typographical）と文法的なもの（grammatical）に分けられる。

## typographical

### パッケージ名、モジュール名
パッケージ名、モジュール名はピリオドで区切られたコンポーネントで階層化されて表現される。
コンポーネントはアルファベットの小文字（とまれに数字）で表される。
組織外で使用されるパッケージには、組織のインターネットドメイン名を逆さにしたものから始める（com.googleなどのように）。このルールはjavaとjavaxから始まる標準パッケージに関しては適用範囲外である。ユーザーはjava、javaxで始まるパッケージ、モジュールを作成してはならない。
インターネットドメイン名をパッケージの接頭辞にする詳しいルールはJLS6.1に書いてある。

パッケージ名の残りは、1つ以上のコンポーネント名から構成される。
コンポーネント名は一般に、8文字以下の短い文字列（略語など）であることが推奨される。

### クラス名、インターフェース名
列挙型、注釈型含むクラス名、インターフェース名の名前は、各単語の先頭一文字を大文字にした単語で構成する。
頭字語とmax、min等の一般的な略語を除いて、略語の使用は控えるべきである。
頭字語について、全部大文字で記載するか、先頭一文字のみ大文字にするか、議論の分かれるところであるが、見やすさの観点からここでは先頭一文字を大文字にする法を推したい。

### メソッド名、フィールド名
メソッド名、フィールド名は基本的に、最初の一文字目を小文字にする、というところ以外はクラス名、インターフェース名の規則と同じである。
この規則の唯一の例外は、定数フィールドでは大文字の単語をアンダースコアで区切るようにする。（NEGATIVE_INFINITY）

### ローカル変数
ローカル変数の命名慣習は、フィールド変数のそれとほぼ同じであるが、ローカル変数では文脈に沿った略語を命名することが認められている（i,denom,houseNum等）。
引数となる変数に関しては、メソッドのドキュメントに統合するものとなるので、注意深く命名してやる必要がある。

### 型パラメータ
型パラメータは基本的に一文字で構成される。
Tは任意の型、Eはコレクションの要素の型、KとVはmapのキーと値の型、Xは例外の型、Rは戻り値の型をあらわす。
また、任意の型を複数使う場合の順序は、T、U、VまたはT1、T2、T3である。

## grammatical
命名に関する文法的な規則は、表記規則より柔軟で議論の余地がある。
### パッケージ名、モジュール名
パッケージについては文法上の命名規則はない。

### クラス名、インターフェース名
列挙型を含む、インスタンス化可能なクラスは、単数名詞、名詞句で名前が付けられる（Thread,PriorityQueue,ChessPieceなど）。
インスタンス化しないクラスは、名詞の複数形で命名されることが多い（Collectors,Collectionsなど）。
インターフェースは、クラスと同様の命名規則であったり（Collection,Comparatorなど）、末尾が形容詞的な終わり方になっていたり（Runnable,Iterable,Accessibleなど）する。
注釈型については、様々な用途があるので、これまでに出てきたいずれにも当てはまらない。名詞、動詞、前置詞、形容詞すべてよく使われる（BindingAnnotation, Inject, ImplementedBy,Singletonなど）。

### メソッド名
何らかのアクションを実行するメソッドは、一般的に、動詞、動詞句で命名される（append,drawImageなど）。
booleanを返すメソッドは、isまたはhasで始まり、名詞、名詞句、または形容詞として機能する言葉が続くように命名される（isDigit, isProbablePrime, isEmpty, isEnabled, hasSiblingsなど）。
boolean以外の値を返すものや、オブジェクトの属性を返すメソッドは、名詞、名詞句、getで始まる動詞句で名前が付けられる。
getで始まる動詞句だけが認めれるとする声があるが、その根拠は乏しい。
名詞、名詞句の命名方法を使ったほうが、たいていは可読性が上がる。

```java
if (car.speed() > 2 * SPEED_LIMIT)
    generateAudibleAlert("Watch out for cops!");
```


いくつかのメソッド命名規則には特別な言及が必要である。
インスタンスの型を変換し、独立したオブジェクトとして返すメソッドはtoTypeメソッドと呼ばれたりする（toString、toArrayなど）。
受け取ったオブジェクトと異なる型のオブジェクトを返すメソッドはasTypeメソッドと呼ばれたりする（asListなど）。
呼び出されるオブジェクトと同じ値のプリミティブな値を返すメソッドはtypeValueメソッドと呼ばれたりする（intValueなど）。
ファクトリメソッドの一般的な名前はinclude from, of, valueOf, instance, getInstance, newInstance, getType, newTypeなどがある（Item1）。

### フィールド名、ローカル変数
フィールド名の文法規則はそれほど重要でない。なぜなら、ちゃんと設計されたAPIでは、公開されるフィールドがほとんどないからである。
boolean型のフィールドはアクセサメソッドの最初の文字列だけ消えたものが採用されることが多い（initialized,compositeなど）。
その他のフィールドでは名詞、名詞句であることが多い（height,digits,bodyStyle）。
ローカル変数の文法規則はフィールドよりもっと緩い。
railsのfile_fieldを編集してuploadの画像が表示されるようにする

# 目的

画像のアップロードが

![スクリーンショット 2018-09-16 18.23.05.png](https://qiita-image-store.s3.amazonaws.com/0/193389/431e81c0-1437-9842-b595-30e0c07c4909.png)

こういうのでダサいのでデザインを変えたい！しかしじつはこのファイルを選択ボタンとfile名が表示されるのは同じでどちらかを消してデザインを足すというのができない。。。なので２つとも消してuploadしたファイルのプレビューを出す方法を下記にまとめた。

# fileuploadのデザインを変える

```ruby
          <label for="post_image" class="btn btn-outline-secondary"><i class="fas fa-upload"></i>サムネイル画像（任意）</label>
          <%= f.file_field :image , class: "hidden" , "v-on:change" => "onFileChange" %>
          </label>
```

file_fieldをhiddenで消してlabelにデザインを入れる。forとidでつなげるのを忘れずに

# デザインを消すとuploadした画像がわからなくなるのでvueで表示

```ruby
    <div id="app">
      <div class="row" v-show="uploadedImage">
        <div class="col-md-12 col-sm-12 image_upload">
          <img :src="uploadedImage" class="rounded form_thum_image" />
        </div><!--12-->
      </div><!--row-->
      <div class="row">
        <div class="col-md-12 col-sm-12 image_upload">
          <label for="post_image" class="btn btn-outline-secondary"><i class="fas fa-upload"></i>サムネイル画像（任意）</label>
          <%= f.file_field :image , class: "hidden" , "v-on:change" => "onFileChange" %>
          </label>
        </div><!--12-->
      </div><!--row-->
    </div>
```

```javascript:app.js
import Vue from 'vue/dist/vue.esm';

var app = new Vue({
  el: '#app',
  data() {
    return {
      uploadedImage: '',
    };
  },
  methods: {
    onFileChange(e) {
      let files = e.target.files || e.dataTransfer.files;
      this.createImage(files[0]);
    },
    // アップロードした画像を表示
    createImage(file) {
      let reader = new FileReader();
      reader.onload = (e) => {
        this.uploadedImage = e.target.result;
      };
      reader.readAsDataURL(file);
    },
  },
})
```

上記で"v-on:change"でuploadしたら発火するようにする。
ガチガチのウォーターフォールの現場にテストファーストを持ち込んだ話

#概要
要件定義→基本設計→詳細設計→製造→単体テスト→結合テスト→総合テスト→ユーザ受入テスト(いわゆる典型的なウォーターフォール)の流れでしか開発経験がない、それ以外の開発プロセスは許容しない、というお客様の案件に、テストファーストを一部導入した話。

#前提
俺氏:とあるSIerにSEとして勤務する2年目。
案件:とある大手企業のサービス開発案件。
経緯:実装終了後、「設計書通りだけど、実際動かしてみるとなんかイメージと違う」と大きな仕様変更のご要望を頂く。納期的に厳しいことをお伝えしたところ、「これでは業務が回らないので困る」とのこと。また、予算追加は厳しいとのことで要員増も難しい。以前、サービスの戦略的な理由からリリースを伸ばしているので、さらに延期するのはできない。結果、プチ炎上。(プチ炎上で済んだのは案件自体の規模がそこまで大きくなかったからではないかと思う)
その後、追加開発を行うことになった。

#背景
もともと、お客様側のプロジェクトメンバーが、IT系のプロジェクト未経験で、要件を期日までにまとめきるのが難しいという理由から、アジャイル開発を提案していた。しかし、お客様の社内の事情からウォーターフォール型の開発以外は許容できないとの回答があったので、ウォーターフォールでの開発を行った。しかし、要件が変わることもよくあり、また、開発側の負荷がつかみにくい(ITプロジェクトの経験がないため)ので、大きな仕様変更が頻繁に入る状況になっていた。

#問題点
今回の案件でプチ炎上になってしまった問題点は、プロセスの進め方以外に、度重なる仕様変更にメンバーのモチベーション低下、コミュニケーションの齟齬、技術的な問題等があったが、開発プロセスに限定して考えることにした。
というのも、上記の問題の根元には「実装後に仕様変更が数多く入る」ということがあるが、それは開発プロセスに問題があると考えたからだ。具体的には、「設計書通りだけどイメージと違う」、この一言に集約されるように、設計書でのイメージと、業務要件を満たすためのイメージが乖離していることが原因だと考えた。経緯については詳細に記憶していないが、詳細設計書を元に実際の動作イメージを話し合う、という進め方をしていた。(これが一般的なことかどうかは経験が浅いこともありわかりません。)詳細設計書は技術者が実装を進めるための、いわゆる内部仕様書なので、動作イメージが実際のイメージと違ってきてしまうのかなと感じた。

#解決案
もともと自分がテスト駆動開発に興味を持っていたこともあり、プロジェクトにテスト駆動開発的なエッセンスを持ち込めないかなと思っていた。単体テスト仕様書を、実際のユーザの動作１つ１つを想定して作成していたので、これをもとにすれば動作イメージが思っていたのと違う、という状態を防げそうだと感じた。そこで、詳細設計書と単体テスト仕様書を同時に作成し、単体テスト仕様書をもとに動作イメージを決定すれば良いのではないかと考え、提案した。

#導入
ということで、上記の解決案をもとにPMに提案を相談。そこで、下記の２つの問題を指摘された。
・詳細設計書と単体テスト仕様書を同時に書くということは、(仕様を決定する段階である詳細設計時に)変更があった場合、修正コストが２倍になる
・プロジェクトの進め方が変更になることで顧客サイドに混乱が起こらないか

しかし、上については実装後に再度仕様を決定するコストの方が高いため、許容できる、と判断。また、下については混乱が起きてもカバーできるように追加開発のうち小さい要件で実施することにした。

#お客様の反応
「一つ一つの動作ベースの方がわかりやすい気がするけど、正直よくわからない」という反応

#実施してみてどうだったか
今回実施してみて、仕様変更がほとんどなく、実装の負担もかなり小さかったので、成功なのかな、とは思いますが、要件自体が小さいことが原因だったかもしれませんので、まだ未知数な部分が大きいです。しかし、この進め方を了承・理解してもらえたので、今後続けていく中でよりはっきり成果が上がるのではないかと考えています。

#最後に
そもそもウォータフォールがどうなんだ、とかそんなんテストファーストとは言えない！などなどあると思います。なにか言ってやりたい！という方はぜひコメントをいただきたいです。
この記事を読んでやっぱこれだからSIerはダメ、というご意見もあるかもしれません。ただ、SIerのいいところは、業務知見がある顧客と組んで、技術を提供することでその業界の人でなければ思いつかないようなサービスを開発できることだと思いますし、とても面白い仕事だと感じています。技術的にバリバリやっていきたい！という人にとっては遅れているように感じられる部分があるのは確かですが、それ以外の面でいいところもあるよ、というのを知っておいていただきたいなと思います。
「Webサイト用」モダン開発環境の考察

社内のフロントエンド、マークアップエンジニア向けに話をしそうなので、そのメモ。
なんとなくで読んでください。

## Index
- 「Webサイト用」モダン開発環境
- パフォーマンス施策

## 「Webサイト用」モダン開発環境

### Webサイト制作において必要な条件
#### モダンな技術を採用しつつ、今までの案件で使える
- SPAではなくWebサイトに対応
    - HTMLファイルが各ページで存在している
    - `head`内の情報が直接書かれている
- きれいなHTML
    - minifyされていない
    - Nuxt.jsのgenerateみたいに、最適化されすぎていない

### 変えたいもの
- 脱Gulp
  - Gulp -> npm scripts（タスクランナー）
  - Gulp -> webpack（バンドラー、トランスパイラー）
- jQuery -> Vue.js & Vanilla.js
- ES2015+ -> TypeScript（Classベース）
- EJS -> Pug

### 脱Gulp（Gulpをやめる理由）
  - Gulp関連の開発が停滞気味。
    - Gulpパッケージは、npmパッケージに依存している場合が多いが、アップデートに対応してくれる保証はない。
  - Gulpの知識は、スケールしない。
    - まあ、JavaScriptの勉強になるかもだが。

#### Gulpの代わりになるもの
- npm scripts
  - npmパッケージを直接使える。
  - Node.js（Server Side JavaScript）の勉強になる。
- webpack
  - 開発が活発
  - ES Modulesが便利（ES Modulesは、今後ネイティブでも実装される）
  - ビルドが優秀（Gulpではバンドルや依存解決は難しい）

### jQuery -> Vue.js & Vanilla.js
jQueryは素晴らしい。

- jQueryのメリット
  - セレクタが扱いやすい
  - 便利なメソッドが盛りだくさん
  - エコシステムが豊富
  - 社内の知見がいっぱい

が、エンジニアとして、頼りすぎてはいけない。

**「jQueryはいらない。エンジニア強度が下がるから」**

#### jQueryでできることは、Vue.jsとVanilla.js（library）でできる。
 - [脱jQueryのためのメモ](https://qiita.com/otsukayuhi/items/6c8d49d000a0e410107a)
 - どちらも使えるに越したことは無い

#### Vue.jsのメリット
- 仮想DOMによる描画の最適化
- 複雑になると、jQueryよりわかりやすい
- HTMLから処理が予想しやすい
- コンポーネントによる、効率的な開発
- オブジェクト指向、コンポーネント指向の勉強になる
- [Vue.js devtool](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)が鬼便利

#### 使い分けのお薦め
- 複雑な処理がないページ：Vanilla.js（jQuery.min.js 約87KBの節約）
- 複雑なページ：Vue.js
- JavaScriptが苦手な人（デザイナー等の非エンジニア）との共同開発：jQuery
- JavaScriptで勝負しない人：jQuery

### ES2015+ -> TypeScript（Classベース）
- TypeScriptはJavaScriptのスーパーセットなので、別に書かなくても良い
- 静的型付けによる、チェックが便利
  - Microsoftが開発しているため、VS Codeと相性が良い
- Classの機能が、ES2015+より豊富
- Googleの標準言語に採用される

### EJS -> Pug
- タグの閉じ忘れがない
- EJSより見やすい
- JavaScriptが書きやすい
- コンポーネント指向で作りやすい
- Vue.jsとの相性が良い
- Github Star （2018.9.17時点）
  - EJS: 2802
  - Pug: 17,223

#### 使い分けのお薦め
- シンプルなページ：Pug
- 複雑なページ：Pug
- 小中〜大規模なページ：Pug
- おれ、HTMLしか知らない：EJS

## パフォーマンス施策
- リクエストを減らす
  - webpackによる、ファイルのバンドル＆画像のbase64エンコード
- 体感的な速さの獲得
  - inline CSSを設定
- CSS・JavaScriptの非同期読み込み、画像の遅延読み込み
  - CSS: [loadCSS](https://github.com/filamentgroup/loadCSS)
  - JavaScript: async, defer
  - images: [lazysizes](https://github.com/aFarkas/lazysizes)
at coder beginner 015　C再帰D動的計画法

高橋くんは、上司から
会社で作っている N 個のソフトウェアに平均でどれくらいのバグがあるか調べろ
ただし、バグがないソフトは調査母数に含めるな
と指示されました。
しかも、上司は小数が嫌いです。とはいえ、バグ数の平均値を過小報告するわけにもいかないので、値を切り上げて報告することにしました。
高橋くんは、素早くバグ数の平均値をまとめて上司に報告する必要があります。 ソフトウェアごとのバグ数が与えられるので、バグが含まれるソフトウェアの、バグ数の平均値を小数で切り上げて求めてください。

切り上げのテクニック
AをBで割った値を切り上げたい。

```
if(a&b==0){
c=a/b;
}else{
 c= a/b+1;
}
```
としてもよいがどうも長い。もっとスマートに書くには、
(a+(b-1))/b
これで切り上げになる。

```
#include <iostream>
using namespace std;
int main(){
	int N;
	int A[110];
	int ans=0;
	int zero = 0;
	cin >> N;
	for (int i = 0; i < N; ++i) {
		cin >> A[i];
		if (A[i] == 0) {
			zero++;
		}
		ans += A[i];
	}
	int num = N - zero;
	if (num == 0)
		cout << 0 << endl;
	else
	cout << (ans + num - 1 )/ num << endl;
	return 0;
}
```

C

```
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<list>
#include<cmath>
#include<map>
using namespace std;
using ll = long long;
const int INF = 1e9;
#define rep(i,n)for(int i=0;i<n;++i)
#define p pair<int,int>
int N, K;
int T[10][10];
bool dfs(int i, int x) {
	if (i == N) {
		return x == 0;
	}
	for (int m = 0; m < K; ++m) {
		if (dfs(i + 1, x^T[i][m])) {
			return true;
		}
	}
	return false;
}
int main() {
	cin >> N >> K;
	for (int i = 0; i < N; ++i) {
		for (int j = 0; j < K; ++j) {
			cin >> T[i][j];
		}
	}
	if (dfs(0, 0)) {
		cout << "Found" << endl;
	}
	else {
		cout << "Nothing" << endl;
	}
	return 0;
}
```
再帰。なんかもやもやするな、
D

```
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<map>
#include<math.h>
#include<queue>
#include<deque>
#include<stack>
#include<cstdio>
#include<utility>
#include<set>
#include<list>
#include<cmath>
#include<stdio.h>
#include<string.h>
#include<cstdio>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using piii = pair<pii, pii>;
const int INF = 1e9 + 7;
int main() {
	int W;
	int N, K;
	int A[51], B[51];
	int dp[51][51][10010];
	cin >> W >> N >> K;
	for (int i = 0; i < N; ++i) {
		cin >> A[i] >> B[i];
	}
	for (int i = 0; i < 51; ++i) {
		for (int j = 0; j < 51; ++j) {
			for (int k = 0; k < 10010; ++k) {
				dp[i][j][k] = 0;
			}
		}
	}
	for (int i = 0; i < N; ++i) {
		for (int j = 0; j < K; ++j) {
			for (int k = 0; k <=W; ++k) {
				if (k >= A[i]) {
					dp[i + 1][j + 1][k] = max({ dp[i][j + 1][k], dp[i][j][k],dp[i][j][k - A[i]] + B[i] });
				}
				else {
					dp[i + 1][j + 1][k] = max(dp[i][j][k], dp[i][j + 1][k]);
				}
			}
		}
	}
	cout << dp[N][K][W] << endl;
	return 0;
}
```
dp
コンポーネントに関する6つの原則

## コンポーネントとは

コンポーネントとは、デプロイ単位のことであり、システムの一部としてデプロイできる最小限のまとまりを指す。例えば、Javaならjar、Rubyならgem、.NETならDLL等がそれにあたる。あらゆる言語において、コンポーネントがデプロイの基準となる。よくできたコンポーネントは常にデプロイできる状態を保っているため、個別に開発を進めることができる。
本記事では「コンポーネントの凝集性に関する原則」3つと「コンポーネントの結合に関する原則」3つを取り上げる。

## コンポーネントの凝集性に関する原則
凝集性とは、機能と機能の関わり具合の尺度を指す。凝集性が高い（機能と機能の関わり具合が低い）ほど良いプログラムとされる。
※密接に関係するものは1つに集め、関係しないものは分けるという考え方がベースとなる。

#### 再利用・リリース等価の原則(REP:The Reuse/Release Equivalence Principle)
「コンポーネントを再利用するには、コンポーネントのリリース単位で行う」という原則。
言い換えると「再利用の単位とリリースの単位は等価になる」という原則。
※例えば、Javaのクラスを修正した場合、クラス単位ではなくjar単位でリリース・再利用を行うのが理想。
考え方としては重要なのは「コンポーネントに含まれるクラスは、すべてが再利用されるか、すべてが再利用できないかのどちらかにすべき」ということ。

#### 閉鎖性共通の原則(CCP:The Common Closure Principle)
「同じ理由、同じタイミングで変更されるクラスをコンポーネントにまとめること。変更の理由やタイミングが異なるクラスは、別のコンポーネントに分ける」という原則。
これは、単一責任の原則（SRP）をコンポーネント向けに言い換えたもので「コンポーネントを変更する理由が複数あるべきではない」としている。変更箇所が1つのコンポーネントに閉じていれば、変更後にデプロイする必要があるのはそのコンポーネントだけになり、そのコンポーネントに依存していないコンポーネントは再デプロイは不要となる。
考え方としては重要なのは「同じ理由、同じタイミングで変更されることが多いクラスは1つのコンポーネントにまとめておくべき」ということ。

#### 全再利用の原則(CRP:The Common Reuse Principle)
「1つのクラスだけを再利用するということはめったになく、複数のクラスと組み合わせて使われることがほとんどのため、そうしたクラス群は1つのコンポーネントにまとめる」という原則。
この原則は、どのクラスをひとまとめにすべきかということと、どのクラスをひとまとめにすべきではないかを表現している。

#### コンポーネント凝集性のテンション図
各原則は相反するところがあるため、アーキテクトはこれらの原則をバランスよく取ること。

![テンション図.png](https://qiita-image-store.s3.amazonaws.com/0/23101/049b8a2e-e178-d79e-2c69-c2f22892853f.png)


## コンポーネントの結合に関する原則

#### 非循環依存関係の原則（ADP:Acyclic Dependencies Principle）
「コンポーネントの依存グラフに循環依存があってはならない」という原則。
コンポーネント間で循環依存がある場合、コンポーネント単独でのデプロイ、リリースができずその部分が温床となりコンポーネント間での不整合が発生する。そのため（アプリケーションが成長するにつれてコンポーネントの依存構造も細かく変わっていくので）、循環依存が生まれないよう適切に管理する必要がある。なお、コンポーネント間での依存は、具象クラスレベルではなく、インターフェース等の抽象レイヤーで依存すること。

#### 安定依存の原則（SDP:Stable Dependencies Principle）
「安定度の高い方向に依存すること」という原則。
「安定度の高い」とは、変更がしづらいということ。多数のコンポーネントから依存されたコンポーネントは（変更することの影響が大きいので）変更しづらい、そのためこういったコンポーネントは安定度が高いと考えらえれる。また、基本的に抽象度の高いレイヤーに依存すべきなため、「安定度の高い方向に依存」とは、言い換えると抽象度の高いレイヤーに依存せよとも言える。

#### 安定度・抽象度等価の原則（SAP:Stable Abstractions Principle）
「コンポーネントの抽象度は、その安定度と同程度でなければならない」という原則。
つまり、安定度の高いコンポーネントは抽象度も高くあるべきで、安定度の高さが拡張の妨げになってはいけない。一方、安定度が低いことによってその内部の具体的なコードが変更しやすくなるため、安定度の低いコンポーネントはより具体的であるべきである。

## 参考
[Clean Architecture 達人に学ぶソフトウェアの構造と設計](https://www.amazon.co.jp/Clean-Architecture-%E9%81%94%E4%BA%BA%E3%81%AB%E5%AD%A6%E3%81%B6%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%81%AE%E6%A7%8B%E9%80%A0%E3%81%A8%E8%A8%AD%E8%A8%88-Robert-C-Martin/dp/4048930656)