OmniAICreator/Qiita-1.07M huggingface dataset:
構造化プログラミング的オブジェクト指向のすすめ

# はじめに
最近のプログラミングはオブジェクト指向プログラミング一択のようなんですが、C#だとかJavaだとかのプログラミング言語を覚える事がオブジェクト指向プログラミングを覚える事とイコールになってしまってオブジェクト指向プログラミングってなによって感じになってるような気がします。

で、オブジェクト指向プログラミングについて勉強しようと思っても専門用語とかが多すぎて訳わかんないし、職場の先輩とか上司とかの間違ったオブジェクト指向プログラミングによる仕様書やなんかで・・・

というわけで、オブジェクト指向プログラミングを勉強する前に、まずは構造化プログラミングを勉強してみてはいかがでしょう？

# 構造化プログラミングとは
wikiによると、

構造化プログラミングではプログラミング言語が持つステートメントを直接使ってプログラムを記述するのではなく、機能を抽象化した仮想機械を想定し、その仮想機械が提供する命令群でプログラムを記述する。普通、抽象化は1段階ではなく階層的である。各階層での実装の詳細は他の階層と隔離されており、実装の変更の影響はその階層内のみに留まる。各階層はアプリケーションに近い抽象的な方から土台に向かって順序付けられている。この順序は各階層を設計した時間的な順番とは必ずしも一致しない。

と難しい言葉でよく判らないことが書いてあるので、ここはあえて無視します。

構造化プログラミングで大事なことは次の3つ
1．プログラムを機能や処理によってブロックに分ける
2．各処理は1．で作ったブロックを呼び出して記述する
3．機能の追加や削除、修正などはブロック単位で行う

このプログラムの機能や処理をまとめた『ブロック』がプログラムを構成する構造体でこのブロックを積み重ねてプログラムが出来上がります。
また、積み重なったブロックの一部を別のブロックに入れ換えたり順番を変えればプログラムの動きが変わりますし、一度作ったブロックは他のプログラムにも利用可能だったりします。

って、これってなんてオブジェクト指向プログラミング？

# オブジェクト指向プログラミングとの比較
wikiによると、

オブジェクト指向プログラミングとは、一般的に以下の機能や特徴のいくつか、あるいは多くを活用したプログラミング技法である。
カプセル化（振る舞いの隠蔽とデータ隠蔽）
インヘリタンス（継承） -- クラスベース
ポリモフィズム（多態性、多相性）
ダイナミックバインディング（動的束縛） -- 動的型付け
これらの機能を提供するプログラミング言語は、オブジェクト指向プログラミング言語 (OOPL; object-oriented programming language) と呼ばれる。これらの機能のうち、オブジェクト指向の考え方で不可欠なのは「カプセル化」の機能だけである。そのため、オブジェクト指向プログラミング言語の中には、カプセル化以外の機能については一部を提供していないものもある。
ただし、カプセル化（可視性の定義）やポリモフィズムとダイナミックバインディングはオブジェクト指向言語に固有の概念というわけではなく、非オブジェクト指向言語の中にもこの性質を備えるものもある。

ってまぁ判りやすいような判りにくいような事が書いてありますが、この中で不可欠と書かれている『カプセル化』が『構造化』に置き換えられるんです。

また、カプセル化以外のインヘリタンスやポリモフィズムもよく読めば構造化プログラミングの中で書かれていたりするので、我々普通のプログラマにとっては殆ど同じ設計思想と言ってしまってもそれほど間違ってはいないかもしれません。あくまでも現場レベルでは、ですがｗ

# 構造化プログラミング的オブジェクト指向のすすめ
オブジェクト指向でプログラムを設計しようと思うと、まずどんなクラスを作ってと言った感じで『外側』から作りがちですが、構造化プログラミングの場合はまずそのプログラムに必要な機能を洗い出して、そしてそれを組み合わせてブロックを作って、そして更にそのブロックを組み合わせてもう一つ大きなブロックを作って・・・と言った感じで『中身』から作ります。

これはオブジェクト指向プログラミングで最初で最大の難関であるたい焼きの例えで考えると判りやすいと思います。

オブジェクト指向プログラミングでは
1.たい焼きの型を作る（クラスの作成）
2.たい焼きの中の餡を作る（プロパティ、メソッドの構築）

構造化プログラミングでは、
1.たい焼きの中の餡を作る（機能ブロックの作成）
2.たい焼きの型を作る（プログラムの作成）

となります。
ここでオブジェクト指向プログラミングがこの例えで何故判りにくいかというと、この状態で今川焼きを作りたい場合どうすれば良いのかと考えるとすぐに判ります。

今川焼きをインヘリタンスで作るとすれば、たい焼きが中に入ったでっかい今川焼きになるの？
たい焼きの中の餡をポリモーフィズムで今川焼きに入れることは出来るけど、そんな風に作ってないから作り直しだしぃ・・・

でも、構造化プログラミングなら、餡は餡というブロックで作ってありますので、今川焼きでも御座候でも回転焼きでも、それこそどら焼きでも違和感なく、直感的に餡を流用出来ます。（餡を餡クラスとして作成して、たい焼きクラスや今川焼きクラス、どら焼きクラスなどでインクルードやインポートしてもいいでしょう）

ま、オブジェクト指向プログラミングでも設計手法をきちんと理解した上で、きちんと設計してからプログラミングすればこんな変なことにはなら無いのですが、現場でやっつけでプログラムしてるとついついこんな変なことになってしまったり、上の人がたい焼き信者の自称ベテランオブジェクト指向プログラマーだったりすると・・・

というわけで、オブジェクト指向プログラミングで作成するように言われてもいきなりクラスから作らずに、まずは機能や処理のブロック化、構造化を行ってから、オブジェクト指向を頭の隅に置きながらどの単位でクラスにすると便利かな？って考えならがブロックという構造体を積み重ねていく事をお勧めします。
Android7に更新すると音が鳴らなくなる・音が消える

手持ちのAndroid端末をAndroid7（Nougat）に更新したところ
現在開発中のアプリ（レトロゲーム風RPG)の効果音が鳴らなくなった。
https://play.google.com/store/apps/details?id=com.game.sh_crew.rebuildingsaga

アプリ起動直後には効果音が鳴っているのだが
あるタイミングを境に、効果音がまったく鳴らなくなってしまった。

戦闘のBGMなどは影響がないため
原因を調査したところ
BGM・効果音ともにMediaPlayerクラスを用いていたが
効果音のみMediaPlayerインスタンスの解放処理を実施していないことが原因だった。

■修正前

```
       try
        {
            mp = MediaPlayer.create(activity.getApplicationContext(), res);
            mp.start();
        }
        catch (Exception e)
        {
            RsLogger.error("Music Error.", e);
        }
```

■修正後

```
       try
        {
            // すでにMediaPlayerが生成されているか？
            if (mp != null)
            {
                // リリース
                mp.reset();
                mp.release();
                mp = null;
            }
            mp = MediaPlayer.create(activity.getApplicationContext(), res);
            mp.start();
        }
        catch (Exception e)
        {
            RsLogger.error("Music Error.", e);
        }
```

BGMの方はrelease処理が実装されているため、きちんと音が流れ続けていた。
Android7以前はreleaseしなくても問題なかったのだが……。

きちんとリソースは解放しなきゃいけないということですね。
（そもそも効果音ならSoundPoolクラスを用いるべきだったのかも）

ネットを調べると、音が鳴らなくなる現象が結構発生しているみたい。
同じような現状が発生しているアプリは
リリース処理が漏れているのかもしれないなあ。
Rails 5.1.2からSendGridのEmail Link WhitelabelでSSL Errorが起きる問題

# （簡単な）対策
production.rbなど適切な場所に、以下のoptionを追加する。

```rb
config.ssl_options = {hsts: {subdomains: false}}
```

# 説明

Rails 5.1.2から、Strict-Transport-Security header（通称：HSTS）のincludeSubdomainsのデフォルト値がtrueになったため、例えばあなたのサービスのドメインが、`example.com`だったとして、SendGridのLink Whitelabelに通常通り、`link.example.com`を使用していた場合、example.com（内のページ）にアクセスしたことがある人（ブラウザ）は、そのサブドメインにもSSL接続を試みるようになりますが、link.example.comが有効なSSL通信ができない場合、エラーが発生します。
（SendGridが送るメール内ではhttpでlink.example.comにアクセスしていますが、ブラウザがHSTSによりSSLに置き換えている形です。）
（やっかいなのは、example.comにアクセスしたことのない人は、基本的にHSTSの機構が働かないので、問題なくそのままアクセスできるので、この問題に気付きにくいです。）

