OmniAICreator/Qiita-1.07M huggingface dataset:
PythonでDiff

#　比較用の関数を作成

```python:FileDiff.py
import difflib


def diff(file_name1, file_name2):
    f1 = open(file_name1, 'r')
    f2 = open(file_name2, 'r')
    d = difflib.Differ()
    diff = d.compare(f1.readlines(), f2.readlines())
    return '\n'.join(diff)
```

#　サンプルコード
```python
import os
import FileDiff

working_dir = r'C:\temp'
file1_name = 'diff_test01.txt'
file2_name = 'diff_test02.txt'

os.chdir(working_dir)

print(FileDiff.diff(file1_name, file2_name))
```

#　テストファイル
```text:diff_test01.txt
Mike is a good student!
Mike plays street fighters.
Mike plays soccer.
```
```text:diff_test02.txt
Mike is a good student!
Addis plays king of fighters.
Mike plays socer.
```

#　実行結果
```text
  Mike is a good student!

- Mike plays street fighters.

+ Addis plays king of fighters.

- Mike plays soccer.
?               -

+ Mike plays socer.
```

# ファイル以外のもの（各タイプを持っている内部関数など）を比較することも可能
```python
import difflib
l = dir(list)
t = dir(tuple)
d = difflib.Differ()
diff = d.compare(l, t)
print('\n'.join(diff))
```
# 実行結果
```python
  __add__
  __class__
  __contains__
  __delattr__
- __delitem__
  __dir__
  __doc__
  __eq__
  __format__
  __ge__
  __getattribute__
  __getitem__
+ __getnewargs__
  __gt__
  __hash__
- __iadd__
- __imul__
  __init__
  __init_subclass__
  __iter__
  __le__
  __len__
  __lt__
  __mul__
  __ne__
  __new__
  __reduce__
  __reduce_ex__
  __repr__
- __reversed__
  __rmul__
  __setattr__
- __setitem__
  __sizeof__
  __str__
  __subclasshook__
- append
- clear
- copy
  count
- extend
  index
- insert
- pop
- remove
- reverse
- sort
```
AWS IAMユーザーの追加(Python版)

### はじめに

AWSのユーザーIDを部署全員分作成する必要があり
コンソールからの手作業だと時間が掛かるためPython(boto3)による
自動作成プログラムを作成。

職業プログラマではないため、コードの記述が酷いのは容赦していただきたい。

---

### やりたいこと

- ExcelファイルからユーザーIDを読み込む
- 乱数によるパスワードを生成して別ExcelファイルにユーザーID/パスワードを書き込み
- boto3によりIAMユーザーの作成、グループのアタッチ