なお、Strict-Transport-Security headerについては、[MDN](https://developer.mozilla.org/ja/docs/Web/Security/HTTP_Strict_Transport_Security)などを参照してください。

# よりよい対策

上では、すぐにできる簡単な対策を書きましたが、当然、より高いsecurityとprivacyのためにはサブドメインでも可能な限り、SSL通信を使うべきで、そちらに関しては、公式が[ドキュメント](https://sendgrid.com/docs/Classroom/Build/Add_Content/content_delivery_networks.html)を公開しています。
golang のバイナリをRaspberry pi用にWindows 上でクロスコンパイルしてputtyで転送する

いつも忘れるので、自分用にメモ。

`uname -m`でARMバージョンを確認

```
$ uname -m
armv6l
```

`windows`のコマンドプロンプトでgoのバイナリをビルド

```
> set GOOS=linux
> set GOARCH=arm
> set GOARM=6
> go build -o {{バイナリ名}}
```
pscpを使ってファイルをRaspberry pi に転送

```
> pscp -scp -P 22 {{送りたいファイル}} pi@192.168.1.1:/home/pi
```

# 参考文献

* http://qiita.com/yamasaki-masahide/items/8fab969ef99968ed374a
* http://phantom37383.blog.fc2.com/blog-entry-1589.html
DigdagとApache AirflowのGCPサポート比較

ワークフローツールであるDigdagとApache AirflowのGCP向けに提供されているオペレータについてざっくりまとめてみた。

## Digdag
今のところGCSとBigQueryに対応
https://docs.digdag.io/operators.html

#### GCS
CSにファイルが置かれるのを待って、置かれたことをトリガーにできる

#### BigQuery
- クエリ実行
- データセットやテーブルの管理（作成や削除など）
- BigQueryからのデータエクスポート
- BigQueryへのデータロード

## Airflow
GCS, BigQuery, Dataflow, Dataproc, DataStoreをサポート。

####GCS
- GCSからのファイルダウンロード
- GCSからBigQueryへのファイルロード

### BigQuery
- クエリ実行
- テーブルコピー
- BigQueryからGCSへのエクスポート
- クエリ実行した結果のチェック

### Dataflow
- Dataflowジョブ（Java)の起動

### Dataproc
- Pigクエリジョブのキック
- Hiveクエリジョブのキック
- SparkSQLジョブのキック
- Sparkジョブのキック
- Hadoopジョブのキック
- PySparkジョブのキック

#まとめ
DigdagよりもAirflowの方がGCP用に用意されているオペレータが多いが、個人的にはDigdagの方がシンプルに記述できるので好みである。ただAirflowはUIが見やすかったりして便利そうなので、用途に合わせて使い分けするのがよさそうである。
コンピューターずぶの素人がORACLE PGXを使ってみた②

####※注意※　SQLのタグをつけていますが、**あくまでSQLライクのクエリ言語です**

##今回行うこと
---

- デモの実践

　今回研究を行うにあたって、物は試し！ということでSlide Shareで公開されているデモを再現してみました。

参考：[Oracle Labs 発！ Parallel Graph Analytics（PGX） - SlideShare](https://www.slideshare.net/oracle4engineer/oracle-labs-pgx)


　とりあえず無料で検証・開発を行えるそうなので以下のサイトでPGXシェルサーバーzipとJavaのパッケージをダウンロード（デモスライドではPGXシェルver2.3.1を使用）。Javaは最新のバージョンで大丈夫でした。


[PGX Server Download](http://www.oracle.com/technetwork/oracle-labs/parallel-graph-analytix/downloads/index.html)
[Java Download](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)


> 1. **linux**用です！！（正直最初はlinuxすらよくわかりませんでした、、）
> 2. 今回はAWSのEC2を使用しました。
> [AWS EC2が何なのか分らない人のために](http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/concepts.html)
> 3. ~~PGXサーバーの最新バージョン（PGX2.4.1）では有向性、無向性の定義の関係上の問題？で上手く処理できなかった。~~
> **バージョン2.5.0で改善されるそうです！**https://community.oracle.com/thread/4055609


 私の場合は一旦ローカル環境に落としてから、SFTP転送によって、EC2で作った仮想linuxサーバーのpgxディレクトリ（/home/ec2-user/pgx）に移しました。
　

※EC2で作成した仮想サーバー内にpgxディレクトリを作成して、そこにダウンロードしたものをそれぞれ入れたということです。

<details><summary>SFTP転送が何なのかわからない人は[こちらを見て下さい](https://winscp.net/eng/docs/lang:jp)。</summary>要するに安全にローカル環境からリモート環境へファイルを転送するということです。転送するにあたって設定が分からないとなる人がいると思いますが、ホスト名（IP）、ユーザ名（ec2-user, ubuntuなど）、パスワード（設定した人のみ）、ポート（設定にもよるが大抵22）を押さえておけば大丈夫です、きっと。</details>


　その後、各ファイルを展開します。

```linux:参照
$ cd $HOME/pgx
$ unzip pgx-2.3.1-server.zip
$ tar xvzf jdk-8u131-linux-x64.tar.gz
```

※tarコマンドについて：[tar コマンド | コマンドの使い方(Linux) | hydroculのメモ](https://hydrocul.github.io/wiki/commands/tar.html)

　Javaのバージョンを確認（`$ java -version`）したら、PGXシェルを起動するために環境変数の設定を行います。参考にしたもののファイル名を自分のものに変える程度です。


- 環境変数設定

```
$ vim env_pgx
```

```linux:env_pgx
#!/bin/sh
export JAVA_HOME=/home/ec2-user/pgx/jdk1.8.0_131
export PATH=$PATH:/home/ec2-user/pgx/pgx-2.3.1/bin
export PATH=$JAVA_HOME/bin:$PATH
```

※#!/bin/shについて：[シェルスクリプトの1行目に書くおまじないで使える便利オプション集:Qiita](http://qiita.com/yn-misaki/items/6fcfab082dd664f10d4e)

　有効化して、うまくいっているかどうか確認します！

```
$ . env_pgx
$ echo $PATH
```

![2017-07-12.png](https://qiita-image-store.s3.amazonaws.com/0/190039/b1758477-9a64-7adf-9f02-2d0aca723f5c.png)

　上のようになっていれば大丈夫です。（多分。）

　なお、このままでは**サーバーを再起動した場合に有効化がリセットされてしまうらしい**ので、有効化を維持するために以下の隠しファイルに同様の内容を追加で記述します（重複すみません）。

```linux:.bash_profile
export JAVA_HOME=/home/ec2-user/pgx/jdk1.8.0_131
export PATH=$PATH:/home/ec2-user/pgx/pgx-2.3.1/bin
export PATH=$JAVA_HOME/bin:$PATH
```


- PGXシェル起動

　それでは起動してみます。

```
$ pgx
```

![2017-07-12 (1).png](https://qiita-image-store.s3.amazonaws.com/0/190039/80f49d34-22b3-59c1-b79d-268a87fd514a.png)

　上手くいけば上の図のようになります。よくわからないけどシェルに入れました！

　なお、シェルを閉じるときは

```
pgx> :exit
```

　エラーが発生した時は

```
pgx> :clear
```

##補足
---

※今回、EC2インスタンスを動かし続けないようにcrontabというものを用いて自動停止設定をしました。

- cron設定

日本時間 24:00 = UTC 15:00

```
$ sudo vi /etc/crontab
0 15 * * * root shutdown -h now
```

```
$ sudo service crond restart
```

cronはcrondが起動していないと実行されないみたいです、難しい、、


> 参照：[cronの設定・実行 | WEBサービス創造記 
](http://linuxserver.jp/linux/cron%E8%A8%AD%E5%AE%9A)
　　　[cronの設定方法 - Qiita](http://qiita.com/hikouki/items/e744b3a4d356d2af12cf)
      [初心者向けcronの使い方 - Qiita](http://qiita.com/tossh/items/e135bd063a50087c3d6a)
ぐちゃぐちゃですみませんでした！
Reactの環境構築を最短で行う

#:star: 目標
* `create-react-app`のコマンド一つでReactのアプリが生成できるようにする

<img width="657" alt="スクリーンショット 2017-07-12 20.27.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/178077/c7ffce6b-146f-4746-635e-e1ad91ddc1f8.png">
#:star: 手順
:pencil: nodebrewをインストールし、初期設定をします

````
$ brew install nodebrew
$ nodebrew setup
````
:pencil: nodebrew用のパスを`bash_profile`に追加し、読み込みます

````
$ cd
$ vi ~/.bash_profile

# これを追記してパスを通す
export PATH=$HOME/.nodebrew/current/bin:$PATH

# 読み込むのを忘れずに
$ source ~/.bash_profile
````
:pencil: Node.jsをインストールします

````
$ nodebrew install-binary v7.4.0

# インストールされていればバージョンが表示されます
$ nodebrew ls
````
:pencil: `create-react-app`コマンドが使えるようにします

````
$ npm install -g create-react-app
````
:pencil: 実際にアプリを作ってみましょう

````
$ create-react-app アプリ名
````
:pencil: アプリのディレクトリに移動して下記コマンドで実行します

````
$ npm start
````

:bulb: 下記の画面が表示されれば成功

<img width="657" alt="スクリーンショット 2017-07-12 20.27.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/178077/c7ffce6b-146f-4746-635e-e1ad91ddc1f8.png">
###:star2: 素敵なReactライフを！
#:star: 関連
* [Reactの環境構築を最短で行う](http://qiita.com/mikan3rd/items/496a87fc8b76263d0a91)←ここ
* [【React】ToDoアプリを作ってみよう【前編】](http://qiita.com/mikan3rd/items/20152cdd63a708264a9e)
* [【React】ToDoアプリを作ってみよう【後編】](http://qiita.com/mikan3rd/items/0a1be8fa9f349735cf4a)
* [【React】ToDoアプリを発展させよう【非同期処理】](http://qiita.com/mikan3rd/items/41e4a94a50fa6676542a)

#:star: 参考
* [Facebook公式のcreate-react-appコマンドを使ってReact.jsアプリを爆速で作成する](http://qiita.com/chibicode/items/8533dd72f1ebaeb4b614)
Insta360 Airの動画フォーマット一覧


これから購入する人の参考になれば

```shell-session
pi@instaview-dev:~ $ v4l2-ctl --list-formats-ext --all

# 前略

ioctl: VIDIOC_ENUM_FMT
        Index       : 0
        Type        : Video Capture
        Pixel Format: 'MJPG' (compressed)
        Name        : Motion-JPEG
                Size: Discrete 1472x736
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 2176x1088
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 3008x1504
                        Interval: Discrete 0.033s (30.000 fps)

        Index       : 1
        Type        : Video Capture
        Pixel Format: 'H264' (compressed)
        Name        : H.264
                Size: Discrete 1920x960
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.042s (24.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                Size: Discrete 2560x1280
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.042s (24.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
```
さくらVPSをはじめてつかってみた⑤ -Apacheインストールしたけど、アクセスできない

Apacheのインストールと初期設定をしてみたもののアクセスができない状態になってしまった
(IPアドレスを打ち込んでも初期画面が表示されず、アクセス不可)

ネット記事をみると色んな記事がヒットしたけど、
とりあえずアクセスログを確認することに。

rootでログインして以下を実行。

`# cd /var/log/httpd`
`# tail -f access_log`

▼参考記事
http://knowledge.sakura.ad.jp/beginner/3424/

`# tail -f access_log`
を実行するとターミナルが入力待ちの状態になって、この状態で該当アドレスにブラウザでアクセスすると
アクセスログがターミナルに出力されるとのこと。
しかし、実行しても何も出力されず。

記録がないということは、Apache側の設定の問題みたい？？

httpd.configの設定を色々かえてもアクセスできない。
だけど、chkconfig –listコマンドなどでApacheの起動をチェックすると、起動はしている様子。

うーん？？となって、ネット記事を漁ったら
iptablesでhttp(80)とhttps(443)の接続が許可されていないのでは？という記事がヒットして

▼この記事
http://te2u.hatenablog.jp/entry/2013/09/12/215031

上記記事の通りにiptablesに設定の追加をしたら
無事に初期画面が表示されました^^
うーんサーバは難しいけど、知見をネットに残してくれる方々に感謝。
Bluemix Infrastructure(SoftLayer)でのDDoS対策

# 1. はじめに
DDOS(distributed denial of service attack)とは、不特定多数の機器を利用してアクセス過多の状態を作り出すことによって、リソース枯渇、高負荷状態を発生させサービスの提供を阻害する攻撃です。本記事では、Bluemix Infrastructure(旧称：SoftLayer)でのDDoS対策について紹介します。

# 2. Bluemix Infrastructureとして保護している内容

- Bluemix Infrastructureでは、各種プロバイダとも協力し、悪質なIPとみなされるサイトからは通信を受け付けないように[spamhaus](https://www.spamhaus.org)などの情報を元にブラックリスト方式でブロックを行なっています。
- 上記に加えて、Bluemix InfrastructureではDDoS対策をNetwork POPで提供しており、上記のブラックリスト以外のサイトからの攻撃も防いでいます。このDDoS対策は、自動もしくは必要に応じて手動で行なっており、ネットワークの利用状況はNOC(Network Operation Center)によって常時監視されています。
- ただし、このDDoS保護は個々のお客様を直接保護するために提供されているものではなく、Bluemix Infrastructure全体のネットワークを保護するために提供されているものです。そのため、特定のお客様向けにカスタマイズした保護が行われる訳ではありません。


例えば、Bluemix Infrastructure上にアカウントA, B, C, D, ....というお客様が存在し、アカウントAが所有するサーバーがDDoS攻撃を受けていると仮定します。この場合、この攻撃を放置すればBluemix Infrastructureのリソースを消費してしまい、他の利用者（アカウントB, C, D,...）までサービスを阻害されてしまう恐れがあります。こうした事態を避けるために、Bluemix InfrastructureではアカウントAで攻撃を受けているPublic IPを、問題が解決されたとみなされる一定期間の間null route化してIPパケットが届かないようにブロックします。その結果、クラウド全体のネットワークリソースを確保することが可能となり、他の利用者（アカウントB, C, D, ...）をアカウントAに対するDDoS攻撃から保護することが可能になります。
なお、攻撃を受けているIPアドレスがnull route化されている間、アカウントAは、SSL-VPNなどの機能を使ってPrivate NW経由でサーバーにアクセスすることはできますが、攻撃を受けている期間中は該当のPublic IPを使ってサーバーにアクセスすることはできません。ただし、null route化されているのは攻撃を受けているPublic IPだけなので、同一VLAN上にある他のPublic IPまでブロックされる訳ではありません。

# 3. ユーザー側での対応案

小規模アクセスによる攻撃であれば、Firewallなどでrate limitingを行い、同時接続数を制限するといったチューニングやSyn-Cookie機能を使って使用リソースを抑えることで、サーバーへの負荷を抑えることが可能です。例えばLinuxであればiptablesでlimitモジュールを利用することで実装が可能ですし、Vyattaなどのソフトウェアルーターでも同様の機能は実装されています。
しかし、一般的にDDoS攻撃は不特定多数のIPアドレスから一斉に攻撃するため、DoS攻撃と違って特定のIPアドレスから攻撃される訳でもありません。よって、ソースIPアドレスでブロックするという手段も有効ではありません。そもそもDDoS攻撃によってフィルタリングを行う内部処理の負荷が増大し、ネットワークだけでなくFirewallもリソースを消費してしまい正常アクセスを妨げてしまう可能性があります。その意味で、DDoS攻撃を防ぐのは一般には難しく、Firewallの設定や単なるツールの導入程度で完全に防ぐことは困難です。
よく私がオススメしている方法は、より万全な対策を取りたいのであればa)のような方法を、コスト的に厳しいのであればb)のような方法をご提案しています。どちらにしても、b)の方法は常日頃から作業手順を確認しておきたいところです。

- a) AkamaiなどのCDN機能や、Akamai Kona Site Defenderなどのような[クラウドベースのDDoS保護機能](https://www.ibm.com/security/services/managed-web-defense/index.html)をIBM Cloud上のサービスの前段に配置する。。
- b) （対処療法的になるが）複数のPublic Portable IPを保持しておき、DDoS攻撃を受けてnull route化された際には別のIPに付け替える（DNSもそれに合わせて切り替える）。


# 参考資料
https://developer.ibm.com/cloudarchitecture/docs/security/securing-workloads-ibm-cloud/network/
EntityListnerをサービスとして定義しているときに、EntityManagerをインジェクトしているサービスをインジェクトできない（解決済み）


## はじめに、何が問題か
下記のissueが分かりやすいので、引用して説明します。

- [Entity Listener : Inject a service containing entity manager #300 doctrine/DoctrineBundle](https://github.com/doctrine/DoctrineBundle/issues/300)


```yml
services:
    acme.invoice.listener:
        class: %acme.invoice.listener.class%
        arguments:
            - "@acme.invoice.manager"
        tags:
            - { name: doctrine.orm.entity_listener }

    acme.invoice.manager:
        class: %acme.invoice.manager.class%
        arguments:
            - "@doctrine.orm.entity_manager"
```

上記のようなサービス定義をしていると、`ORMException`が発生します。

```
[Doctrine\ORM\ORMException]                                                                                          
It's a requirement to specify a Metadata Driver and pass it to Doctrine\ORM\Configuration::setMetadataDriverImpl(). 
```

## 今までどうしてきたか
このissueは、2014-06-17に作成されました。
10日後の2014-06-27には、下記のように、[コメント](https://github.com/doctrine/DoctrineBundle/issues/300#issuecomment-47270839)が付いています。

```
We passed the service_container to the listener.
It's not the best solution but we don't have time to find a better one.

私たちはサービスコンテナをリスナーに渡すようにした。
決して最良の解決策ではないが、これよりいい方法を探す時間がない。
```

つまりは、`EntityListener`には、具体的なサービスではなく、サービスコンテナそのものを渡すというバッドノウハウが使われてきたようです。

## 2年のときを経て、いよいよ解決に
2015-07-06に、この問題を解決すべく、下記Pull-Requestが作成されました。

- [Added lazy-loading entity listeners #443 doctrine/DoctrineBundle](https://github.com/doctrine/DoctrineBundle/pull/443)

そして、様々な議論・レビューの結果、2016-11-19にmasterブランチにマージされました。
`doctrine/doctrine-bundle`の`1.6.5`にて上記PRが取り込まれています。

## 結論、こうすれば解決する
- `doctrine/doctrine-bundle`を`1.6.5`以上に更新する
- `EntityListener`の`tags`に`lazy: true`を付け加える

```yml
services:
    acme.invoice.listener:
        class: %acme.invoice.listener.class%
        arguments:
            - "@acme.invoice.manager"
        tags:
            - { name: doctrine.orm.entity_listener, lazy: true }

    acme.invoice.manager:
        class: %acme.invoice.manager.class%
        arguments:
            - "@doctrine.orm.entity_manager"
```

## おわりに
サービスにサービスコンテナをインジェクトするのは、アンチパターンだということをチーム内で声高に言ったら、この問題を踏んでしまいました。
くじけずに調べて解決できて良かったです。
同じ問題にぶち当たった人が見てくれるといいなと思っています。
ではでは。
[Elixir] Qiita API v2 ラッパーを作成してみた

Qiita API v2 ラッパーをElixirで作成してみました

## つくったもの

`qiitex` というパッケージ名でhexに公開しています

Github : https://github.com/tamanugi/qiitex
hex : https://hex.pm/packages/qiitex

## インストール方法

```elixir:mix.exs
def deps do
  [{:qiitex, "~> 0.2.0"}]
end
```

hexで公開しているので、mix.exsに上記を追加して
`mix deps.get` でインストールできます

## 使い方

認証情報とAPIのエンドポイントを保持したclientを生成し、
関数に引数として渡すことで実行できます

```elixir
iex> client = Qiitex.client.new %{access_token: "enteryouryoken"}
iex> Qiitex.Tags.list client
iex> Qiitex.Tags.list client, %{page: 1, per_page: 30, sort: "count"}
iex> Qiitex.Items.create client, %{title: "title", body: "body", tags: [%{name: "qiita"}]}

```
アクセストークンは[こちら](https://qiita.com/settings/tokens/new) から発行してください

各関数のドキュメントは[こちら](https://hexdocs.pm/qiitex/api-reference.html)をご参照ください〜 (~~Qiita公式ドキュメントからほぼコピペですが~~)

※Qiita API v2 の仕様については[公式ドキュメント](https://qiita.com/api/v2/docs)を参考にしてください

## APIの構成について

今回APIラッパーを作成にするあたって下記のライブラリを参考にしました

https://github.com/edgurgel/tentacat

lib/qiitex にて `use HTTPoison.Base` でHTTPoisonモジュールを読み込んで
必要な関数のみ実装しています

GET, POST, PATCH, PUT, DELETE の各HTTPメソッドの関数を実装したら
あとはQiitaのAPIリファレンスにしたがってURLとメソッドを指定していくだけだったので
実装は楽でした


またQiita APIは JSON Schemeを公開しているので
そのJSON Schemeを利用したテストも実装してみました

http://qiita.com/api/v2/schema
http://qiita.com/api/v2/schema?locale=en
http://qiita.com/api/v2/schema?locale=ja

[ExJsonScheme](https://github.com/jonasschmidt/ex_json_schema)という
ライブラリを用いて取得したデータの構造が正しいか確認しています

## その他
Qiita:team については確認ができないため実装はしませんでした・・・残念

## 参考にしたもの

[tentacat](https://github.com/edgurgel/tentacat)
[qiita-rb](https://github.com/increments/qiita-rb)

[Elixir 実装の Qiita API v2 Client を公開しました](http://qiita.com/ma2ge/items/8645f0e8bbd41e48b84b)
[ElixirのライブラリをHexに公開する](http://dev.classmethod.jp/server-side/publish-elixir-library/)

## 最後に

コメント, issue, Pull Request, マサカリ
なんでもフィードバックなど頂けると嬉しいです！
アクセスログから任意のランキングを作る汎用的なワンライナー

サーバを運用していると、アクセスログからサクッと件数を調べたくなることが多々ある。

時系列でのアクセス件数、ユーザーエージェント毎、リクエストURLなど様々だが、ワンライナーの型はほとんど同じ。

``` command
perl -ne 'next unless(/★単純にgrepするキーワード★/);/★集計単位★/;$counts{$1}++;END{for(sort keys %counts){print "$_ $counts{$_}\n"}}' access_log
```

Apacheのアクセスログ例を元に、具体的な使い方を紹介する。

# Googlebotのアクセス件数
単純にgrepするキーワード：Googlebot
集計単位：時間

``` command
$ perl -ne 'next unless(/Googlebot/);/2017:(\d\d)/;$counts{$1}++;END{for(sort keys %counts){print "$_ $counts{$_}\n"}}' access_log

03 1
04 11
05 17
06 36
07 20
08 36
09 30
10 33
11 54
12 45
13 62
14 23
15 32
16 38
17 24
18 15
```

# Safariでのアクセス件数
単純にgrepするキーワード：Safari
集計単位：時間

``` command
$ perl -ne 'next unless(/Safari/);/2017:(\d\d)/;$counts{$1}++;END{for(sort keys %counts){print "$_ $counts{$_}\n"}}' access_log
03 89
04 1982
05 6149
06 15110
07 18474
08 17452
09 14082
10 11929
11 11365
12 12830
13 9830
14 16637
15 19439
16 19432
17 25928
18 22898
```


# GoogleBotの接続元IP毎のアクセス件数
単純にgrepするキーワード：Googlebot
集計単位：接続元IP

``` command
perl -ne 'next unless(/Googlebot/);/^(\S+)/;$counts{$1}++;END{for(sort keys %counts){print "$_ $counts{$_}\n"}}' access_log
66.249.66.205 1
66.249.71.143 1
66.249.71.145 2
66.249.71.147 2
66.249.71.73 182
66.249.71.75 106
66.249.71.76 1
66.249.71.77 56
66.249.71.77, 1
66.249.71.78 1
66.249.79.35 48
66.249.79.39 25
66.249.79.61 51
```

# 叩かれたAPIのアクセス件数
単純にgrepするキーワード：なし
集計単位：API(/js/v2/*)

``` command
$ perl -ne 'next unless(//);/(\/js\/v2\/\w+)/;$counts{$1}++;END{for(sort keys %counts){print "$_ $counts{$_}\n"}}' access_log
 95215
/js/v2/com 19069
/js/v2/fb 63491
/js/v2/pc 27632
/js/v2/old 26
/js/v2/smartphone 9392
```


# 解説

```
END{集計処理}
```
抽出するキーでソート、件数をカウントして表示

```
/★集計単位★/;$counts{$1}++;
```
集計単位で抽出された部分がここに入る。
pipelineで秘匿したい文字列を扱う

# 課題
Backlogなどからファイルをwgetで落とそうとすると、APIキーがモロ出しになるのをどうにかしたい。

## 対応方法
Credentialsを使う

# 手順
## Credential登録
まず Credentialを登録する為、下記へ移動する
`Jenkins -> リポジトリ名/チーム名 -> 認証情報 -> Folder -> グローバルドメイン` 
`認証情報の追加` から認証情報を追加する。

今回隠したいのはAPIキーなので、
種別 Secret text とし、SecretにAPIキーを入力し、その他は適当に決める
![1.png](https://qiita-image-store.s3.amazonaws.com/0/59953/5ee23bf6-e4d3-5d79-56a8-40801f0d40e6.png)
## スクリプトを取得
`Jenkins -> リポジトリ名/チーム名 ->Pipeline Syntax` へ移動し、
`withCredentials`の項目を確認する。

追加ボタンから秘密テキストを選択し、認証情報から、先程登録した`BackLogKey`を選択する。
変数名を`ApiKey`とし、その後`Generate Pipeline Script` ボタンを押下する

押下すると、以下のようなPipeline用のGroovyスクリプトが表示される。

```groovy
withCredentials([string(credentialsId: 'BackLogKey', variable: 'ApiKey')]) {
    // some block
}
```
## Jenkinsfileの更新
あとはあなたのJenkinsfileに追加するだけです。

```groovy
withCredentials([string(credentialsId: 'BackLogKey', variable: 'ApiKey')]) {
    sh "wget -q https://hoge.backlog.jp/api/v2/projects/PROJECT/files/0123456?apiKey=$ApiKey -O ./hogefuga"
}
```

そうすると、ログとしては下記のような形で出力されます。
```
+ wget -q https://hoge.backlog.jp/api/v2/projects/PROJECT/files/0123456?apiKey=**** -O ./hogefuga
```

APIキーが****になってる！やったね！
ユーザIDやパスワードにも使えるようですので、使っていくと良いと思います。
Vimでスラッシュを含む文字列を検索する方法


*例）`/var/www/html`を検索する*

## 前方検索の場合

そのまま検索可能！

```
?/var/www/html
```


## 後方検索の場合

スラッシュをバックスラッシュでエスケープする。

```
/\/var\/www\/html
```

### Mac版のVimをお使いの方へ

以下のバージョンではバックスラッシュでエスケープが効かなかった。

```
:version
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Apr  4 2017 18:14:54)
```

Homebrewで新しいVimをインストールしたところ、エスケープが効くようになった。

```
:version                                                                                                                                                                                                          
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Jul 13 2017 12:02:51)
MacOS X (unix) version
```


### 参考

* [Homebrewで新しいバージョンのVimをインストールする](http://qiita.com/owlbeck/items/2df2ab50eedd32011ffd)
[iOS]ステータスバーの高さ、ナビゲーションバーの高さを取得

### Objective-C
```
// ステータスバーの高さを取得する
float statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
// ナビゲーションバーの高さを取得する
float navigationBarHeight = self.navigationController.navigationBar.frame.size.height;
```

### Swift
```
// ステータスバーの高さを取得する
let statusBarHeight = UIApplication.shared.statusBarFrame.size.height
// ナビゲーションバーの高さを取得する
let navigationBarHeight = self.navigationController?.navigationBar.frame.size.height
```
VirtualBox と Hyper-Vは共存できなかった


## 説明

Windowd 10 Pro は、標準でHyper-V が使えるので有効化している人もいると思いますが、VirtualBoxとの共存はできないので導入には注意が必要です。

Hyper-Vが有効化されているWindows 10 Pro 環境で、VirtualBox を導入して仮想イメージを起動しようとすると以下のように突然ブルースクリーンになってしまいます。

![bluescreen.png](https://qiita-image-store.s3.amazonaws.com/0/127983/be45613f-ddd9-50a7-8ca9-303e314531e4.png)

## 原因
64bit のゲストOS を利用するには、インテルの仮想化支援技術である**Intel VT-x** を有効化する必要があります。
しかし、Hyper-V を有効にしているとこの **Intel VT-x** が無効になってしまうようです。
そのため、正常に起動しないようです。

## 対応
Hyper-V または VirtualBox のいずれかのみを使用するように決める、です。

Hyper-V を有効また無効にするにはコマンドで以下のように実施する事ができます。

### Hyper-V無効化
`bcdedit /set hypervisorlaunchtype off`

### Hyper-V有効化
`bcdedit /set hypervisorlaunchtype auto`

上記コマンドは、いずれも **管理者権限で実施**、また**実施後の再起動が必要** となります。

ちなみに、私はHyper-V用のPCと、VirtualBox用のPCを分けて使用することにしました。
ローカルのポートをリモートのポートに転送する

# やり方
ssh には -L オプションというものがあり、このオプションを使うことでローカルのポートをリモートのポートに転送することができます。
例えば、ローカルの8080番ポートをリモートのlocalhostの8000番ポートに転送した時は以下のコマンドを打つとできます。

`ssh -L 8080:localhost:8000 hoge@example`

前の8080がローカルのポート番号で、真ん中のlocalhostがリモートホストから接続するホストで、後ろの8000がリモートから接続するポートのことです。これで、「自分の8080番ポートにつなぐ」ことと、「hoge@exampleから見た8000番ポートにつなぐことと同じ」ということになります。

ssh には様々なオプションがあり、自分がまだ全く知らないので勉強していきたいです。
なにか便利なオプションがあれば教えてください。
BrowsersyncでAccess-Control-Allow-Originを設定する方法

configのserver.middlewareに以下を追加するだけ。

```js
function(req, res, next) {
  res.setHeader('Access-Control-Allow-Origin', '*');
  next();
}
```

起動するところはこんな感じ。

```js
browserSync({
  port: <your port>,
  ui: {
    port: <your ui port>
  },
  server: {
    baseDir: <your src>,
    middleware: [
      function(req, res, next) {
        res.setHeader('Access-Control-Allow-Origin', '*');
        next();
      }
    ]
  },
  files: [
    ...
  ]
});

```
Bash の if 文（test文）のオプションを整理してみた

毎回調べるので備忘として整理する。
# 数値の比較オプション
書式　：　数値△オプション△数値
例　　：　if [ ${hoge} -eq 0 ];then

|オプション|説明|補足|
|:-----------:|:------------:|:------------:|
|-eq | 等しければ真     | equal                |
|-ne | 等しくなければ真 | not equal            |
|-lt | より小なら真     | less than            |
|-le | 以下なら真       | less than or equal   |
|-gt | より大なら真     | greater than         |
|-ge | 以上なら真       | greater than or equal|

# 文字列の比較オプション
書式　：　文字列△オプション△文字列
例　　：　 if [ "${hoge}" = "fuga" ];then

|オプション|説明|
|:-----------:|:------------:|
|=  | 等しければ真 |
|!= | 等しくなければ真 |

# ファイル・ディレクトリのオプション
書式　：　オプション△ファイルやディレクトリ
例　　：　if [ -d ${hoge} ];then

|オプション|説明|
|:-----------:|:------------:|
|-d | ディレクトリなら真          |
|-f | 普通のファイルなら真        |
|-s | サイズが 0 より大きければ真 |
|-e | 存在するなら真              |
|-r | 読み取り可能なら真          |
|-w | 書き込み可能なら真          |
|-x | 実行可能なら真              |

# 文字列長のオプション
書式　：　オプション△変数や文字列
例　　：　 if [ -z ${hoge} ];then

|オプション|説明|
|:-----------:|:------------:|
|-z | 文字列長が 0 なら真       |
|-n | 文字列長が 0 より大なら真 |

# その他使うやつ
## 引数の比較(getopts使わない)
例　　：　if [ $# -eq 2 ];then

|変数|説明|
|:-----------:|:------------:|
|$# | 実行時に指定された引数の数     |
|$1 | 実行時に指定された 1 番目の引数 |
|$n | 実行時に指定された n 番目の引数 |

## 実行結果の比較
例　　：　if [ $? -ne 0 ];then

|変数|説明|
|:-----------:|:------------:|
|$? | 直前のコマンドの実行結果 |

- - -
シェル書いてると、いつも忘れてぐぐってることをここにまとめていこうと思います。
『図解メモ』の使い方

##簡単に図解を作成したい
何かの説明のため、簡単な図を描きたいことがあります。
四角（要素）と矢印（要素間の関係）、2種類の図形を使えば、意思疎通の助けになります。
だけど、ＰＣで画像ファイルを作るのは、（自分には）ちょっと面倒です。

##フリーソフト『図解メモ』
自分が楽するために、Excel VBAでツールを作りました。
他に使う人がいるかもしれないので、フリーソフトにして、Vector.co.jpに置かせてもらいました。
http://www.vector.co.jp/soft/winnt/business/se516217.html 
使い勝手や、成果物の見栄えもカスタマイズできるように、ソースを公開しています。
良かったら、お試しください。

##使い方
（１）excelシート上のセルに、文字（要素）を配置する

<img width="442" alt="11.png" src="https://qiita-image-store.s3.amazonaws.com/0/76471/7f8c3c1c-912c-62ff-d209-856bc865aeff.png">

（２）Alt+F8などでマクロ「A_DRAW」を実行指示する

<img width="345" alt="2.png" src="https://qiita-image-store.s3.amazonaws.com/0/76471/88d4296f-8b35-ae07-e0e4-436b4daaf031.png">

（３）A～C列に表が作られるので、これを編集する

<img width="613" alt="13.png" src="https://qiita-image-store.s3.amazonaws.com/0/76471/d0ac8dfd-8e12-1f9b-586a-a1e292d1c61b.png">
　　（セルの文字の上に、サイズの揃ったテキストボックスが自動作成されています）

・A列C列は、四角いtextboxを作成する指示
・B列は、A列の四角からC列の四角までの結線の指示
　・A列C列の値を省略するとその上のセルの値を転用する
　・TBLR（上下左右）の指示があれば、カギ線のコネクタ、なければ直線で結びます。
　・T：上辺、B：下辺、L：左辺、R：右辺に結合、<：A列側に矢印、>：C列側に矢印の意
　・＃：一時的に結線の指定を無効にする意（自動描画位置が見難く手で結線を作成した場合など）

<img width="598" alt="14.png" src="https://qiita-image-store.s3.amazonaws.com/0/76471/45455e13-fcc6-f07e-7a97-b14ede9fa452.png">

（４）Alt+F8などでマクロ「A_DRAW」を実行指示する（sample2）

<img width="609" alt="15.png" src="https://qiita-image-store.s3.amazonaws.com/0/76471/3d177ec2-29d2-0045-da8a-52d46d91d2c5.png">

（画像として使いたい場合）
（５）画像にしたいセルの範囲を選択し
　　　Alt+F8などでマクロ「B_COPY」を実行指示し、
　　　他所（ペイントブラシ、Word、Excel、など）に貼り付けて使える

<img width="429" alt="sample.png" src="https://qiita-image-store.s3.amazonaws.com/0/76471/00dea0df-9e4d-a99c-fbf1-65e90c8afcfb.png">

（図形の位置を変更したい場合など）
（６）Alt+F8などでマクロ「C_DELETE」を実行指示すると、自動作成された図形が削除されます
（７）セル上の文字の位置を変えて、
（８）Alt+F8などでマクロ「A_DRAW」を実行指示してください
（９）図形名から「ZUKAIMEMO」を消すと、マクロでは削除されなくなります
##まとめ
図解を描きたいけど、描くのが面倒なら、『図解メモ』は如何ですか？
kviewer   結果を確認しながらKvファイルが書けるツール

　私は以前[KvEditor](http://qiita.com/gotta_dive_into_python/items/d903f10d4afe86868def)という物を作り 記事にもしたのですが、それが車輪の再発明であった事に今日気付きました。紹介します、[kviewer](https://github.com/kivy/kivy/blob/master/kivy/tools/kviewer.py)さんです。

# 準備

### 依存PackageをInstall
```
$ pip install watchdog
```

### ソースコードを修正

(追記: この作業はpython2においては不要です。dario_okazakiさんありがとう)
(追記: この修正を行うPullRequestは既に適用されています。version1.10.1以降を使っているならこの作業は要りません)

kviewer.pyの下の方には以下の行があります。


```python3:kivy/tools/kviewer.pyの一部
        except Exception as e:
            Window.add_widget(Label(text=e.message if e.message else str(e)))
```

私が使っているPython3.6.0ではAttributeError(messageという属性が存在しない)で落ちてしまうので以下の様に書き換えました。

```python3
        except Exception as e:
            Window.add_widget(Label(text=(
                e.message if getattr(e, r'message', None) else str(e)
            )))
```

# 使ってみる

適当にKvファイルを書いてから

```
$ python3 -m kivy.tools.kviewer ./test.kv
```

![Screenshot at 2017-07-12 18:15:51.png](https://qiita-image-store.s3.amazonaws.com/0/144673/310b2b60-2346-b08e-1b8c-f5907ae8fda1.png)

後はtest.kvが更新される度にkviewerがそれを感知して自動で結果を更新してくれます。

### 各種Error

存在しないClass
![Screenshot at 2017-07-12 18:16:02.png](https://qiita-image-store.s3.amazonaws.com/0/144673/427c78a0-3ee6-a4cb-ce3f-eb07980727f3.png)
問題のある行を示してくれればありがたいのですが...

Property名とコロンの間にSpaceを入れる
![Screenshot at 2017-07-12 18:16:21.png](https://qiita-image-store.s3.amazonaws.com/0/144673/c67d82e5-31d6-c5d3-5329-776511220afb.png)
何故かErrorにならなかった。Kivy1.9.1ではちゃんと怒ってくれたのに。

無効な識別子
![Screenshot at 2017-07-12 18:16:30.png](https://qiita-image-store.s3.amazonaws.com/0/144673/be63e024-d787-6ccc-f9d8-e40c8906d446.png)
Azure新ポータルのサイト間VPNをYAMAHA RTXで接続する場合

Azure新ポータルのサイト間VPNをYAMAHA RTXで接続する場合、サイト間接続(S2S)ではRouteBasedの設定が必要になる。

YAMAHAが公開している資料は古く、RouteBasedでない。
Microsoftが公開している「検証済みの VPN デバイスとデバイス構成ガイド」にはYAMAHA RTXは載っていない。
ネット上で見つかる設定例は、情報が古く、RouteBasedでないか、あっても内容があやしかったり、変なことをしていたりするので、あまり当てにならない。

設定のポイントは以下の通り

- RouteBased の場合 IKEv2 を使用する。
- RTX は IKEv2 に対応したできるだけ新しいファームウエアを使用する。 
- Azure では SA の ライフタイムは 27000 秒である。
  SA のライフタイムは IKEv2 ではネゴシエーションされないので、RTX 側で 27000 秒以内に SA の更新がかかるように `ipsec ike duration` を設定する。

設定のサンプル

```
tunnel select 10
 ipsec tunnel 10
  ipsec sa policy 10 10 esp anti-replay-check=off
  ipsec ike version 10 2
  ipsec ike duration ipsec-sa 10 27000
  ipsec ike duration ike-sa 10 27000
  ipsec ike keepalive use 10 on dpd
  ipsec ike local name 10 <my-ip-address> ipv4-addr
  ipsec ike nat-traversal 10 on
  ipsec ike payload type 10 2 2
  ipsec ike pre-shared-key 10 text deadbeaf
  ipsec ike remote name 10 <azure-public-ip> ipv4-addr
```

参考

- [VPN ゲートウェイの構成設定について]
(https://docs.microsoft.com/ja-jp/azure/vpn-gateway/vpn-gateway-about-vpn-ga
teway-settings)
   https://docs.microsoft.com/ja-jp/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings

- [サイト間 VPN ゲートウェイ接続用の VPN デバイスと IPsec/IKE パラメーターについて]
(https://docs.microsoft.com/ja-jp/azure/vpn-gateway/vpn-gateway-about-vpn-devices)
  https://docs.microsoft.com/ja-jp/azure/vpn-gateway/vpn-gateway-about-vpn-devices
マルチモニタ環境とシングルモニタ環境を切り替える


<img src="https://i.gyazo.com/1192637fc97e4901e1654d75be9681b0.gif" width="500" />

メインの開発環境として MacBook Pro (13-inch, Early 2011) を使っています。

6 年目になりますが、これまでに

- メモリ 8GB → 16GB 換装
- HDD → SSD 480GB 換装
- バッテリー交換
- ファン交換

を自前でやっていて、快適に利用できています。

現行 MacBook Pro と比べると Retina ディスプレイじゃない、 Bluetooth 4 未対応、 USB 3 未対応などの劣る部分はありますが、何より自前でバッテリー・HDD・メモリの換装が可能なことで 5 年以上の長期に渡って使い続けることが出来ています。いいマシンです。

***

自宅の作業机では外部モニタ (LG 24MP76) を使ってマルチディスプレイな環境で作業、それ以外では MacBook Pro 単体のシングルディスプレイな環境での作業が基本です。

自宅内でも作業机以外での作業はシングルモニタなので、それなりの頻度でマルチモニタ環境とシングルモニタ環境の切り替えがあります。

Retina じゃない MacBook Pro 13-inch の画面は 1200 x 800 は流石に手狭に感じることがあり、シングルモニタ環境では常時立ち上げているアプリケーションをフルスクリーンモードで利用するようにしています。

Mac OS X 10.7 Lion から導入されたフルスクリーンモードは、シングルモニタ環境では便利でよく利用します。 [macOSでディスプレイ1枚で作業する技術](http://qiita.com/saboyutaka/items/d6cfd2a2b60f1a374d60) でも触れられている通り「フルスクリーンモードにするタイミングで並び順が変わる」のがちょっと厄介です。

私のようにマルチ・シングルの切り替えがそこそこある、シングルモニタ環境ではいくつかの特定のアプリケーションをフルスクリーンモードで利用したい ... できればアプリケーションの並び順も固定したいという場合、いちいち並び替えるのは面倒です。

... という訳で、私はマルチモニタ環境とシングルモニタ環境を切り替えるスクリプトを用意してターミナルからのコマンドで切り替えできるようにしています。

```AppleScript
on run argv
	if item 1 of argv is "true" then
		set needsToTurnFullscreen to true
	else
		set needsToTurnFullscreen to false
	end if
	set myList to {"Google Chrome", "Reeder", "Slack", "Mail", "Evernote"}
	if needsToTurnFullscreen is not true then
		set myList to reverse of myList
	end if
	repeat with theItem in myList
		if application theItem is running then
			tell application theItem
				activate
				set isfullscreen to false
				tell application "System Events" to tell process theItem
					set gotStatus to false
					set tryCount to 0
					repeat until gotStatus is true
						set tryCount to tryCount + 1
						try
							set isfullscreen to value of attribute "AXFullScreen" of window 1
							set gotStatus to true
						end try
						if tryCount is 45 then
							log "[applescript] failed to get full screen status."
							exit repeat
						end if
						delay 0.1
					end repeat
				end tell
				if isfullscreen is not needsToTurnFullscreen then
					tell application "System Events" to keystroke "f" using {command down, control down}
					delay 1
				end if
			end tell
		end if
	end repeat
	set theApps to {"Terminal", "iTerm2"}
	repeat with theApp in theApps
		if application theApp is running then
			tell application theApp
				activate
				delay 0.5
			end tell
		end if
	end repeat
end run

```

こんな感じの AppleScript (`make-fullscreen.scpt`) を用意します。

```AppleScript
set myList to {"Google Chrome", "Reeder", "Slack", "Mail", "Evernote"}
```

が、フルスクリーンモードで動作させたいアプリケーションリストで、基本的にこの順番で並ぶようになります。

このスクリプトに対して、 `mf` コマンド (make fullscreen の略のつもり) を以下のように `alias` 設定します。

```bash
alias mf="osascript /path/to/make-fullscreen.scpt"
```

`/path/to/` は作成した `make-fullscreen.scpt` へのパス。

これで

```bash
$ mf true
```

とすれば、リストアップしたアプリケーションがフルスクリーンモードに切り替わって、

```bash
$ mf no
```

とすれば、リストアップしたアプリケーションのフルスクリーンモードを解除します。

ターミナルからのコマンド起動を前提しているので、ターミナルへのフォーカスを維持するため、いずれの場合も最後にターミナル (Terminal もしくは iTerm) にフォーカスを戻します。

... スクリプトによる力技なので、時折うまくいかない場合もありますが、まぁ、九割以上うまくいくので、とりあえず、このまま使っています。
PDOを使用してMySQL接続メモ

##はじめに
PDOでMySQLを操作する方法の備忘録です。
## PDO接続
```php:autoload.php
spl_autoload_register(function($class) {
  $prefix = 'App\\';

  if (strpos($class, $prefix) === 0) {
    $className = substr($class, strlen($prefix));
    $classFilePath = __DIR__ . '/' . str_replace('\\', '/', $className) . '.php';

    if (file_exists($classFilePath)) {
      require $classFilePath;
    }
  }
});

```

```php:config.php
define('DB_HOST', 'localhost');
define('DB_NAME', '****');
define('DB_USERNAME', '****');
define('DB_PASSWORD', '****');
define('DB_DSN', 'mysql:host='. DB_HOST .';dbname='.DB_NAME);

require_once(__DIR__ . '/autoload.php');
```

```php:Model.php
namespace App;

class Model {
	protected $pdo;

	public function __construct() {
		try {
			$this->pdo = new \PDO(DB_DSN, DB_USERNAME, DB_PASSWORD,
				[
					\PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
					\PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
					\PDO::ATTR_EMULATE_PREPARES => false,
				]
			);
			$this->pdo->query('SET NAMES utf8');

		} catch (\PDOException $e) {
			echo $e->getMessage();
			exit;
		}
	}
}
```

```php:index.php
require_once(__DIR__ . '/config.php');
$app = new App\Model();
```
Nginx プロキシキャッシュでクッキーがついていてもキャッシュするには

## なにが危険か

Nginx のプロキシキャッシュで、レスポンスにクッキーが含まれていてキャッシュされない場合、

```
proxy_ignore_headers Set-Cookie;
```

を設定すればよい、というような説明が多く見られるのですが、これはプロキシキャッシュに `Set-Cookie` ヘッダを無視させる設定では**ありません**。

これは見た目に反して、**クッキー込みでキャッシュする**設定です。

キャッシュにより、他人のクッキーが漏れます。例えばセッション ID が漏洩します。

## 対策

`proxy_hide_header Set-Cookie;` を一緒に指定します。

```
proxy_ignore_headers Set-Cookie;
proxy_hide_header Set-Cookie;
```

## 参考記事

なかなかにヤバい話だと思うんですが、あまり記事が見つかりません。

 * https://stackoverflow.com/a/9232739/785491

に、元の回答者とは別の方が後から追記しています。

> This is important to avoid leaking cookies via the NGINX cache. 


## なぜこんなことになっているのか？

`proxy_ignore_headers` は、レスポンスヘッダの処理を止めるディレクティブです。

 * http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers

例えば、レスポンスの `Cache-Control` ヘッダを無視するために使います。

レスポンスに `Set-Cookie` ヘッダがついている場合、デフォルトだと「キャッシュを止める」という処理を行います。

この処理を無効にする、つまり**「`Set-Cookie` がついていてもキャッシュする」**のが、`proxy_ignore_headers Set-Cookie;` の効果です。

でも、この字面から受け取れる意味は、どう見ても `Set-Cookie` ヘッダを無視するというものです。Nginx は、`Set-Cookie` ヘッダ用に別のディレクティブを作るべきなのでは、と思います。
AWSでWOWZAサーバ構築に使用するAMI

CloudFormationでライブサーバ構築する際に探したので、メモ。


# Version 4.7.1 released 08/01/2017
|Region|AMI ID|
---+---
|Asia Pacific (Mumbai)|ami-6aceb605|
|EU (London)|ami-d10312b5|
|EU (Ireland)|ami-fc21ca85|
|Asia Pacific (Seoul)|ami-eda27b83|
|Asia Pacific (Tokyo)|ami-5858ba3e|
|South America (Sao Paulo)|ami-34a3d458|
|Canada (Central)|ami-6903bc0d|
|Asia Pacific (Singapore)|ami-79ed701a|
|Asia Pacific (Sydney)|ami-e7b6a984|
|EU (Frankfurt)|ami-5667cb39|
|US East (N. Virginia)|ami-12e0bf69|
|US East (Ohio)|ami-2a33134f|
|US West (N. California)|ami-ee4f678e|
|US West (Oregon)|ami-3f849e46|

# Version 4.6.0 released 04/18/2017
|Region|AMI ID|
---+---
|Asia Pacific (Mumbai)|ami-ccc9baa3|
|EU (London)|ami-61c5d105|
|EU (Ireland)|ami-34f1f552|
|Asia Pacific (Seoul)|ami-811fcdef|
|Asia Pacific (Tokyo)|ami-a6a689c1|
|South America (Sao Paulo)|ami-6ddbb901|
|Canada (Central)|ami-82d569e6|
|Asia Pacific (Singapore)|ami-de3a83bd|
|Asia Pacific (Sydney)|ami-8a343de9|
|EU (Frankfurt)|ami-c38d50ac|
|US East (N. Virginia)|ami-4cd0405a|
|US East (Ohio)|ami-9c9fbbf9|
|US West (N. California)|ami-6695b006|
|US West (Oregon)|ami-18fd6078

# Version 4.5.0 released 06/29/2016
|Region|AMI ID|
---+---
|Asia Pacific (Mumbai)|ami-6d94fe02|
|EU (Ireland)|ami-91960ce2|
|Asia Pacific (Singapore)|ami-8025f7e3|
|Asia Pacific (Sydney)|ami-c391b9a0|
|Asia Pacific (Seoul)|ami-6577bc0b|
|EU (Frankfurt)|ami-62dc370d|
|Asia Pacific (Tokyo)|ami-8e0ffeef|
|US East (N. Virginia)|ami-969f56fb|
|US East (Ohio)|ami-75356e10|
|US West (N. California)|ami-901c5bf0|
|South America (Sao Paulo)|ami-3952c755|
|US West (Oregon)|ami-8b3ff9eb|

# Version 4.4.1 released 03/18/2016
|Region|AMI ID|
---+---
|EU (Ireland)|ami-5995102a|
|Asia Pacific (Singapore)|ami-6039f203|
|Asia Pacific (Sydney)|ami-8f0b2bec|
|Asia Pacific (Seoul)|ami-08935a66|
|EU (Frankfurt)|ami-0515f26a|
|Asia Pacific (Tokyo)|ami-a0aaa1ce|
|US East (N. Virginia)|ami-68f7f402|
|US West (N. California)|ami-6a5d2f0a|
|South America (Sao Paulo)|ami-6cd95500|
|US West (Oregon)|ami-cb5db4ab|

# Version 4.3.0 released 11/05/2015
|Region|AMI ID|
---+---
|EU (Ireland)|ami-c0a77eb3|
|Asia Pacific (Singapore)|ami-4566a126|
|Asia Pacific (Sydney)|ami-51520c32|
|Asia Pacific (Seoul)|ami-269d5348|
|EU (Frankfurt)|ami-b52c3fd9|
|Asia Pacific (Tokyo)|ami-ee183f80|
|US East (N. Virginia)|ami-ae473bc4|
|US West (N. California)|ami-a65639c6|
|South America (Sao Paulo)|ami-b148f3dd|
|US West (Oregon)|ami-86e7f0e7|

# Version 4.2 released 08/10/2015
|Region|AMI ID|
---+---
|EU (Ireland)|ami-d03f74a7|
|Asia Pacific (Singapore)|ami-7c3b392e|
|Asia Pacific (Sydney)|ami-23c48219|
|EU (Frankfurt)|ami-c81b1ed5|
|Asia Pacific (Tokyo)|ami-0652e506|
|US East (N. Virginia)|ami-1370ad78|
|US West (N. California)|ami-1fb4495b|
|South America (Sao Paulo)|ami-9f77f882|
|US West (Oregon)|ami-b1686481|

----
参考：[Wowza Streaming Engine 4: Pro Edition (HVM)](https://aws.amazon.com/marketplace/pp/B012BW3WB8?qid=1499850179090&sr=0-1&ref_=srh_res_product_title)
GAE SE/pyのdatastore NDBが保存するmemcacheの場所

Google AppEngine Standard Environmentのpythonにはdatastoreのマッパーであるndbがとても便利で使いやすいです。


このライブラリは内部でキャッシングを行なってくれるため、平均取得時間の遅延を下げてくれます。
内部ではIn-Contextキャッシュとmemcacheを使ったキャッシュを併用しています。

[NDB Caching](https://cloud.google.com/appengine/docs/standard/python/ndb/cache)

# datastore更新後もmemcacheにキャッシュが残る

memcacheを使わないコンテキストでの更新やGCEや外部からの更新時に、memcacheの更新を怠ってしまうとキャッシュの削除が行われずに、いつまでも更新後のデータが取得できなくなるケースがあります。

## AppEngineからキャッシュをdisableにして保存
AppEngineから保存する時に、contextのポリシーでmemcacheへの同期をoffにして保存等してしまうと、キャッシュを利用している別のcontextと不整合が起きてしまいます。

```py:appengine_view.py
from google.appengine.ext import ndb

class Item(ndb.Model):
  name = ndb.StringProperty()

item = Item.get_by_id('item1')
item.name = 'car'
item.put()  # 通常はmemcacheにも保存されます

# キャッシュを使いたくないケースで、memcacheをcontext内でオフにしてしまう 
ctx = ndb.get_context()
ctx.set_memcache_policy(False)

item = Item.get_by_id('item1')
item.name = 'train'
item.put()  # キャッシュポリシーがOFFだとmemcacheに保存されません
```

実際に、memcacheをオフにするケースはtaskqueue等で非同期で更新していたりするケースが多いと思いますが、時々遭遇してしまいます。

## memcacheにアクセスできない環境から保存

GCEや外部など、memcacheにアクセスできない環境からdatastoreの更新や保存をした場合に、memcacheに保存されずに不整合が起きます。
[google-cloud-python](https://googlecloudplatform.github.io/google-cloud-python/)ライブラリなどを使うことが多いと思いますが、その時に遭遇することが多いです。

```py:gce.py
# google-cloud-pythonを使った場合
from google.cloud import datastore

client = datastore.Client('my-project')
item = client.get(client.key('Item', 'item1'))
item['name'] = 'airplane'
client.put(item)  # memcacheには保存されません。
```
（GCE上などからmemcacheの読み書きをする方法を知らないので、知っていたら教えてください。）

## [コンソール](https://console.cloud.google.com/datastore/entities/query)上で編集

コンソール上で編集する機能がありますが、これで編集してしまってもmemcacheには保存されない現象が起きてしまいます。
静的なconfig等をdatastoreで管理していて、それを更新した時に反映されない、といったケースに遭遇しました。

# 解決策
## memcache全体をクリア(flash)すれば解決
memcache上に保存されているものを全て削除してしまえば、このような問題は解決します。
[Memcache](https://console.cloud.google.com/appengine/memcache)のページからもフラッシュできます。

しかし、appengineからのdatastoreアクセスのパフォーマンスがその時に低下してしまうと思われるので、あまりやりたくないケースも多いですよね。

## memcacheの該当データだけ削除
該当のデータだけmemcache上から削除すれば、そのデータだけが再取得されるので、全体のパフォーマンスへの影響を減らせるかと思います。

保存しているkeyを知って入れば良いのですが、ndb内部でmemcacheへ保存するときのkeyを決めています。
具体的にはprefix + entityのkeyのハッシュです。
prefixは`ndb.Context._memcache_prefix`に定義されていますが、appengine sdk 1.9.55では`NDB9:`となっていました。

なので以下のようにすれば削除できそうです。

```py
item = Item.get_by_id('item1')

memcache.delete('{}{}'.format(ndb.Context._memcache_prefix, item.key.urlsafe()))
```


ndbライブラリ自体はappengineのpython sdkに含まれていて、github等で公開されていない？のでソースを見てみる必要があって少しわかりづらかったです。

中身もアップデートはあまりされていないみたいですし、先行きは少し不安ですね。
LODに関する覚書。

# 初めに…
JavaでLODを扱う案件がありそうなので登場キャラを覚書。

## LOD

LOD…Linked Open Data
OpenDatとして公開されているデータ同士を結び付けて誰でも自由に利用できるように公開されているもの。

LODとして認識されるためには以下の条件がある。

    1.すべてのモノ・コトには名前(URI)がついている。
    2.すべてのモノ・コトに参照できるようにHTTP URIを使用する。
    3.URIを参照したときに有用な情報を標準フォーマットで提供できること。
    4.さらに多くのモノ・コトを発見できるように他のURIを含むこと。

参考サイト：
[LODって？](http://www.fujitsu.com/jp/group/labs/resources/tech/techguide/list/lod/p04.html)

## RDF
RDF…Resource Description Framework
LODとしての条件の「3.」にある有用な情報を提供するための標準フォーマット。

「トリプル」と呼ばれる３つの要素で構成されます。

- Subject（主語）
- Predicate（述語）
- Object（目的語）

[RDF -- リソース表現のフレームワーク](http://kanzaki.com/docs/sw/rdf-model.html)
[RDF（Resource Description Framework）](http://www.asahi-net.or.jp/~ax2s-kmtn/internet/rdf/rdf-concepts.html)

## Jena
Jena…RDFを扱うためのJavaライブラリ

## SPARQL
SPARQL…SPARQL Protocol and RDF Query Language
RDFを扱うためのクエリ言語。
[WordPress]カスタムフィールドの値もプレビューする

[WordPress のカスタムフィールドをプレビュー対象にする](http://www.warna.info/archives/2502/)

上記参考ページではACFのバージョンが古いので
今現在のバージョン用にしたり
エラー出ないようにしたりしたやつ。

もちろんACFが有効になってない場合は落ちるので注意。

```php:functions.php
function get_preview_id($postId) {
	global $post;
	$previewId = 0;
	if ( isset($_GET['preview'])
			&& ($post->ID == $postId)
				&& $_GET['preview'] == true
					&&  ($postId == url_to_postid($_SERVER['REQUEST_URI']))
		) {
		$preview = wp_get_post_autosave($postId);
		if ($preview != false) { $previewId = $preview->ID; }
	}
	return $previewId;
}

add_filter('get_post_metadata', function($meta_value, $post_id, $meta_key, $single) {
	if ($preview_id = get_preview_id($post_id)) {
		if ($post_id != $preview_id) {
			$meta_value = get_post_meta($preview_id, $meta_key, $single);
		}
	}
	return $meta_value;
}, 10, 4);

add_action('wp_insert_post', function ($postId) {
	global $wpdb;
	if (wp_is_post_revision($postId)) {
		if (isset($_POST['fields']) && count($_POST['fields']) != 0) {
			foreach ($_POST['fields'] as $key => $value) {
				$field = get_field($key);
				if ( !isset($field['name']) || !isset($field['key']) ) continue;
				if (count(get_metadata('post', $postId, $field['name'], $value)) != 0) {
					update_metadata('post', $postId, $field['name'], $value);
					update_metadata('post', $postId, "_" . $field['name'], $field['key']);
				} else {
					add_metadata('post', $postId, $field['name'], $value);
					add_metadata('post', $postId, "_" . $field['name'], $field['key']);
				}
			}
		}
		do_action('save_preview_postmeta', $postId);
    }
});

```
image is being used by running containerで削除できない問題への対処



よく忘れるのでメモ&ググりやすくしておく。


## エラー内容

docker rmi しようとすると、こういうのが出る

```
Error response from daemon: conflict: unable to delete ad912aaaca3b (cannot be forced) - image is being used by running container a17e2251b82a
```


## 対処方法

以下のどちらかをやる


### 対処方法1

``` 
docker stop コンテナID
docker rmi イメージID
```


### 対処方法2

```
docker rmi -f IMAGE_ID
```



## 参考

[How to List and Delete Docker Images - Little Big Extra](http://www.littlebigextra.com/delete_docker_images/)
Unity: c# delegateというかAction? GearVR タッチパッドメモ

#GearVRのタッチパッド

使ってみようと思い、以下のサイトを参考に、
https://framesynthesis.jp/tech/unity/gearvr/

VRsamplesを確認してみた。
https://www.assetstore.unity3d.com/en/#!/content/51519

確認したスクリプトは
VRStandardAssets/Scripts/VRInput.cs
VRSampleScenes/Scripts/Examples/ ExampleTouchpad.cs

調べているとActionというものに行き当たった。
なんか関数代入してるぞ…？

以下のサイトで確認。
http://kan-kikuchi.hatenablog.com/entry/Delegate

どうやら関数を入れられる変数のようなもので、ほかのクラスに「この関数つかってー」と受け渡せるらしい。
いちいち呼び出さなくていいのは楽だし、ほかの制作時にコードを使いまわすのが楽そう。
Slackで投稿したPostのHTMLをコピるChrome拡張

## 作った理由

たくさんのPostをHTMLでまとめる必要があったんですが、開発者ツールして単にコピーすると要素が重複してたりしてダルかった。

## インストール

![icon_128x128.png](https://qiita-image-store.s3.amazonaws.com/0/84144/86d5f0a0-63f5-642a-ff16-ffaaa75acb5e.png)

https://chrome.google.com/webstore/detail/copy-slack-post/fbfgfbladjopnpagodaciocjcghacmah?hl=ja

## 使い方

投稿したPostの`Edit in new window`か`Copy link`したリンクを開いたら、この拡張のアイコンがアクティブになるのでクリックするだけ！

![Kapture 2017-07-12 at 17.23.00.gif](https://qiita-image-store.s3.amazonaws.com/0/84144/5883b08e-ed2c-f648-91a7-9e8c83a70182.gif)

```HTML
<div><div><div><h2><caret></caret>何かタイトル</h2></div></div><div><div><p><a href="http://aaaaadfsajhfajdshf.com">何かリンク</a></p></div></div><div><div><li type="bullet">何かリスト</li></div></div><div><div><li type="bullet">何かリスト</li></div></div><div><div><li type="bullet">何かリスト</li></div></div></div>
```

## リポジトリ

https://github.com/nju33/chrome-copy-slack-post
ユースケース駆動開発　ロバストネス分析編

## なぜ書くか
* ユースケースからロバストネス図を書くことによって、振る舞いが整理され実装時にあれこれ悩まなくても良い

## ロバストネス分析
* ユースケースから詳細設計（とコード）を作成するには、ユースケースをオブジェクトに関連付ける必要がある。その「関連付け」を行い分析と設計のギャップを埋める
* <font color="Red">ユースケースをオブジェクトの絵として表現したもの</font>
* ユースケースに示された振る舞いを図式化したもの
* どの振る舞いがどのクラスの責務となるかはあえて示さず、ここのクラスはグラフィカルなステレオタイプのアイコンによって表される。

## クラスステレオタイプ
* バウンダリオブジェクト（名詞）<br>　システムと外部世界との「インターフェイス」
* エンティティオブジェクト（名詞）<br>  ドメインモデル上のクラス
* コントローラ（動詞）<br>  バウンダリとエンティティの接着剤

#### 規則
* 名詞は動詞とつなぐことができる。
* 名詞を他の名詞につなぐことができない。
* 動詞は他の動詞とつなぐことができる。

これらの規則に違うことで、「名詞ー動詞ー名詞」の形式でユースケース記述を確実にパターン化できる

ロバストネス分析は、ユースケースに対する健全性のチェックになる。
 
## ガイドライン
1. ユースケース記述をロバストネス図に直接貼り付ける。<br>これにより、ユースケースに記述されている内容をオブジェクトの絵として書いているという事実が、強く認識できる。
2. ドメインモデルからエンティティクラスを取り出し、不足しているものがあれば追加する。<br>当然ながら取りこぼしたドメインクラスがあるかもしれない。発見したら追加する。
3. ロバストネス図作成時中にも、ユースケース図記述を書き直して明確にすることがある。<br>ロバストネス図を書くためには、ユースケースを順に１文づつ見ていかなければならないため。
4. 画面単位にバウンダリオブジェクトを作成し、明確な画面名をつける。
5. コントローラは、本物のコントロールオブジェクトになることがあるかもしれないということを忘れない。これらは通常、論理的なソフトウェア機能にすぎない。
6. ロバストネス図上の矢印の方向については気にしない。<br>ロバストネス図を書く目的。<br>* ユースケース記述から曖昧さを取り除く<br>* ドメインモデル内で見逃したオブジェクトの発見を助ける
7. 親のユースケースから起動するのであれば、ユースケースをロバストネス図上にドラッグ可。
8. ロバストネス図はユースケースに対する予備的な概念設計を示している。文字通りの詳細設計ではない。<br>* 設計前に要求を完全に理解することは素晴らしい<br>* 試験的な設計を行うことなしに、要求を完全に理解することは不可能<br>実際の設計を行う前に、振る舞い要求を検証する目的で概念的な設計を行う。
9. 一般的に、ロバストネス図上のバウンダリオブジェクトとエンティティクラスはシーケンス図上のオブジェクトインスタンスとなる。コントローラはシーケンス図上のメッセージとなる。
10. ロバストネス図はユースケースの「オブジェクトの絵」である。その目的はユースケースの記述とオブジェクトモデルの両方を強制的に洗練させることである。