---
### 読み込むExcelファイルイメージ
![WS000000.JPG](https://qiita-image-store.s3.amazonaws.com/0/184018/f3a399f7-cb91-f963-caef-87eb7c6be702.jpeg)

書き込み後

![WS000001.JPG](https://qiita-image-store.s3.amazonaws.com/0/184018/69ffeca3-2ab3-130e-1ac1-1da9f0781457.jpeg)



---

```python:qiita.py
import boto3
import xlrd
import xlwt
import string
import random


def password_generator(size=8, chars=string.ascii_letters + string.digits):
    return ''.join(random.choice(chars) for i in range(size))
 
  
def main():
    wbr = xlrd.open_workbook('aws_create_user.xls')
    book = xlwt.Workbook()
    newSheet_1 = book.add_sheet('Users') 
    read_sheet = wbr.sheet_by_name('User')
    
    for i in range(read_sheet.nrows):
        cell = read_sheet.cell(i, 0)
    
        if cell: 
            password = password_generator()
            newSheet_1.write(i, 0, cell.value)
            newSheet_1.write(i, 1, password) 
            Create_User(cell.value, password)

    book.save('AWS_User_Account.xls')


def Create_User(User, password):
    Group = 'admin'
    client = boto3.client('iam')
    
    client.create_user(
            Path = '/',
            UserName = User
            )
    
    client.add_user_to_group(
            GroupName = Group,
            UserName = User
            )

    iam = boto3.resource('iam')    
    login_profile = iam.LoginProfile(User)
    
    login_profile.create(
            Password = password,
            PasswordResetRequired = True
            )
    
if __name__ == '__main__':
    main()
```

---
### 今後、追加する(したい)機能

- Google App Scriptで各ユーザーアカウント(メールアドレス）宛てにパスワードを通知
SikuliXで画像の認識機能を使わずにgoogle検索をしてみる

SikuliXには画像によって、クリック箇所の特定ができます。
しかし、画像をつかった場合、実際の画面の解像度やウィンドウサイズ、文字サイズによって、うまく同じ画像と認識してくれないことがあるため、その場合の回避策として画像の認識を使わない方法を記載します。

## やりたいこと
googleの検索ページで検索を実施する。

![google.png](https://qiita-image-store.s3.amazonaws.com/0/139291/67c52364-74d3-25a2-442e-2d932d0e76bd.png)



## 作成コード

```py:sikuliXSample

# CHROMEを開く
openApp("C:\Program Files (x86)\Google\Chrome\Application\chrome.exe")
# CHROMEにフォーカスする
switchApp("chrome")
sleep(3)
# 検索文字列を入力 typeでは日本語が扱えずエラーになる
paste(u"SikuliXとは")

# 検索を実行（Enter入力）
type(Key.ENTER)

# CHROMEを閉じる
# closeApp("chrome")
```

## ポイント

今回のやりたいことでは、検索欄の指定と検索ボタンの押下部分が画像認識でクリックしたくなる箇所でした。
ただ、

1. 検索欄の指定はChromeを起動すると検索欄に自動的にカーソルがあたっている
2. 検索実行はボタンをクリックしなくてもエンターキーの入力で代用できる

という２つを利用すると画像認識をなくすことができます。

今回のように最初のカーソルの位置や代用できるキー操作などを知っておくと動作を安定させることができる場合があります。
【社内LT用資料転載】そうだゴルフをしよう⛳

## はじめに
社内LTシリーズ第二弾です。
第一弾： [PHP7移行概要](https://qiita.com/go12lim/items/8c2823d212a29f16f716)
第二弾： [そうだゴルフをしよう⛳](https://qiita.com/go12lim/items/be1f358a9d930ba312a0)
第三弾： [純粋関数](https://qiita.com/hayashi-ay/items/f6999f6b111bd86efd97)

---

LTは2018年3月11日に行い資料はその時点での情報となります。
「ゴルフに必要な用具を揃えよう」から下が社内LTに用いた資料となります。

---
![golf.png](https://qiita-image-store.s3.amazonaws.com/0/215694/09d26d72-db90-fa98-5c28-56b69265087b.png)

---

## ゴルフに必要な用具を揃えよう
ゴルフに必要なものといえば。。。

---

![golf-club.jpg](https://qiita-image-store.s3.amazonaws.com/0/215694/51d46e3c-d8d4-2082-3807-6ecca7085ff2.jpeg)

---

クラブだけでもドライバー・アイアン・パターなど色々な種類があって覚えるのが大変ですし、安い中古のセットでも数万円はします。

その他にゴルフシューズ・グローブ・キャディーバッグなども揃える必要があります。

---

![kaiji1.jpg](https://qiita-image-store.s3.amazonaws.com/0/215694/496ae53e-2593-ae74-4bec-ef678e96b8fb.jpeg)

---

ご心配無用。
今回ご紹介するゴルフではMacのターミナルから以下のコマンドを入力するだけで準備完了です。


```shell
vim
```
---

## コースを回る前に打ちっぱなしに行こう

ただ、いきなりラウンドを回るのは不安ですよね。
実際にゴルフ場に行く前に打ちっぱなしで練習をしましょう。

ラウンドを回るよりは安上がりですが、都内ですと1回平均して2~4000円ほどは掛かってしまいます。

---

![kaiji2.jpeg](https://qiita-image-store.s3.amazonaws.com/0/215694/47d5752f-8422-2b77-37a0-99284b1c61f7.jpeg)

---

ご心配無用。
今回ご紹介するゴルフではMacのターミナルから以下のコマンドを入力するだけで練習ができます。


```shell
vimtutor
```
---
## ゴルフ場の会員登録をしよう

平日だと安いところだと5000円ほどで回れますが、土日祝日だと1万円はします。
また、立地にも左右され関東近郊だとそれよりさらに高くなります。
それに往復の交通費なども別に掛かってきます。

---

![kaiji3.jpeg](https://qiita-image-store.s3.amazonaws.com/0/215694/bba17551-9d20-15a6-8d5e-b7a538bd3689.jpeg)

---

ご心配無用。
今回ご紹介するゴルフではTwitterアカウントさえあればコースを廻ることができます。

[VimGolf](http://www.vimgolf.com/)

---

## 実際にコースを回ってみよう

前置きが長くなりましたが、実際にコースを回ってみましょう。
VimGolfではスタートのテキストとゴールのテキストが与えられ、ゴールに至るまでのキーストロークを競います。

---

### 1ラウンド目： [I forgot quotes](http://www.vimgolf.com/challenges/5462e3f41198b80002512673)

スタート地点

```
foo = a
      ab
      abc
```


ゴール地点

```
foo = "a"
      "ab"
      "abc"
```

---
### 2ラウンド目： [One number per line](http://www.vimgolf.com/challenges/56fb2e75ccffcc0009026473)

スタート地点

```
- One number per line -
-----------------------
2,3,5,7,
11,13,17,
19,23,29,
```

ゴール地点

```
2
3
5
7
11
13
17
19
23
29
```
【合格】AWS ソリューションアーキテクト受験奮闘記 (2019年)

## はじめに
- AWSのソリューションアーキテクトを受験しようと思い立ったのが2019年1月
- 今年度中の取得を目指して勉強を開始しました

## 私
- AWSを触り始めたのは2年前ですが、AWS関連で携わった案件はまだ1つ
- アプリ保守、プロマネ、インフラ設計・保守を薄ーくやってきてます

## 勉強開始
#### 1. 参考書を読む (1週間)
「AWS認定 ソリューションアーキテクト-アソシエイト 教科書」を読みました。
わかりやすいうえに、よくまとまっています。まずは1週軽く流し読みしました。

#### 2. 問題 をひたすら解く (1ヶ月半)
参考書を読んで何となくわかった気になったので、AWS WEB問題集 のゴールドプランに登録。問題数が豊富なので、問題解く➔間違える➔調べる➔理解する を繰り返さないと知識が定着しない私にとってはありがたかったです。

#### 3. 模擬試験を受けてみる
AWS WEB問題集 や 参考書 の例題とは違い、文章問題が多くて戸惑いました。
思ったよりはいい結果が出せたけど、勘で解いた問題もあったのでラッキーだっただけかも。(このラッキーを本番で出したい)

- 総合スコア:  92%
- トピックレベルスコア:
  - 1.0  Design Resilient Architectures: 100%
  - 2.0  Define Performant Architectures: 85%
  - 3.0  Specify Secure Applications and Architectures: 100%
  - 4.0  Design Cost-Optimized Architectures: 50%
  - 5.0  Define Operationally-Excellent Architectures: 100%

#### 4. 参考書を読む(1週間)
復習がてら、最初に読んだ参考書を再度読みました。
なんとなく流し読みしていた部分が理解できて、すっきりしたところも。

## 最初の受験（できず）
久々のテストセンター。懐かしい、この独特の雰囲気。
さて受付するぞ、と思ったらアクシデントが。
会社で試験を予約したため、うっかり旧姓で登録しておりました。あああ・・・
当日は必要な身分証明書がそろっていないとのことで、受験できず。
受験費 16,000円も返ってこず。自業自得ですがもう最悪です。
泣きそうな気持になりながら、何もせず帰りました。
こんなアホこと普通ないと思いますが、みなさま気を付けて・・・

## 再受験（できた）
2019/4/1 に再受験しました。結果は783点！
ボーダーが720点とのことなので、結構ぎりぎりだったようです。
パフォーマンスに関する知識が弱いとのこと。もう一度学びなおす必要ありですね…
![image.png](https://qiita-image-store.s3.amazonaws.com/0/375411/29a77c28-ef3b-bfba-61c8-178f17dc960e.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/375411/b2610971-ae8a-0921-d6e5-ad7a9a19a55c.png)

## まとめ
WEBの問題集や参考書に載っている例題よりも難易度は高く感じました。
システムになれるためにも、事前に模試を受けておくことをお勧めします。(ちょっとだけ癖があります)

あと、会社で旧姓を名乗っている状態でAWSの資格試験申し込みをする場合は、
登録時の名前と身分証明書が一致するように気を付けましょう…
失った16200円は返ってきませんが、社会勉強代だと思って次に活かします涙
ドットインストールでのRuby on Railsでの備忘録

#ブラウザにアクセスする時
Active Recordのエラーが出る場合
作成したappのGemfileを開き
`gem 'sqlite3' `
の行を
`gem 'sqlite3', '~> 1.3.6`
に変更して保存を行う。
その後
`bundle install`
とし一度webサーバーを終了させてもう一度立ち上げる。
golangで電卓Webアプリケーションを作ってみた

# はじめに
Goを用いて簡単な__【電卓Webアプリケーション】__を作成したので、アウトプットしたいと思います！

# アプリ画面
<img width="390" alt="スクリーンショット 2019-03-11 15.28.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/343290/4e9ce89c-99a0-a340-e53f-555d1257ddf3.png">

# コード

```golang
package main

import (
	"fmt"
	"html"
	"math/big"
	"net/http"
)

// ServerHTTPメソッド用の構造体型

type Server struct{}

// httpリクエストを受け取るメソッド

func (Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// フォームの入力値を取得
	left := r.FormValue("left")
	right := r.FormValue("right")
	op := r.FormValue("op") //演算子（ラジオボタンの値）

	// 文字列を整数に変換
	leftInt := &big.Int{}
	rightInt := &big.Int{}

	_, leftOK := leftInt.SetString(left, 10)
	_, rightOK := rightInt.SetString(right, 10)

	// 四則演算の処理
	// 変換エラーがなければ、演算子に従って計算
	var result string
	if leftOK && rightOK {
		resultInt := &big.Int{}
		// 演算子ごとに分岐
		switch op {
		case "add":
			resultInt.Add(leftInt, rightInt)
		case "sub":
			resultInt.Sub(leftInt, rightInt)
		case "multi":
			resultInt.Mul(leftInt, rightInt)
		case "div":
			resultInt.Div(leftInt, rightInt)
		}
		result = resultInt.String()
	}

	//HTMLの文字列
	h := `
			<html>
				<head>
					<title>電卓アプリ</title>
				</head>
				<body>
					<form action ="/" method="post">
						左項目：<input type="text" name="left"><br>
						右項目：<input type="text" name="right"><br>
						演算子：
						<input type="radio" name="op" value="add" checked> +
						<input type="radio" name="op" value="sub" > -
						<input type="radio" name="op" value="multi" > ×
						<input type="radio" name="op" value="div" > ÷
						<br><input type="submit" name="送信"><hr>

						[フォームの入力値]<br>
						左項目：` + html.EscapeString(left) + `<br>
						右項目：` + html.EscapeString(right) + `<br>
						演算子：` + html.EscapeString(op) + `<br>
						演算結果：` + html.EscapeString(result) + `<br>
					</form>
				</body>
			</html>
		`
	// クライアント（ブラウザ）にHTMLを送信
	fmt.Fprint(w, h)
}

func main() {
	// Webサーバを起動
	http.ListenAndServe(":4020", Server{})
}
```

# リファレンス
詳しくは[こちら](https://www.amazon.co.jp/dp/B01KFFS1CI/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)に載っています！
![51J2rfJA5uL.jpg](https://qiita-image-store.s3.amazonaws.com/0/343290/5ef39565-2b3c-8fa1-db07-af9bbbb2c86b.jpeg)
【OracleDB】BLOBデータをVARCHAR2にキャストして内容確認

#OracleDBでBLOBデータをVARCHAR2にキャストして内容確認
##やりたいこと
桁数が不明なデータを`BLOB`や`CLOB`で受け取った際にデータを確認しようとしても、バイナリデータで保存されているため、そのままでは内容がわからない…
そんなときには`DBMS_LOB.SUBSTR`と`UTL_RAW.CAST_TO_VARCHAR2`を使用して内容確認を行います。

BLOB項目へのデータの登録方法は下記参照
[【OracleDB】BLOBデータにINSERT](https://qiita.com/t-kikuchi/items/b84647501e68ab927c99)

##1. BLOBの抽出
BLOBデータを適当な桁数を指定し、バイナリデータの抽出を行います。

```sql:blob_cast1.sql
SELECT 
    DBMS_LOB.SUBSTR(test_column,3000,1)  -- BLOBの抽出
FROM test_table
```

##2. VARCHAR2へのキャスト
抽出したバイナリデータをVARCHAR2型へキャストして内容を確認します。

```sql:blob_cast2.sql
SELECT 
    UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(test_column,3000,1))   -- VARCHAR2へのキャスト
FROM test_table
```
Google Cloud Endpointsのエラーレスポンスをまとめてみた

# はじめに

Google Cloud Endpointsを使うと、サーバーのうちOpenAPI形式で書いた通りのAPIのみを公開することができます。

Cloud Endpointsの層で不正なリクエストと判定された場合には、指定のフォーマットでレスポンスが返ってくるようで、種類がいくつかあったので自分が遭遇したエラーをまとめました。

見た目を変えたい場合は、以下のレスポンスを参考にフロントの制御を行うとよいかと思います。

※ なお、裏側のサーバーはGoogle App Engineで作っているため、別のサービスで作った場合はまた別のレスポンス形式になるかもしれません。

## エンドポイント未定義の場合

ドキュメントに書かれていないエンドポイントを叩いた場合に発生します。

```
{
    "code": 5,
    "message": "Method does not exist.",
    "details": [
        {
            "@type": "type.googleapis.com/google.rpc.DebugInfo",
            "stackEntries": [],
            "detail": "service_control"
        }
    ]
}
```

# APIキーがない場合

Cloud Endpointsでは認証方式としてAPIキーを設定でき、APIキーが含まれていないリクエストが来ると以下のレスポンスを返すようです。

```
{
    "code": 16,
    "message": "Method doesn't allow unregistered callers (callers without established identity). Please use API Key or other form of API consumer identity to call this API.",
    "details": [
        {
            "@type": "type.googleapis.com/google.rpc.DebugInfo",
            "stackEntries": [],
            "detail": "service_control"
        }
    ]
}
```

# APIキーが間違っている場合

こちらは認証失敗時のエラーです。

```
{
    "code": 3,
    "message": "API key not valid. Please pass a valid API key.",
    "details": [
        {
            "@type": "type.googleapis.com/google.rpc.DebugInfo",
            "stackEntries": [],
            "detail": "service_control"
        }
    ]
}
```

# APIキーの権限がない場合

Cloud Endpointsのサービスに対してAPIのキーの権限がない場合に出るようです。

```
{
    "code": 13,
    "message": "Request blocked due to unsupported error code: 122",
    "details": [
        {
            "@type": "type.googleapis.com/google.rpc.DebugInfo",
            "stackEntries": [],
            "detail": "service_control"
        }
    ]
}
```

GCPの「APIとサービス」の機能でAPIキーを発行した際、APIキーの制限を設定する箇所でCloud Endpointsが接続するバックエンド（今回はApp Engine)に対して権限がないと発生するようです。

この場合はAPIの制限に対して、バックエンドとなるサービスを追加することで解決できるようになるようです。

<img width="674" alt="スクリーンショット 2019-03-11 15.18.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/5964/7688ae22-5742-c77c-9693-00ef29f0a36b.png">

# まとめ

ということでCloud Endpointsのエラーレスポンスのまとめでした。

いろいろあってCloud Endpointをサービスで使わないことにはなったのですが、今後も検証していく予定ではあるので新たなエラーを見つけたら更新したいと思います。
<p>と<div>をなぜ分けるのか

プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。
#初心者から見た、ラクしたいと考えたこと
初め、「＜p＞と＜div＞や＜li＞、＜h＞を全て同じに＜a＞のようにすれば、気にすることなくコードを書くことができるのに。」と思っていました。
##＜p＞の役割
＜p＞は、「paragragh（段落）」の意味です。
また、、＜p＞は、HTMLにおいてブロック要素であるので、１つの塊と考えることができる。
##＜div＞の役割
＜div＞は、「division（仕切り）」の意味です。
また、＜div＞は、HTMLにおいて汎用ブロック要素であるので、同じく１つの塊と考えることができる。
##＜p＞と＜div＞の違い
コードによりできた結果の違いがある。
それは、行間の違いです。
＜p＞の場合
改行され、一行の空白がある

```HTML
<p>今日</p>;
<p>明日</p>;
<p>明後日</p>;
```
結果：今日
　　　
　　　明日

　　　明後日

＜div＞の場合
改行されるのみ

```HTML
<div>今日</div>;
<div>明日</div>;
<div>明後日</div>;
```
結果：今日
　　　明日
　　　明後日
#まとめ
＜p＞と＜div＞の違いについて理解できました。
そして、プログラミングを1週間勉強すると、エラーの発見やタグの数を確認する際に、区別することは大切であると気づきました。
これからのコーディングに生かしていきます。
MySQLでデータベースをrenameする方法

2通りの方法があります

1. mysqldumpを使う方法
2. table renameを使う方法

## mysqldumpを使う方法

データ量が気にならないのであればこれを使うのが最も単純です

```sql:mysqldumpを使う方法
$ mysqldump -uuser old_database -p -hhost > old_database.dump
$ mysqladmin -uuser -p -hhost create new_database
$ mysql -uuser new_database -p -hhost < old_database.dump
$ mysql -uuser -p -hhost drop old_database
```

参考：https://weblabo.oscasierra.net/mysql-database-copy/


## table renameを使う方法
データ量が大きい場合はmysqldumpではなく、テーブルをrenameする方法がおすすめです。

```sql:tableをrenameする方法
mysql> rename table old_database.table to new_database.table;
```

old_database内の全テーブルのコマンドを作るのが大変な場合、下記記事のコマンド作成方法を参考にしてください
参考：https://qiita.com/whisper/items/06add22b692a25bd19b5

### renameが使えないテーブルだった場合
これはしょうがないです。その場合はあきらめてmysqldumpしてください。(自分はそうしました)

例えば古いバージョンのMySQLでストレージエンジンをmroongaでラッパーモードにしている場合、rename(alter table全般？)が使えません。



どなたかもっといい方法がありましたら教えてください。
Azure で仮想ネットワークとか作ると勝手に作成される Network Watcher RG について

# Azure で仮想ネットワークとか作ると勝手に作成される Network Watcher RG について

## はじめに
最近 Azure で、仮想ネットワークを初めて作成した場合に **NetworkWatcherRG** なるものが勝手に作成されるようになりましたが、
何に使われてるのか、課金されちゃったりしているのか、消してもいいのか、
など色々疑問に思う人も多いかと思いますので、まとめてみます。

## 結論から
* Azure で提供されている **Network Watcher** という機能で使われるリソースグループ
* 最近になって、仮想ネットワーク作成時に自動で作成されるようになった
* Network Watcher を使わないなら消してしまっても可
* このリソースグループ自体に課金は発生しない
* リソースグループ名が気に食わないなら別のリソースグループへの移動も可

## そもそも ネットワーク ウォッチャーとは

まずはドキュメントから。

Azure Network Watcher とは
https://docs.microsoft.com/ja-jp/azure/network-watcher/network-watcher-monitoring-overview

> Azure Network Watcher は、
Azure 仮想ネットワーク内のリソースの監視、診断、メトリックの表示、ログの有効化または無効化を行うツールを提供します。

要するに、Azure 内のネットワーク系の監視ツールの総称のことを Network Watcher といいます。
Network Watcher で提供されている機能としては、

* 接続モニター (VM 間の死活監視サービス)
* ネットワーク パフォーマンス モニター (VM 間のレイテンシーや、ExpressRoute 経由での通信のレイテンシ、損失などが計測できるサービス)
* トラフィック分析 (トラフィックを様々な方法で可視化できるサービス)

などがあります。

## NetworkWatcherRG について

NetworkWatcher は、サブスクリプションに対して、
リージョン毎に有効 / 無効を設定しますが、
今までは、あるリージョンでNetworkWatcher を有効化した場合に、
NetworkWatcherRG というリソースグループが作成され、
そのリソースグループ内に、**NetworkWatcher_<リージョン名>** など、
リージョンに対応した NetworkWatcher 用のリソースが作成されていました。

が、最近になって、あるリージョンで仮想ネットワークを作成すると、
自動でそのリージョンの NetworkWatcher が有効化される
(つまり、NetworkWatcherRG が作成される) ようになったみたいです。

ちなみに、接続モニターとか、接続モニター用のアラートとか設定すると、
NetworkWatcherRG内に接続モニター用のリソースが作成されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/361213/4508ca25-2efe-b2c4-e610-78e65c41d45a.png)

## 作成されるタイミング
この NetworkWatcherRG、仮想ネットワークの作成時もそうですが、
ドキュメントによると仮想ネットワークの更新時にも作成されることがあるようです。
※ 試しにNetworkWatcherRG 削除後にサービスエンドポイントを追加してみたら、再作成されてました。

Azure Network Watcher のインスタンスの作成
https://docs.microsoft.com/ja-jp/azure/network-watcher/network-watcher-create

> サブスクリプションで仮想ネットワークを作成したり更新したりすると、お使いの Virtual Network のリージョンで Network Watcher が自動的に有効になります。 Network Watcher は自動的に有効化され、リソースや関連する料金が影響を受けることはありません。

## NetworkWatcherRG リソースの移動方法

ネットワークウォッチャーは使いたいが NetworkWatcherRG が作成されるのはなんか気持ち悪い...
といったことがあるかと思いますが (僕は思いました)、
普通に他のリソースと同じように別のリソースグループに移動出来ます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/361213/b2fa0839-450b-f72b-e78f-b8e904d91e0b.png)

※ NetworkWatcher 用リソースを他のリソースグループに移動したとしても、
別リージョンの仮想ネットワーク作成時にまた NetworkWatcherRG が復活します。


## 自動有効化のオプトアウトについて
最近では、仮想ネットワーク作成時に自動で NetworkWatcher が有効化されるようになったと前述しましたが、
この自動有効化を無効化することも出来るみたいです。

Network Watcher の自動有効化のオプトアウト
https://docs.microsoft.com/ja-jp/azure/network-watcher/network-watcher-create#opt-out-of-network-watcher-automatic-enablement
> Network Watcher の自動有効化のオプトアウトは、永続的な変更です。 一度オプトアウトすると、サポートに連絡しない限りオプトインできなくなります

ただドキュメントにも書いてあるように、一度無効化すると、サポートに連絡しない限り再有効化することはできないみたいですね。
別に NetworkWatcherRG 自体には害はないので、よっぽどの理由がない限りはオプトアウトはしないほうが良いように思います。


## 終わりに

というわけでまとめると、
NetworkWatcherRG リソースグループは、
NetworkWatcher という機能で使われるリソースグループであり、
仮想ネットワーク作成時に自動で作成されるものになります。

邪魔なら別のリソースグループに移動することも出来ますし、
NetworkWatcher を使わないなら削除してしまっても問題はないです。
(仮想ネットワークを更新したらまた復活しますが。。。)
あれ？Mac使い始めたけど画面分割したいなあ

# はじめに
ずっと欲しかったMacBook Proを最近ついに購入しました．Macビギナーです．
近頃はMacになれる事とMacの環境構築を頑張っています．
今までは，Windows・Ubuntuしか使ったことがなかったので，それらでできていたけどできないことが気になってしまいます．

本記事では，Windowsにおける`Win+Left/Right`，Ubuntuにおける`Super(+Ctrl)+Left/Right`でできていた画面分割(Split)をMacでも使えるようにする手順とその設定を紹介します．

# ShiftIt
このアプリを使えば画面分割（上下左右），最大化，ウィンドウの拡大縮小，フルスクリーンなどのウィンドウに関するショートカットを設定することができます．

## インストール方法
[こちら](https://github.com/fikovnik/ShiftIt/releases)から最新版のzipをダウンロードします．

<img width="998" alt="スクリーンショット 2019-03-11 0.32.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/282145/b5e5ea0e-0b6e-4f21-cb44-c5dff26d7d4f.png">

Finderでダブルクリックすることでzipファイルを解凍します．
解凍が完了したら，Shiftlt.appをダブルクリックします．途中で出てくるものは基本的にOKしてしまって大丈夫です．
この際，`Shiftlt.appを開けません`などと出てくると思いますので，
システム環境設定＞セキュリティとプライバシー＞アクセシビリティ
の許可するアプリケーションにShiftltを追加します．以下のような画面になっていたらOKです．
<img width="780" alt="スクリーンショット 2019-03-11 15.11.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/282145/e3027c34-e3a1-7ed6-3f51-224e254320ff.png">

インストールが完了したら，Finderを用いてShiftlt.appを`~/Downloads`から`~/Applications`へ移動します．
ショートカットキーの確認には，Macのデスクトップの右上にある
<img width="30" alt="スクリーンショット 2019-03-11 15.07.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/282145/f407d564-018e-795b-b88d-9cdf781cc1c6.png">
アイコンをクリックして出てくる
<img width="234" alt="スクリーンショット 2019-03-11 15.12.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/282145/925c1526-dbde-0b89-505a-688df441c1e9.png">
をみると良いです．ショートカットを変更したい場合には，上の画像の環境設定をクリックしてそれぞれにキーを割り当てます．私の設定は以下になっています．

<img width="520" alt="スクリーンショット 2019-03-11 15.04.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/282145/9f6d5f74-5743-8146-6c8f-eff7c5be1e19.png">

使わないであろうショートカットは消してしまいました．

# おわりに
Macを使い始めて半年たった今でもShiftltは使用しています。
しかし、画面分割の目的で使うのではなく、`Shift+Enter`の仮想デスクトップのオンオフの機能を主に用いています。
Electron+React+Typescriptの開発環境を作る

Electron+React+Typescriptで何かWebアプリを作ってみたいという人のために、Electronで開発を始めるまでの過程を書いていこうと思います。

※2019/09/25追記
create-react-appがTypescriptをサポートしたことによってこのQiitaの記事は非推奨になったので最新の開発環境を作りたい場合は[Electron+React+Typescriptの開発環境を作る・改](https://qiita.com/butachin/items/4ef8c6720999a3c8fe73)をみてください。

# 事前準備
[create-react-app](https://github.com/facebook/create-react-app)をグローバルにインストールする。

```
npm install -g create-react-app
```

# アプリ起動まで
## アプリ作成
今回はTypescriptを使用するために、[react-scripts-ts](https://github.com/wmonk/create-react-app-typescript)を使用しアプリを作成する。

```
npx create-react-app --scripts-version=react-scripts-ts [アプリ名]
```

※Could not create a project called "[アプリ名]" because of npm naming restrictions:
  *  name can no longer contain capital letters
 このようなエラーが出た場合はアプリ名が悪いようなので先頭を小文字にするなどしてみるとエラーがなくなるはずです！

## Electronの設定
[electron](https://github.com/electron/electron)と[foreman](https://github.com/ddollar/foreman)をインストールする。

```
yarn add --dev electron
yarn add foreman
```

https://github.com/csepulv/electron-with-create-react-app 内の下記ファイルを同じ場所にコピーする

```
Procfile
src/electron-starter.js
src/electron-wait-react.js
```

package.jsonを編集する

```package.json
{
 .
 .
  "homepage": "./",
  "main": "src/electron-starter.js",
  "scripts": {
    .
    .
    "electron": "node_modules/.bin/electron .",
    "dev" : "nf start -p 3000"
  }
}
```
tslint.jsonに下記の"rules"を追加する

```tslint.json
{
  "extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
  "linterOptions": {
    "exclude": [
      "config/**/*.js",
      "node_modules/**/*.ts",
      "coverage/lcov-report/*.js"
    ]
  },
  "rules": {
    "no-console": false,
    "ordered-imports": false,
    "object-literal-sort-keys": false,
    "member-ordering": true,
    "strict-boolean-expressions": false,
    "jsx-boolean-value": false
  },
  "jsRules": {
    "no-console": false
  }
}
```
# アプリ起動
```
yarn dev
```

# 最後に
今回は環境構築だけでしたが、これを用いてお天気アプリの作成も行いました。それに関しては[Electron+React+Typescriptでお天気アプリを作る](https://qiita.com/butachin/items/13f793c9136b3ab4d44d)に書きました。
メモ程度ですが参考にしてください。

# 参考
[React + TypeScript (+ Electron)でアプリを書き始めるときにやってること](https://qiita.com/azu/items/a149501ca1b5864000a3)
conoha gmail メールアドレス追加

conohaのメールサーバーを使って

・独自ドメインメールアドレス info@hoge.com に来たメール を gmailへ転送
・gmail で info@hoge.com へ送信できるようにする

DNS設定に多少時間かかるかも。



# 1 メールサーバーの情報を見て情報をメモ

![1.png](https://qiita-image-store.s3.amazonaws.com/0/31338/90f279ee-b8a9-821d-3df6-879e0c1a3a5a.png)



# 2 DKIMも 有効にし、 DNSレコードをメモ

![2.png](https://qiita-image-store.s3.amazonaws.com/0/31338/d1aa19b4-c592-163c-7340-5835103735c7.png)

![3.png](https://qiita-image-store.s3.amazonaws.com/0/31338/41b58aeb-0908-558e-fb9f-3dbf3219fde4.png)



# 3 上記の情報をDNSにそれぞれ登録

2つのレコードを下記のように作成する必要があります。
1つ目: タイプは「MX」、値は「MXレコード設定値」
2つ目: タイプは「TXT」、値は「SPFレコード設定値」
DKIMは TXT

![4.png](https://qiita-image-store.s3.amazonaws.com/0/31338/b7b6f085-ff52-16fb-96a0-94b217defe3d.png)


# 4 転送設定

yahoo と gmail 両方に転送しておく。
でないと自分の場合はなぜか届かないので。

また、このSMTPサーバーもメモっておく。

![5.png](https://qiita-image-store.s3.amazonaws.com/0/31338/e8b7803f-c0e3-b27c-c4e7-302ff12ffd10.png)


#gmail

設定 > インポート > 他のメールアドレスを追加をクリック

![6.png](https://qiita-image-store.s3.amazonaws.com/0/31338/6fc2552d-255d-c297-4ced-dd541f1fb5d7.png)

これでメールが届くようになる。
復元ポイントの作成手順(Let's Note)

## Let's Note (Windows 10)の復元ポイント作成手順

1. タスクバーの「ここに入力して検索」の窓に、「復元ポイントの作成」と入力する
2. 「システムの保護」タブが表示されるため、「構成」をクリックする
3. 「システム保護対象」の「システムの保護を有効にする」にチェックを入れ「OK」をクリックする
4. 「作成」をクリックする。

※ CF-SZ6 より、上記「3」の手順が必要になった
3日目(2)：HTTPメソッドとCRUDとSQL

授業3日目(2)の分を下書きのまま放置していました。

#Webページが表示される流れのごく一部
![HTTPmethod図.jpg](https://qiita-image-store.s3.amazonaws.com/0/294402/42488d5e-582d-9f31-eaf5-97857487587d.jpeg)



1.ブラウザでURLにアクセスして、DNSサーバーにIPを問い合わせ、DNSサーバーがIPを返す
2.htmlなどの情報をやり取りするためのProtocol Cliantがサーバー上のquery(何を)と
　Httpメソッド(行いたい処理）をサーバーにHttpリクエストする。
3.サーバーがレスポンス
#そもそもHTTPとは
- Hypertext Transfer Protocolの略
- HTMLとXMLによるHypertextの送信を主に、その他様々なデータのやり取りができる。
- リクエスト-レスポンス型のプロトコルで、
    - webブラウザ「あれが欲しいんだが。これをしてくれ」
    - (※あれ＝query、これをして＝http method)
    - webサーバ「おかのした、ほらよっ」


#HTTPメソッドの内訳とSQLの関係、CRUDとRESTful

|  HTTPメソッド  | 内容 | CRUD  |MYSql| MySQL|
|:-:|:-:|:-:|:-:|:-:|
|  GET 　| リソース取得 | CREATE  | 生成| INSERT |
|  POST  | リソースデータ追加、小リソース作成 | READ | 読み取り | SELECT |
|  PUT/PATCH  | リソース更新作成  | UPDATE  | 更新 | UPDATE |
|  DELETE  | リソース削除 | DELETE  | 削除 | DELETE |

下もHttpメソッドであるが、今の自分には不要なので、表を分割した

| HTTPメソッド | 内容 |
|:-:|:-:|
| HEAD | リソースのヘッダ(メタデータ取得)  |
| OPTION | リソースがサポートしているメソッドの取得  |
| TRACE | プロキシ動作の確保  |
| CONNECT | プロキシ動作のトンネル接続への変更  |
##CRUDとは
- CREATE, READ, UPDATE, DELETEの4つの単語のイニシャルを並べたもの
- 上４つは、**殆ど全てのコンピュータソフトが持つ永続性の4つの基本機能**
- （情報の参照。検索。更新。削除）
    - [ここでいう永続性とは専門的な意味合いなので、wikiだけでも読むと面白い](https://ja.wikipedia.org/wiki/%E6%B0%B8%E7%B6%9A%E6%80%A7)

##RESTとは
- 分散ハイパーメディアシステムのためのソフトウェアアーキテクチャのスタイルのひとつ。
- HTTP規格の主要著者のロイ・フィールディングが2000年に初めて提唱
- その論文HP　[Architectural Styles and
the Design of Network-based Software Architectures](https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm)

> [wikipedia「Representational State Transfer」より](https://ja.wikipedia.org/wiki/Representational_State_Transfer)
>> フィールディングのRESTアーキテクチャスタイルの原則に合わせたWebサービスシステム。
>> 遠隔手続き呼出し(RPC)スタイルに合わせた簡易なXML + HTTPインタフェースを採用したシステム

`CRUDやRESTという考え方があるという事だけ、今は覚えておきたい。`
PHPで定数のリストが定義されたクラスからランダムに定数を取得する

テスト用のデータを作成する際に、ランダムにカテゴリーが入るようにしたかったので、どのようにクラスから定義を取得すれば良いのか調べました。

## ファイル構成
定数が定義されているクラス

```php
<?php

namespace App\Constants;

class Categories
{
    const Category1 = 'category1';
    const Category2 = 'category2';
    const Category3 = 'category3';
}
```

テストデータを作成する呼び出し元(適当)

```php
<?php

namespace App

class HogeSeeder
{
	public function hoge()
	{
		$reflect = new ReflectionClass('App\Constants\Categories');
		$categories = array_values($reflect->getConstants());

		// これでランダムに取得できるので、データ作成時にこのカテゴリーを使用する
		var_dump($categories[random_int(0, count($categories) - 1)]);
	}
}
```

### 解説
reflectionクラスを使用することで、対象クラスのあれこれを取得できます。
[ReflectionClass クラス](http://php.net/manual/ja/class.reflectionclass.php)

reflectionクラスのgetConstantsを使用することで、そのクラスに定義されている定数を取得を配列として取得できました。

```php
dump($reflect->getConstants());

array:3 [
  "CATEGORY1" => "inappropriate category 1"
  "CATEGORY2" => "inappropriate category 2"
  "CATEGORY3" => "inappropriate category 3"
]
```

`array_values` で数値添字にした上でrandom_intでランダムに数値を取得することでランダムにカテゴリーを取得できました。

```php
dump(array_values($reflect->getConstants()));

array:3 [
  0 => "inappropriate category 1"
  1 => "inappropriate category 2"
  2 => "inappropriate category 3"
]
```
Linux で Maya 2018/2019 + XGen IG hair を modifier/deformer と連携すると OpenCL で segmentation fault するバグがある

Linux(CentOS 7) で Maya 2018u5 /2019 で XGen IG hair を modifier/deformer と連携させているときに, playback を何度かさせると XGen + OpenCL のバグによりクラッシュすることがわかりましたのでご注意ください.

以下のようなエラーとだいたい同じです.

https://forums.autodesk.com/t5/maya-forum/xgen-interactive-groom-crash-opencl-error/td-p/7096492

* NVIDA 418 driver
* AMD amdgpu-pro 18.10(OpenGL) + ROCm 2.1(OpenCL) 

両方で発生を確認しました.

メモリの確保に失敗, もしくは out-of-bounds アクセスのようです.

## workaround

hide するととりあえず play back できますが, deformer などと連携している場合, unhide すると deform しなくなったりします.

毛量が少ないのであれば, 一旦 XGen IG を Alembic curves(nurbs)に変換するのがよいかもしれません.

原理的には Windows でも発生しそうであるが...? CLGL 連携周りっぽいのでそこは Windows ドライバだとうまくやっていて動いているのかもしれません.

## TODO

* CPU OpenCL に fallback させる方法を探してみる(OClgrind を試したが, やはり CLGL 連携しているようで, OpenGL が動かなくなりダメであった)
* XGen は開発が止まっている感があるので, XGen を使わない hair にする(e.g. Ornatrix/HairFarm/Yeti など)
* 自作 hair 描画/sim ツール作りたいので, 優秀な hair sim 若人を探す旅に出たい.
dockerメモ

自分用のメモ:writing_hand_tone2:

# インストール

https://docs.docker.com/install/linux/docker-ce/centos/
$ sudo docker run hello-world まで確認

# イメージの一覧

```
$ docker images
```

# コンテナの操作

## コンテナの一覧を表示する

```
$ docker ps -a
```

STATUS
UP=起動中
Exited=停止

## コンテナの生成+起動

```
$ docker run [オプション] イメージ名[:タグ名] [引数]

$ docker run [オプション] イメージ名[:タグ名] /bin/bash
```

```
$ docker run -it -p 8888:8888 tensorflow/tensorflow
```

docker run オプション

|オプション|内容|
|:--:|:--|
|-it|コンテナを作ってログインする|
|--rm|コンテナ終了時にコンテナを自動的に削除|
|--name 名前|設定した名前でコンテナを起動|
|-d|バックグラウンドで実行する|
|-p XXXX:YYYY|ホストのポートXXXXがコンテナのポートYYYYにマップする|
|-v \${DIR_ON_HOST}:${DIR_ON_CONTAINER}|コンテナにボリュームを割り当てる|
|-w dir_on_container|dir_on_containerをワーキングディレクトリに設定|
|--runtime=${RUNTIME}|GPU対応tensorflowで使うやつ。公式ドキュメントにもコンテナに使うランタイムとしか書いてない|


ログイン状態から抜けるdettach(デタッチ)
ctrl + P → ctrl + Q

# コンテナの起動

```
$ docker start ${container_id} or ${name}
```

# コンテナの停止

```
$ docker stop ${container_id} or ${name}
```

# コンテナの操作

## 起動中のコンテナに入ってbashを使う
rootユーザでコンテナに入る

```
USER=root
CONTAINER_NAME=jupyter
docker exec -it --user ${USER} ${CONTAINER_NAME} /bin/bash 
```

# イメージの作成

## コンテナからイメージを作成

```
CONTAINER_NAME=jupyter
REPOSITORY=continuumio/anaconda3
TAG=snorkel
docker commit ${CONTAINER_NAME} ${REPOSITORY}：${TAG}
```

## Dockerfileからイメージを作成

tagを省略しているので、latestが付与される

```
IMAGE_NAME=test
DOCKERFILE_PATH=.
docker build -t ${IMAGE_NAME} ${DOCKERFILE_PATH}
```

tagを付ける場合

```
IMAGE_NAME=test
TAG_NAME=1.0
DOCKERFILE_PATH=.
docker build -t ${IMAGE_NAME}:${TAG_NAME} ${DOCKERFILE_PATH}
```


Volume dockerでホストのデータ領域をマウントする時に使う方法


https://kiririmode.hatenablog.jp/entry/20180608/1528447002




便利なdocker

Jupyter

```
$ docker run --rm --name jupyter -d -p 8888:8888 \
    -v `pwd`/workspace:/workspace -w /workspace \
    continuumio/anaconda3 \
    jupyter-lab --no-browser --port=8888 --ip=0.0.0.0 \
    --allow-root --NotebookApp.token=''
```
ひらがな、カタカナのソート【Swift】

### Tips

日本語、ひらがなカタカナをソートすると気が付いた

```swift
let index = ["あ", "ア", "か", "カ", "が", "ガ", "さ", "サ"]
print(index)
// ["あ", "ア", "か", "カ", "が", "ガ", "さ", "サ"] 
let sortedIndex = index.sorted()
print(sortedIndex)
// ["あ", "か", "が", "さ", "ア", "カ", "ガ", "サ"]
```
ひらがなソート > カタカナソートという順に並ぶ🤔

これは、**unicode**でソートされているからである

```swift
let unicodeIndex = index.compactMap({ $0.unicodeScalars.first })
print(unicodeIndex)
// ["\u{3042}", "\u{30A2}", "\u{304B}", "\u{30AB}", "\u{304C}", "\u{30AC}", "\u{3055}", "\u{30B5}"]

let unicodeSortedIndex = unicodeIndex.sorted()
print(unicodeSortedIndex)
// ["\u{3042}", "\u{304B}", "\u{304C}", "\u{3055}", "\u{30A2}", "\u{30AB}", "\u{30AC}", "\u{30B5}"]
```

我は、ひらがなカタカナ入れ混ぜて、ソートしたい

### ソート手段

何とも素敵なメソッドが用意されていました✨
ご教授いただいた[woxtu](https://qiita.com/woxtu)さんに感謝！！！

**Compares strings as sorted by the Finder.**
https://developer.apple.com/documentation/foundation/nsstring/1409742-localizedstandardcompare

```swift
let sortedIndex = index.sorted { $0.localizedStandardCompare($1) == .orderedAscending }
print(sortedIndex)
// ["あ", "ア", "か", "カ", "が", "ガ", "さ", "サ"]
```

以下最初に取った手段
~~ひらがな、カタカナを統一して並び替えよう🤗~~

```swift:String+Extension.swift
extension String {
    func transformHiraganaToKatakana(_ reverse: Bool) -> String {
        let mutable = NSMutableString(string: self) as CFMutableString
        CFStringTransform(mutable, nil, kCFStringTransformHiraganaKatakana, reverse)
        return mutable as String
    }
}
```

```swift
let sortedIndex = index.flatMap({ $0.transformHiraganaToKatakana(false) }).sorted()
print(sortedIndex)
// ["ア", "ア", "カ", "カ", "ガ", "ガ", "サ", "サ"]
```

> Swift4
【PL/SQL】比較を行い、片方にのみ存在するレコードを論理削除するSQL

#2つのテーブルのうち片方にのみ存在するレコードの論理削除
##やりたいこと
2つのテーブルを比較し、一方に存在し、もう一方に存在しないレコードを論理削除します。
データ連携などの際に連携されなかったマスタ情報などを更新するために使用します。
UPDATEだけでなく、DELETEなどの応用も可能です。
この処理では「TGTテーブル」に存在し、「WKテーブル」に存在しないものを「TGTテーブル」でUPDATEする場合に使用します。

逆に「WKテーブル」に存在し、「TGTテーブル」に存在しないものを「WKテーブル」からINSERTする場合には「MERGE」文を使用します。
[【PL/SQL】MERGE=INSERT+UPDATE](https://qiita.com/t-kikuchi/items/77515b167017fb3a630a)

##テーブル
**WKテーブル**

|       EMP_CD(主キー) |    EMP_NAME    | 
|:-----------------:|:------------------:|
|              E111111 |        aaa        |
|              E222222 |        bbb        |

**TGTテーブル**

|       EMP_CD(主キー) |    EMP_NAME    |     DEL_FLG(削除区分)    | 
|:-----------------:|:------------------:|:------------------:|
|              E111111 |        aaa        |        0        |
|              E222222 |        bbb        |        0        |
|              E333333 |        ccc        |        0        |

⇒TGTテーブルのみに存在するレコードのDEL_FLGを1として論理削除を行いたい。

|       EMP_CD(主キー) |    EMP_NAME    |     DEL_FLG(削除区分)    | 
|:-----------------:|:------------------:|:------------------:|
|              E111111 |        aaa        |        0        |
|              E222222 |        bbb        |        0        |
|              E333333 |        ccc        |        **1**        |


##コード(主キーが1つの場合)
```sql
UPDATE tgt tgt
SET    tgt.del_flg = '1'    -- del_flgを1に更新
WHERE  tgt.emd_cd =
    (   SELECT
            tgt_wk.emd_cd
        FROM tgt tgt_wk                -- TGTテーブル
        LEFT OUTER JOIN wk wk          -- WKテーブル
        ON tgt_wk.emd_cd = wk.emd_cd
        WHERE wk.emd_cd IS NULL        -- 主キーがNULLの項目をキャッチ
    );
```
または

```sql
UPDATE tgt tgt
SET    tgt.del_flg = '1'    -- del_flgを1に更新
WHERE  NOT EXISTS
       (SELECT *
        FROM   wk
        WHERE  tgt.emp_cd = wk.emp_cd
        );
```

`EXISTS` は後に続く括弧で囲まれた副問い合わせの結果が「存在すれば (TRUE)」、「存在しなければ (FALSE)」を戻します。
`NOT EXISTS`はその逆のため、「存在しなければ (TRUE)」、「存在すれば (FALSE)」を戻します。

##コード(主キーが2つ以上の場合)
主キーが`emp_cd`と`emp_cd2`の場合には以下のような記述になります。

```sql
UPDATE tgt tgt
SET    tgt.del_flg = '1'    -- del_flgを1に更新
WHERE (  tgt.emd_cd,
         tgt.emd_cd2
     ) IN
    (   SELECT
            tgt_wk.emd_cd,
            tgt_wk.emd_cd2
        FROM tgt tgt_wk                -- TGTテーブル
        LEFT OUTER JOIN wk wk          -- WKテーブル
        ON tgt_wk.emd_cd = wk.emd_cd
        WHERE wk.emd_cd  IS NULL        -- 主キーがNULLの項目をキャッチ
        AND   wk.emd_cd2 IS NULL
    );
```
または

```sql
UPDATE tgt tgt
SET    tgt.del_flg = '1'    -- del_flgを1に更新
WHERE  NOT EXISTS
       (SELECT *
        FROM   wk
        WHERE  tgt.emp_cd  = wk.emp_cd
        AND    tgt.emp_cd2 = wk.emp_cd2
        );
```

##NOT EXISTS とNOT IN
`NOT EXISTS`ではなく`NOT IN`を使用した場合、副問い合わせの結果が NULLとなる場合、結果はUNKNOWNになるため `NOT EXISTS` の場合と異なる挙動を取ります。NULLについて特別な処理を行わないならば、`NOT EXISTS`が無難です。
IONIC  ion-select で Defalut valueのセット方法

公式では value= で設定出来ると書かれていますが、何度やってもうまくいかない。

状態に応じて動的に選択肢を変化させるというion-selectを作成しましたが、初期値のセットがうまくいかず色々調ベタ結果


以下の選択肢の場合

```typescrypt:aaa.ts
       this.ranklist = [{id: 'black' ,name: 'ブラック'}
                     , {id: 'beginner', name: 'ビギナー'}]
```

これは動作しない。

```typescrypt:aaa.ts
.setValue({id: 'black' ,name: 'ブラック'});

```

以下で動作しました。

```typescrypt:aaa.ts
.setValue(this.ranklist[0]);

```

選択肢一覧のうちの何番目という渡し方をしないとどうさしてくれないのかな？
Minecraft Modding[1.12]　Itemの特殊レンダーのつけ方

#Itemの特殊レンダー
メモ代わりに

##やること
・IBakedModel.isGuiとIBakedModel.isBuiltInRendererでtrueを返すModelを作る
・ModelBakeEventで作ったModelを描画したいItemに登録する

・TileEntityItemStackRenderer（TEISR）を継承しrenderByItemに描画処理を書く（TileEntity持ちどころかItemBlock以外ですら可能）
・Item.setTileEntityItemStackRendererでItemに作ったTEISRを渡す


##参考

https://github.com/Otamusan/NotEnoughCompression/blob/master/src/main/java/otamusan/nec/client/itemcompressed/CompressedModel.java

https://github.com/Otamusan/NotEnoughCompression/blob/master/src/main/java/otamusan/nec/client/ModelBakeEventHandler.java

https://github.com/Otamusan/NotEnoughCompression/blob/master/src/main/java/otamusan/nec/client/blockcompressed/TileSpecialItemRendererCompressed.java

https://github.com/Otamusan/NotEnoughCompression/blob/master/src/main/java/otamusan/nec/client/ClientProxy.java#L101
laravel 5.7 で cron

laravel cron やろうぜ

cron の内容を更新する場合は以下を参考
https://qiita.com/ma7ma7pipipi/items/d65caa48a96aace39df9


```Console/Commands/Cron.php

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Log;

class Cron extends Command
{
    protected $signature = 'cron';
    protected $description = 'Cron description';

    public function __construct()
    {
        parent::__construct();
    }

    public function handle()
    {
        Log::debug(time()." ハンドルcron ログ動作");
    }
}


```


```Console/Kernel.php

<?php

namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{

    protected $commands = [
    ];


    protected function schedule(Schedule $schedule)
    {
        $schedule->command('cron')
            ->evenInMaintenanceMode()//メンテナンスモードでも動かす
            ->everyMinute(); //毎分動かす
//            ->cron('5 */1 * * *'); //1時間毎に 5 分になったら動かす

//        複数個 cron を仕掛けたい場合はふくすうファイルを作るだけ。
        //        $schedule->command('cronanalytics')
//            ->evenInMaintenanceMode()//メンテナンスモードでも動かす
//            ->cron('3 */1 * * *'); //1時間に1度動かす
    }

    protected function commands()
    {
        $this->load(__DIR__.'/Commands');
        require base_path('routes/console.php');
    }
}


```


分	1-59
時	0-23
日	1-31
月	1-12
曜日	0-6 （ 日曜日が0となります。 ）
コマンド	スクリプトなど、実行できるもの。
->cron('* * * * *');//分　時　日　月　曜日　コマンド


cronをしかける


```cron.txt

* * * * * /opt/remi/php71/root/usr/bin/php -c /etc/opt/remi/php71/php.ini /var/www/html/mama-rich.net/artisan schedule:run 1>> /dev/null 2>&1

```

再読み込み
```
crontab cron.txt
```


これでログができる。
































# 以下古い記事

```
php artisan make:command  GetItemFeed --command="getitem"

```

以下のファイルができる。
そして処理したい内容は handle() 内に書く。

ログを取得するプログラムを書く。

```/app/Console/Commands/GetItemFeed.php
use Log;

    public function handle()
    {
        Log::debug(time()." cron ログ動作");
    }


```

実行しようぜ
ログファイルにログが記述される。

```

php artisan getitem
// [2019-03-11 13:55:01] production.DEBUG: 1552280101 cron ログ動作  

```

Cron登録準備

```kernel.php

    protected $commands = [
        \App\Console\Commands\GetItemFeed::class, // ←今回の追加
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('getitem')
            ->evenInMaintenanceMode()//メンテナンスモードでも動かす
            ->everyMinute(); //毎分動かす
    }

```


それではCronに登録
実行日時は laravelで判断するので、すべて * にしておく。

```

* * * * * /opt/remi/php71/root/usr/bin/php -c /etc/opt/remi/php71/php.ini /var/www/html/helpee.club/artisan schedule:run 1>> /dev/null 2>&1


```

ログができてるかチェック

```

[2019-03-11 13:56:01] production.DEBUG: 1552280161 cron ログ動作  
[2019-03-11 13:57:01] production.DEBUG: 1552280221 cron ログ動作  
[2019-03-11 13:58:02] production.DEBUG: 1552280282 cron ログ動作  


```

やったね！
GitとGitHubのアカウントを連携させる（GitHubにpushしても草が生えない時）（初心者向け）

以前書いた記事
[Cloud9とGitHubを連携させる方法（初心者向け）](https://qiita.com/higu1988/items/3a9c4fe528c2388bdc7f)
で、Cloud9などのIDEやローカル環境とGitHubを連携させて、
Git→GitHubへpushする方法を書きましたが、
これだけだと、プロフィール画面の「** contributions in the last year」のところに色が塗られない！

![スクリーンショット 2019-03-11 13.17.54.png](https://qiita-image-store.s3.amazonaws.com/0/374100/b3a09f76-c56d-ce6d-2700-0826cc1caa11.png)

毎日眠い目をこすって頑張って開発してpushしたのに、
「no activity yet for this period.」とか言われると涙出ちゃいますよね。。

今回はアカウント連携ができてないせいだったので、アカウント連携の方法を備忘録がてら書いていこうと思います。
ちなみにアカウント連携以外にも原因がある場合があるので、
連携してるのに色塗られないよーという方は、
[Why are my contributions not showing up on my profile?](https://help.github.com/en/articles/why-are-my-contributions-not-showing-up-on-my-profile)を見るか、ネットで調べて見てください。

# 何がおきてるか
ローカル環境とGitHubを連携させたのに、アカウントが連携されてないって何事！？って感じですよね。

ローカル環境とGitHubの連携は、ローカル環境からGitHubに情報を渡せるようにしただけで、
必ずしもローカル環境の人が、GitHubの人と同一人物だとは言ってないんです。


# 連携されてるかどうかを確認する
まずは、今、アカウントが連携されているか確認してみましょう。
<img width="1008" alt="スクリーンショット 2019-03-11 13.38.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/374100/9c4efe68-a2e5-8fcf-c612-a668952c2220.png">
赤線で囲ったところが<img width="134" alt="スクリーンショット 2019-03-11 13.38.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/374100/7f171b16-3fd4-362f-0c43-9cb89de26445.png">になってたら残念ながら連携されてないです。
他にも確認方法ありますが、GitやGitHub初心者はこの確認でいいと思います。

# 連携させる
ローカル環境とGitHubを連携させるには、メールアドレスを使います。
（ローカル環境に登録したメアドが、GitHubで登録しているメアドと一致すれば連携するということだそうです）

まずはターミナルに下記のコードを打って、ユーザー名を登録します。
`$ git config --global user.name "ユーザー名"`
そして、下記のコードでメールアドレスを登録。
`$ git config --global user.email メールアドレス`

これでdoneです！

# 連携されているか確認する
再度、ローカル環境でGitHubにpushしてみてください。
プロフィールに反映されてたら、連携完了です！
<img width="752" alt="スクリーンショット 2019-03-11 13.48.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/374100/f63ee46d-9e08-944f-66f5-e7fcd70b7f18.png">

ちなみに、過去にpushしたけど、当時はアカウント連携されてなくて、プロフィールに反映されてないってやつを
遡って連携する設定方法が別であるらしいです。
やってみたらまた記事にしまーす

あと、プロフィール画面の下記のチャートを緑にしていくことを、
エンジニアさんは「草を生やす」「芝生に芝を生やす」とかっていうらしいです。
<img width="746" alt="スクリーンショット 2019-03-11 13.47.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/374100/82fe0ad1-0565-cdf7-6e7e-3f0d92528711.png">

本当に専門用語多すぎですね。。。リアルガチで初心者の方、共に頑張りましょう・・・！
EgretProを使ってみよう

# EgretProとは？

Unityのように3Dプロジェクトを開発＆ビルドできる統合開発環境です

# インストール

こちらからインストーラーをダウンロードしてください。

http://developer.egret.com/cn/docs/3d/
![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/ce30043a-ff92-7e06-64cf-e8d45a354ade.png)

ダウンロードしたインストーラーを起動する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/20511570-b005-e624-dfb9-d6e0659418a9.png)

利用規約ですが、残念ながら読めないので、スルーパスで「Agree」

![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/e67788aa-e5af-d8b8-32e2-b8aad31a6d11.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/f99b4168-f780-8bfe-f7c1-585962ed25b9.png)

以上

![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/f64de967-56a5-581d-a50d-74f0d39bbfc9.png)

# 起動

Windowsメニューのプログラム一覧から「Egret Pro」を選択して起動する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/bf115cc6-ca7c-a510-1e3a-c5d2e38d352c.png)

起動した！が読めないぞ！！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/ff0d978f-efe6-f5a1-9f2d-8d0bc2480c67.png)

|UI|翻訳|
|----|----|
|最近打开|Recently Opened|
|新项目|New Project|
|打开项目|Open Project|

「New Project」からプロジェクトを作ります
![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/d3267f53-4e51-a3b7-24ee-e1fb8bc0260f.png)


|UI|翻訳|
|----|----|
|（左側のボタン）|（不明）→Select Folder的なボタンのようです|
|新建项目|Create Project|

プロジェクトを作成するとエディターが起動しますが、ローディング画面が何秒か続きます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/fb8cee46-7720-4041-acff-0749a6931237.png)

このように開きました
![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/22ae741b-e4a8-24e8-ef59-cf0256675af3.png)

# 感想
UIすべてが中国語なのでしんどいです。
ネイティブソフトなのでUIの中国語文章がコピーできないので、機械で翻訳するのも難しい状況です。
設定メソッドの削除(Remove Setting Method)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/257568/fdaf5b9d-a029-52fa-35b6-44022684defa.png)


1つずつリファクタリング技法まとめ
個人的に簡単かつ取り入れ易いと思うものから

## 目的
すぐ引き出せるようにする

## 基本作業サイクル
- システムを動かして仕様を精査
- テストメソッドを作成
- テストの失敗を確認
- テストの成功を確認
- 小さい変更、随時テスト実行(パターン追加失敗確認->成功確認)
- 最後テスト実行
- 最後動作確認

## 設定メソッドの削除(Remove Setting Method)とは
不要なsetterを削除すること
フィールドの情報を書き換えられたくない(べきでない)場合、それを自明にすること
 
## ポイント
- クラスの作成時に暫定的に追加していた記述を見直す。
- setterが行えることによって起き得る弊害を考える。

## 例

```
class Person
  attr_accessor : relatives

  def initialize(args)
    @relatives = args[:relatives]
  end
end
```
　　　↓

```
class Person
  attr_reader : relatives

  def initialize(args)
    @relatives = args[:relatives]
  end
end
```

## 書籍情報
Jay Fields (著), Shane Harvie (著), Martin Fowler (著), Kent Beck (著),
長尾 高弘(訳), リファクタリング:Rubyエディション
https://amzn.to/2VlyWML

## 雑感
使い易さは汎用性だけではないことをしっかり念頭におく
iOS 設備　Identification For Advertisers(IDFA) の話　iPhoneのIDFAとは

### 📘 公式定義　

**広告ID（IDFA：Identifier for Advertisers）** は、各iOSデバイスに割り当てられる一意の識別子で、ユーザーにターゲティング広告を提供するための唯一の手段です。ユーザーは、iOSデバイスの設定からターゲティング広告の制限を選択することができます。

iOSでは、**2012年以降、プライバシー保護の観点から、アプリがユーザーを識別するための固定IDを取得することが禁止されました**。

しかし、広告の効果測定やターゲティング広告の実現のため、開発者側では引き続きユーザーを識別可能なIDが必要とされていました。

このような背景から、**広告追跡専用の識別子として「IDFA（Identifier for Advertisers）」が導入されました**。

ただし、IDFAはユーザーによって以下のような操作が可能です：

* 設定 → プライバシー → 広告 → 「追跡型広告を制限」
* 「広告識別子（IDFA）」のリセット

---

### 🔄 結論

* **開発者**は、IDFAを利用することでユーザーを識別し、広告の最適化や効果測定が可能です。
* **ユーザー**は、プライバシーを重視する場合、IDFAのリセットや広告トラッキングの無効化をいつでも設定から実行できます。
IM-FormaDesigner / IM-BIS セレクトボックス Option値をAPIで設定する

IM-FormaDesigner / IM-BIS セレクトボックス Option値をAPIで設定する

## 前提
- intra-mart Accel Platform 
- IM-FormaDesiner / IM-BIS

## やりかた
[IM-BIS クライアントサイドスクリプトAPI](https://www.intra-mart.jp/document/library/bis/public/bis_specification/texts/spec/csjs_script.html)
上記のAPI解説には書いてないが、setItemDataのargsにmasterプロパティが設定されていればその値となる

masterプロパティの内容は下記の通りに設定する
> master.%フィールド識別ID%.[i].value_%フィールド識別ID%
> master.%フィールド識別ID%.[i].key_%フィールド識別ID%

分かりにくいと思うのでサンプルを提示する
これをクライアントサイドスクリプトで使う

```javascript:sample.js
// フィールド識別IDを指定
var dep2_id = "dep2_selectbox";
var dep2_args = {};
// Option項目設定
dep2_args.master = {};
dep2_args.master[dep2_id] = [];
// 空行設定
var emprow = {};
emprow["value_" + dep2_id] = "";
emprow["key_" + dep2_id] = "";
dep2_args.master[dep2_id].push(emprow);

// 1行目設定
var row1 = {};
row1["value_" + dep2_id] = "1";
row1["key_" + dep2_id] = "1行目";
dep2_args.master[dep2_id].push(row1);

// 2行目設定
var row2 = {};
row2["value_" + dep2_id] = "2";
row2["key_" + dep2_id] = "2行目";
dep2_args.master[dep2_id].push(row2);

// 選択値設定
dep2_args.data = {};
dep2_args.data[dep2_id] = "";
formaItems.product_80_selectbox.setItemData[dep2_id](dep2_args);
```

## 
おそらくリストボックス、チェックボックス、ラジオボタンでも使える

## 注意事項
公式のAPI資料には載っていない方法ですので使用は自己責任でお願いします
なぜ僕は、GUIアプリを作れないのか（2019-06-10T17:20 加筆）

# はじめに

僕はGUIアプリが作れない。

理由がわからないので、今回その理由を掘り下げるために記事を書いた。

## 筆者スペック

* 多分ソフトウェア開発の現場で5年働いてる
* Gitの操作はCLI派
* Webページは10年前みたいなものしか作れない
* できる言語
  * C#
  * VB.net
  * Python
  * JavaScript
  * RustとかNimとかGoとかをちょっとやってた時期もあった。

# 問題点

[はじめに](#はじめに) 書いたとおり、僕はいまいちGUIアプリを作れない。

もう少し厳密に言うと、データストリームが絡んできたアプリを作れないような気がする。なのでGUIに限らない事がわかる。

以上の点から、以下の問題に細分化できるものと思われる。

## マルチスレッドの理解

OSやフレームワーク・ライブラリでの動作に依存するものと思われるが、どれにしたって私はこの辺りの理解が浅い気がする。

### 別スレッドで動作するプログラムの作用の理解

そのため、別のスレッドで動作したものが、自分の書いているプログラムにどの様に影響するか、もしくはどの様に影響を与えれているのかを理解できていないフシもある。

## UIパーツの作用・副作用の理解

続いてはここだろうか。UIパーツが与える作用・副作用を理解・把握しきれない。
自分の書いているコードでさえ、ボタンがクリックされたときのイベントの情報から、どの様なことが取得できるか、深く調べたことがなく、忘れていることも多々ある。

## コードを責任分散したくても（自分の思ったように）できない

MVC/MVVMなどの設計について漠然とした理解しかしておらず、
「僕はこの処理はModelで行うものと考えていたのに、実際に処理を書こうとすると、Controllerに配置しなければ処理を行えない」
ということがままあり、そこで素直にControllerに処理を書けばいいものを、自分の考えとの重ね合わせに苦悶してコードが一片も書けないということに毎回陥る。

## 「グローバル変数的考え」からの脱却のできなさ

極論を行ってしまえば、「グローバル変数」ないし「シングルトンパターン」でデータの使い回しをしてしまえば解決する問題も多々あるだろう。

だが、僕はあまりこれを良しとしない頑固者である。
「グローバル変数」や「シングルトンパターン」を安直に使用して、それらが肥大化することを過剰に恐れている。実装もせずにだ。

# まとめ

GUIアプリを作るには、どうしてもマルチスレッドの事を意識しなければいけない。

そうでもないと思われるのであれば、あなたの使っているフレームワークが優秀か、あなたがフレームワークへの理解やマルチスレッドに対して無意識に熟知しているのだと筆者は思う。

僕は、作ったGUIアプリやWebフロントエンドの数が、人より少ないのだろう。
そのくせ、実装もせず足りない頭で考えて、何も実装せず、自分の知識や学習の不足感に思考を持っていかれて、結局何も実装できなくなる。

だから、Reactiveプログラミングとかasync/awaitに、
「他のスレッドのことを考えずにプログラミングできるのかなー」
という漠然とした希望をいだき続けている限り、僕は使い物にならない。

5年この業界でぶらぶらしてたつもりだが、未だにPowerShellかBashスクリプト、もしくはPythonで、あるXMLをあるフォーマットのJSONに変換する程度のプログラムを組む、時給1,000円くらいの仕事が身の丈的に限界なのかもしれない。

それで、こういう「爪楊枝」になるかならないかわからないプログラムしか書けないやつは、この先どう生き残れば良いのか……。

# その後 2019-06-10T17:30 加筆

紆余曲折あって、また少々古めのCSharp案件に入った。

そこで幸い、良い設計とチームメンバーに出会えた。

そしてテストコードを書いて、
「見た目の問題は少し脇に置いて、まずデータの入出力だけに集中してプログラムを書く」
ということをした。

実行ファイル化されたプログラムとWebサーバープログラム、更に現物を知らないハードウェアが絡み合った開発だが、自分なりにはうまくやっていけてる気がする。

挫折したLINQも、`IObservable` とかReactiveを少し脇に置いて書いてみたら、すんなりかけてしまっている。 `Func<>` や `Action<>` を、今までのソースコードの雰囲気を読まずに多用しているのはいささか問題ありそうだが、delegateについて業務を通しながら学んだら、意外と分かったつもりになってる（こういう発想が一番危険なのだが）。

## この半年の学び

端的に言ってしまえば、
「いきなり踏み込みすぎた」
のだろう。
そこから少し、物理的にも時間的にも心理的にも間を置いたことにより、自分の踏みだせる歩幅で踏み出したら、分かった。

それだけのことだと言ってしまえばそれだけのことだし、この記事に関しては.netFrameworkに限定された話でもあるため、Webブラウザになった瞬間、また1から出直さなければならなくなるだろう。

とはいえ、この体験は残しておくとともに、もし、
「うんあー、今学んでいることがわっかんねー」
と言ってもがいている人たちに、一歩引いて学びなおすきっかけになれば幸いである。
Raspberry Pi (Raspbian)でログインループから抜け出せなくなったときの対処

## 問題となった現象
Raspberry Pi (Raspbian)を起動後にGUIのログイン画面でログインしようとしたところ、パスワード認証は成功するものの、デスクトップが表示されずに、再度ログイン画面が表示されてしまうという問題に遭遇しました。

![ログイン画面](https://qiita-image-store.s3.amazonaws.com/0/469/c8a82def-6df0-08aa-a19f-7f86181fa4bc.jpeg)

間違ったパスワードを入力すると、以下のようにエラーが表示されるので、パスワード間違いではないことが確認できます。

![パスワードエラー](https://qiita-image-store.s3.amazonaws.com/0/469/aea893cd-1ec0-5592-f51b-561da01ba96c.jpeg)

## 原因の発見と解決
今回は、`lxsession`のバイナリがなくなっていた事が原因でエラーになっていました。直前の作業で、パッケージをいくつか削除したので、その際に巻き込まれてしまったのかもしれません。

以下、原因の発見と解決するまでの手順です。SSHでログインできることが前提となっています。

他のマシンからSSHで接続します。

```
$ ssh <user>@<hostname>
```

エラーログを確認してみます。

```
$ tail .xsession-errors
...
/usr/bin/x-session-manager: 33: exec: /usr/bin/lxsession: not found
```

lxsessionがnot foundになっていることが確認できました。


以下コマンドで`lexsession`をインストールします。
```
$ sudo apt-get install lxsession
```

インストールが完了したら、Rasberry PiのGUIから再度ログインをします。
ネコでも分かるSOLID原則(第1回)

こんにちは、らべねこです。
私は今「アジャイルソフトウェア開発の奥義」を読んでいます。
その中のSOLID原則の部分がよく分からなかったので、私なりにまとめて理解したものをQiitaに投稿していきたいと思います。
間違い等ありましたらご気軽にコメントください。

# SOLID原則とは
多くの設計で用いられている考え方を原則としてまとめたものです
以下の5つの原則があります

- S：SRP、単一責任の原則
- O：OCP、オープン・クローズドの原則
- L：LSP、リスコフの置換原則
- I：ISP、インタフェース分離の原則
- D：DIP、依存性逆転の原則

第1回は、単一責任の原則についてまとめました

# S: 単一責任の原則(SRP: The Single Responsibility Principle)
### 守るべきルール
クラスを変更する理由は1つ以上存在してはならない

### ルールを守らないとどのような問題が起きるか
- クラスが持つ役割が複数あると、そのうちの1つの変更でクラス全体に影響が出てしまいます
- クラスが本来持つべきではない不要な役割を持ってしまうこともあります

### クラスが持つ役割は1つという原則ではない
- 複数の役割が必ず同時に変更されるようなケースでは分離する必要はないです
- 以下の理由があります
  - 設計が不必要に複雑になってしまいます
  - 「変更の理由が変更の理由たるのは、実際に変更の理由が生じた場合だけである」という法則があります。変更の兆候もないのに単一責任の原則を適用するのは懸命ではないです。

### クラスによっては、複数の役割の分離が難しいものもある
- クラスによっては、全く関係のない役割のものを持たなければいけない制約があるものもあります
  - 例) ハードウェアやOSがそのような役割の分離を許さない場合など
- この場合は、他の部分と依存関係がなく、他の部分に漏れ出さないようにすることが大切です

第2回では、オープン・クローズドの原則について説明します
（らべねこしか分からないSOLID原則になっていたらごめんなさい…）