OmniAICreator/Qiita-1.07M huggingface dataset:
【SQL】前処理に使うコードなど

##複数keywordでの絞込

where likeの多用による、複数keywordでの絞込はperformance低下に繋がるため、以下の記載で複数のkeywordでの絞込を行う（下記の場合、前方一致での絞込

```sql
where regexp_like(【column_name】,'^【keyword】|^【keyword】|^【keyword】')
```



##case式

値が「1か2か３」だったら1を入れる
値が「4か5か6」だったら0を入れる
それ以外だったらnullとする

```sql
case
  when 【column_name】 in (1,2,3) then 1
  when 【column_name】 in (4,5,6) then 0
  else null
  end as 【column_name】
```



##data型の変換

整数に変換

```sql
cast(【column_name】 as int)
```

##nullを埋める

指定した文字列（や数値、0等）でnullが埋められる

```sql
coalesce(【column_name】,【代わりに埋めたい文字列】)
```



##文字列の加工

###分割

下記により出力されるのは配列なので、分割後のものを使用したい場合は、

```sql
split(【column_name】,'【分割のkeyとしたい文字列】')
```

下記のように配列の中身を取り出す（sqlの場合、配列は0からではなく、1からのstart

```sql
select 【column_name】[1]
```





###結合

２つのcolumnを結合したcolumnを作成

```sql
concat(【column_name】,【column_name】)
```



##queryによるtableの作成と削除（≒更新

【table_name】が既に存在していたら、一旦削除
その上で、【table_name】を【sub query】を実行する形で作成（≒tableを更新
これらをbatchで定期的に実行する等

```sql
drop table if exists 【table_name】;
create table if not exists 【table_name】 as

with （以下【sub query】）
```



##group byの注意点

大文字／小文字で別々にgroupingされてしまうので、以下のように大文字変換か小文字変換を行い、統一してからgroup byをすると確実

```sql
upper(【column_name】)
```

```sql
lower(【column_name】)
```
AtCoderログ：0102 - ABC 217 に参加しました


この記事は 2021年09月04日(土)21:00-22:40 に開催された [AtCoder Beginner Contest 217 (ABC 217)](https://atcoder.jp/contests/abc217) に参加した記録です。

https://atcoder.jp/contests/abc217

# 結果
- 得点：600 (=100+200+300)
- 時間：16:50 (= 16:50 + 05:00 × 0)
- 順位：4843 / 8543
- パフォーマンス：479
- レーティング：368 → 380 (+12) Highest更新！
- 段級位：9級

![2021-09-04_abc217.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1589302/15ca85d3-e595-c1e7-dd74-5e7ab2455862.png)

# 詳細
|問題|得点|時間|提出コード|復習|
|:--:|:--:|:--:|:--:|:--:|
|[ABC 217 A](https://atcoder.jp/contests/abc217/tasks/abc217_a)|100|03:34|[○](https://atcoder.jp/contests/abc217/submissions/25561573)|[AtCoderログ：0103](https://qiita.com/RoadLynton/items/861291cdcc4ce8bd9558)|
|[ABC 217 B](https://atcoder.jp/contests/abc217/tasks/abc217_b)|200|08:14|[○](https://atcoder.jp/contests/abc217/submissions/25568836)|[AtCoderログ：0104](https://qiita.com/RoadLynton/items/031cddef375aecfc6559)|
|[ABC 217 C](https://atcoder.jp/contests/abc217/tasks/abc217_c)|300|16:50|[○](https://atcoder.jp/contests/abc217/submissions/25576234)|[AtCoderログ：0105](https://qiita.com/RoadLynton/items/82c9162232c3c14241ec)|
|[ABC 217 D](https://atcoder.jp/contests/abc217/tasks/abc217_d)|400|(2)|---|---|
|[ABC 217 E](https://atcoder.jp/contests/abc217/tasks/abc217_e)|500|---|---|---|
|[ABC 217 F](https://atcoder.jp/contests/abc217/tasks/abc217_f)|600|---|---|---|
|[ABC 217 G](https://atcoder.jp/contests/abc217/tasks/abc217_g)|600|---|---|---|
|[ABC 217 H](https://atcoder.jp/contests/abc217/tasks/abc217_h)|600|---|---|---|

# 感想
- A, B, C まで完答できました。
- A は悩むことなく正解。
- B は解法に迷いましたが難なく正解。
- C はすぐに解法を思いつくことが出来たので、こちらも難なく正解。
- 残り時間は D を解くのに使いましたが、解答には至りませんでした。
- レーティングは微増でした。
 
# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0101 - ABC 216 C](https://qiita.com/RoadLynton/items/b31ccf2806e239c34014)
- 次の記事 → [AtCoderログ：0103 - ABC 217 A](https://qiita.com/RoadLynton/items/861291cdcc4ce8bd9558)
【git】warning: LF will be replaced by CRLF in Gemfile.lock.の対処法

<h2>症状</h2>
gitaddをしたところ、下記メッセージが表示されaddできませんでした。
翻訳すると、「警告：Gemfile.lockではLFがCRLFに置き換えられます。」となりました。

```terminal:error
warning: LF will be replaced by CRLF in Gemfile.lock.
The file will have its original line endings in your working directory
```

<h2>解決策</h2>
GitがLF改行コードをCRLFに自動変換した事によるwarnで、それをしないようにGitに設定することで解決しました。

```terminal:
git config --global core.autoCRLF false
```

<h2>参考</h2>

https://normalblog.net/system/lf_replaced_crlf/
Rails コントローラーのアクションについて

# アクションとは
ユーザーからリクエストを受けたときサーバー側でどのような処理をするのかを
***アクション(動作)*** と言います。
アクションはapp/controllers/〜controller.rbつまりコントローラーの中に作成されます。
今回のコントローラーはsportsコントローラーにします。


```sports_controller.rb

	class SportsController < ApplicationController

	def baseball
	
        render  plain: "野球"
	end
 ```
⚫︎補足
***render plainを使うとブラウザで表示***できる。

```routes.rb
Rails.application.routes.draw do
	
get "/yakyu", to:"sports#baseball"

end
```
- railsサーバーを起動
```localhost/3000/yakyu```で***ブラウザには野球と表示***されます。

ルーティングの中身を見てみると/yakyuをURLで指定すると
Sportsコントローラーの中のbaseballメソッドが呼び出されている
わけえです。

下ではそれぞれよく使うアクションを見ながら
見ていきましょう。


# indexアクション
Indexアクションは主に***一覧表示やトップページがよばれた時に使います。***

```sports_controller.rb
	def  index
	 @sports = Sports.all
	end
```
@sports = Sports.allはコントローラーからスポーツの一覧を全部取ってきてくれという
指示を出しているコ意味です。
HTTPはGETです。

⚫︎補足
***@はインスタンス変数と言います。***　これはviewに渡せる変数のことです。

例えば
```sports_controller.rb

    def  index
	@sports = "サッカー"
    end
```
```index.html.erb
  <h1> <%= @sports %></h1>

```
とするとサッカーと出力されます。


# show
Showアクションは***指定したデータを表示する。投稿の詳細ページを作るとき***に使います。

```sports_controller.rb

	def  show
	 @player= Player.find(params[:id]) 　#idに合致した値を取得してほしい
         @sports = Sports.where(sports_id: params[:id])
         end
```
Viewからの***送信値(params)***を元にデータを探しViewに返却します。
***[:]は取得したい値によって変わる。***　HTTPは***GETされた時**に使います。

# new
newアクションは***新規作成された時***に使います。

```sports_controller.rb
        def  new
        @players = Player.new　#新しいデータを作成する
	end
```
 @players = Player.newはコントローラーに新しくplayerのデータを作成する意味です。
データ作成するためのフォームが呼ばれます。
つまりこれからデータを作成するという宣言でもあります。

HTTPはGETです。

# create
createアクションは***データを新規作成して追加(保存)する時***使います。

```sports_controller.rb

	def  create
        Sports.create#省略
       redirect_to "/"
       end
```
他にも

```sports_controller.rb
  def  create
       @sports.new(params[:id])　#データを作る
       @sports.save　　#データを保存

       #または
       Sports.create(params[:id]　#データを作りたいだけならこのコードのみ
  end
```
上の***viewから送られてきたparamsの中に登録したいデータを入れます***。
その中のデータがコントローラーに処理が送られていくイメージです。


⚫︎補足
paramsとは***パラメーターのことで、変数のことです。例えば入力フォームから送られてくる値のことです。***



HTTPは***POST***された時使います。。

# edit
editアクションは***データを更新するためのフォームを表示する時***に使います。

```sports_controller.rb

      def  edit
	@sports = Sports.find(params["id"])
      end
```
HTTPは***GETされた時***使います。

# update
updateアクションは***更新する時***に使います。

```sports_controller.rb

	def  update
	sports = Sports.find(params[:id])　#どのデータを更新する？
　　　　　　　　@sports.update(params[:XX])　#更新データ
        #省略
　　　　　　　　　　　　　　　　end
```

HTTPは***PATCHかPUTされた時***使います。

# destroy
destroyアクションは削除する時に使います。

```sports_controller.rb

	def  destroy
	 sports = Sports.find(params[:id])
         sports.destroy
         redirect_to "/"

	end
```
HTTPは***DELETE***された時使います。


HTTPの説明はこちらから

https://qiita.com/Hashimoto-Noriaki/items/6b83ee8f6cf6a79c4b49


# 参考資料
https://qiita.com/kidach1/items/43e53811c12351915278

https://qiita.com/morikuma709/items/5b21e9853c9d6ea70295

https://web.lingual-ninja.com/2018/12/ruby-on-rails-action.html

https://railsguides.jp/routing.html
【Application Gateway 続編】パスベースルーティングの BackendPool に App Services を追加する

前回の記事では APGW のパスベースルーティングをチュートリアルを参考に試してみました。
前回記事 => [Azure Application Gateway のパスベースルーティングを試してみる](https://qiita.com/komiyasa/items/c38b933861ec18ad3e09)

チュートリアルではバックエンドプールに VM の IIS を追加するという形でした。今回はターゲットの指定を Web App にしてみようと思います。

#まずは App Services デプロイ
`komiyasaservices` という App Services をデプロイしてみます。前回作成した APGW と同じリソースにデプロイしました。プランは B1 を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/7a71a8d0-680c-2068-3dd6-aff0a29f7031.png)
作成したリソースの名前はあとでバックエンドプールから指定するので覚えておきましょう。デプロイが完了したら App Services の準備は終了です。

#バックエンドプールに App Services を追加する
前回作成した Application Gateway のメニューから、バックエンドプールを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/743278a6-f39d-6aab-8882-47bc31c60988.png)
新しく `komiyasabackendpool` という名前のバックエンドプールを追加し、ターゲットを先ほど作成した App Services の名前を追加します。App Services として同じサブスクリプションのものすべてが指定できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/fa847750-4233-8e50-5f4b-8e4c023c8584.png)
これでバックエンドプールの作成とターゲットの指定は完了です。

#ルーティング規則の追加
最後にルーティング規則を追加します。パスが `/komiyasa/*` というパスを追加します。ターゲットで先ほど追加したバックエンドプールを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/5355c314-6a8b-32fd-1b35-474dd3b5c47f.png)
保存を押すとわずか10秒まりで設定完了の通知がきます。APGW のデプロイ自体には時間がかかりましたが、規則を更新したり、ルールを追加したりする際は割とさくっとできるみたいですね。

#試してみる
追加した URL パスルールの `komiyasa` にアクセスしてみると、ちゃんと App Services にルーティングされているのが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/b5f4df39-05ba-765b-b46c-647bb88fe0ba.png)
こちら一般サイトですが、App Services にデプロイした API を URL パスベースルーティングを使用する方法について参考になるかと思います。

参考サイト => [Azure App Service と Application Gateway の連携（ルーティング編）](https://www.sigmact.com/updated/zero-to-hero/part6-application-gateway/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/e62acae8-624c-4ad5-85e2-2309067a9d2c.png)

次はバックエンドに AKS のリソースを追加して、マイクロサービスのアーキテクチャに役立つような Application Gateway の使い方をまとめてみようかと思います。
LTEルーターWN-CS300FR（Rakuten UN-LIMITなど）でVPNを使用する

##　LTEルーターWN-CS300FRでVPNを使用する場合
Cisco の  AnyConnect Secure Mobility Client など　在宅勤務の場合使用することが多い. 
この場合、LTEルーターWN-CS300FR側で　設定を変更しないといけない。  
LTEルーターのプライベートIPアドレスをブラウザに打ち込んで管理画面に接続し. 
### [PPTPパススルー］［IPSecパススルー］を［有効］に変更


https://www.iodata.jp/support/qanda/answer/s30540.htm
Google検索したらタイトル長が短かった件

## はじめに

`Googleのコーディング面接で使えるかもしれないKosarajuと ...`──Googleで検索すると、このような検索結果がQiitaの記事に表示された。`Kosaraju`と`Tarjan`の両方のキーワードがタイトルとして出て欲しいのに、片方しか出ないことに引っかかった。

`誰でもたった1分で1万円の現金をラクラクGET！ - 消費者庁`──Googleで検索すると、このような検索結果が表示されることを、[ITmedia](https://www.itmedia.co.jp/news/articles/2108/30/news131.html)は記事で公表した。消費者庁が詐欺的なページを公開しているかのようにも見えるということだ。

ITmediaは、Webページのタイトルを生成する新しいシステムを導入したのが原因としたが本当だろうか？ページ内で目立つコンテンツなどを考慮したページタイトルを自動生成するというものだ。

## ページタイトルの自動生成？

> 「誰でもたった１分で１万円の現金をラクラクＧＥＴ！」などとうたい多額の金銭を支払わせる事業者に関する注意喚起

PDFファイルのタイトルが`誰でもたった1分で1万円の現金をラクラクGET！ - 消費者庁`に変わったのは、「」の中を取って英数字を半角にして後ろにハイフンとドメイン名を付けたものだと思う。

「」の中を取っただけでページタイトルの自動生成とまでは言えないと思う。

> ワイ「Googleのコーディング面接で使えるかもしれないKosarajuとTarjanアルゴリズムを教えて？」

Qiitaの記事のタイトルが`Googleのコーディング面接で使えるかもしれないKosarajuと ...`に変わったのは、「」の中を取ってからタイトルの長さを短くして省略記号...を付けたものだと思う。

## Googleは長いタイトルを省略する

> Googleが検索結果に表示するSEOタイトルのピクセル数には制限がある（現在は580ピクセル）

このような解説が[AuthorityLabs](https://www.authoritylabs.com/title-tags/)にあった。

そこでタイトルのピクセル数を調べるJavaScriptの関数を作ってみた。

### タイトルのピクセル数を調べるJavaScript関数

```javascript
var get_text_width = (text) => {
	const ctx = document.createElement('canvas').getContext('2d');
	ctx.font = '20px Times';
	return ctx.measureText(text).width;
};

var check_title = (text) => {
	var text_width = get_text_width(text);
	var judge;
	if (text_width <= 580) {
		judge = 'OK';
	} else {
		judge = '長すぎる';
	}
	console.log(judge, Number(text_width.toFixed(1)), '"' + text + '"', text.length + '文字');
};
```

フォントの種類を変えるとピクセル数が変動する。Timesにしたが、Googleがどのフォントを基準にしてピクセル数を計測するか分からなかった。

### タイトルのピクセル数を調査

この関数でQiitaの記事のタイトルのピクセル数を調べた。

> 長すぎる 801.9 "Googleのコーディング面接で使えるかもしれないKosarajuとTarjanアルゴリズムを教えて？" 51文字
>
> 長すぎる 581.9 "Googleのコーディング面接で使えるかもしれないKosarajuとTarjan" 40文字
>
> OK 531.1 "Googleのコーディング面接で使えるかもしれないKosarajuと" 34文字

`Googleのコーディング面接で使えるかもしれないKosarajuと`までタイトルの長さを減らすと580ピクセルに収まった。これに省略記号...を付けるとGoogleの検索結果で表示されるタイトルになる。

## さいごに

Goolgeの検索結果でQiitaの記事のタイトル長が短かったことに引っかかった。JavaScriptの関数を作ってSEOタイトルとピクセル数を調べた。

Googleの検索結果で表示されるタイトルについて次のように考えた。

- 580ピクセルに収まるようにタイトルの長さを短くして省略記号...を付ける。
- タイトルの長さを短くするために「」の中を取る。

Qiitaの記事でもSEOを考えて580ピクセル（全角で29文字）に収まるタイトルにするのがいいと思う。
マジックナンバー使うな? どんどん使え!

# マジックナンバー使うな? どんどん使え!
マジックナンバー使うなって言われません? 私も昔はそう思ってたんですよ。

そうでもないなあと最近思い始めたわけでして。


## よくある「マジックナンバー使うな!」
消費税の税額を求めるプログラムがあるとします。(軽減税率とかいろいろありますが、面倒なので一律 10% ってことにします)

```csharp
Console.WriteLine(税抜金額 * 0.10m);
```

このままだとよくないってお話ですね。

* `0.10m` が何のことか、コードを書いた本人以外にはわからない
* `0.10m` がコードのあちこちに散在することになる
  - タイプミスする人が出てくる
  - 消費税率が変わった時の修正量ががが

っていう理由で `0.10m` っていうマジックナンバーじゃなくて、定数化しなさいって言われます。

```csharp
const decimal 消費税率 = 0.10m;
```

って定数にしておいて

```csharp
Console.WriteLine(税抜金額 * 消費税率);
```

こういう風にしなさいってことですね。


## 定数化なんて役に立たない
名前を与えてわかりやすくするのはいいことなんです。消費税率をタイプミスする人も減るでしょう。でも、`* 消費税率` じゃなくて `+ 消費税率` とかタイプミスしたらどうでしょうか?

いちゃもんっぽいですけど。(笑)

このケースでは、定数化するよりは「消費税額は税抜き金額の 10% 分」という仕様に合わせて関数を書いたほうがすっきりします。

```csharp
decimal 消費税額(decimal 税抜金額)
{
    return 税抜金額 * 0.10m;
}
```

このように関数を用意しておいて、利用するわけです。

```csharp
Console.WriteLine(消費税額(税抜金額));
```

ここで `0.10m` とマジックナンバーを使いましたけど、消費税額の計算なのは明白ですし、掛け算を利用している以上税率なのもわかります。ですので、定数化する理由はほとんどなくなるんじゃないかと。

仕所得税の所得控除額とかのややこしいのになると、定数化したほうがわかりにくくなります。

```csharp
const decimal ランク1上限 = 1_625_000;
const decimal ランク1控除額 = 650_000;
const decimal ランク2上限 = 1_800_000;
const decimal ランク2控除率 = 0.40m;
// 以下省略...
```

```csharp
if (収入金額 <= ランク1上限)
{
    Console.WriteLine(ランク1控除額);
} 
else if (収入金額 <= ランク2上限)
{
    Console.WriteLine(収入金額 * ランク2控除率);
}
// 以下省略...
```

これをわかりやすいという人はいないと思います。わかりにくいだけならまだしも、タイプミスを防げません。`ランク3上限` のところを `ランク2上限` とタイプミスしても気が付かないでしょう。

また、定数化しておくと変更に強くなるといわれますが、このケースではめったに当てはまりません。

ランク1上限が引き下げられた場合は定数の値の修正でも対応できますが、次のケースでは定数の値の修正だけでは対応できません。

* ランクが増減した
* ランク 2 の控除額が「収入金額 * 40%」から「収入金額 * 40% + 5 万円」に

現実には定数の値の修正では足りない変更が入る確率のほうが高いでしょう。

次のように定数を使わずに関数化したほうがよっぽどいいです。

```csharp
decimal 給与所得控除額(decimal 収入金額)
{
    if (収入金額 <= 1_625_000) return 650_000;
    if (収入金額 <= 1_800_000) return 収入金額 * 0.40m;
    // 以下省略...
}
```


## 最後に
ほとんどの処理には名前があります。「消費税額」や「所得控除額」という仕様にある名前をそのまま関数にして、仕様と同じになるように実装を書きます。それをすれば、定数化はほとんど必要ないでしょう。

誤解してほしくないのは、定数化絶対ダメってわけじゃないことです。「マジックナンバーはだめだから定数かしろ」っていうルールだけをうのみにすると逆効果になるよっていうことです。(もしかしたら、このドキュメントに書いたルールもそうなのかもね)
人生で一番長くリファクタリングやった話

# 誰に向けたどんな記事か

とても幸運なことにフロントエンドエンジニアとして
長い期間リファクタリングする機会に恵まれた

リファクタリングで色々経験したことで
次からはこれをやっておくといいかも
と思えるものをいくつか見つけたので

これから大きなシステムを作る人や
今からリファクタリングをするんだという人に

「なるほど、これはやっておくべきかもしれない」
と少しでも「気づき」を共有できれば嬉しい

# やってみてほしいランキング

## 第1位 E2Eテストの自動化

**E2Eを自動化することで
リファクタリングや、その後の機能追加作業でデグレする危険性が下がった**


:::note info
[E2E (End to End) テスト]
 画面操作（Web ブラウザの操作）により
 想定通りの動作となっていることを確認するテスト
:::

リファクタリングをする前にまずE2Eテストの自動化を行った
これは本当に正解だった

プログラムを変更するたびに
どこかしらでバグが発生してないか
手動で都度確認を行なっていてはあまりにも時間がかかる

E2Eを自動化することでこの手間を大幅に省くことができた
リグレッションテストとして非常に優秀だと感じた

:::note info
[リグレッションテスト] 
プログラムの変更・修正の際に
他の機能に問題ないか影響を確認するテスト
:::

開発期間が長いほど、E2Eテストは自動化した方がいい
テストを作る手間を加味したとしても恩恵がある

全てのE2Eテストを自動化する必要はない
止まっては困る必須の機能を確認できる自動E2Eがあれば
それが動くことを開発中に確認するだけで
少なくとも致命的なデグレは避けることができる

細かい機能のE2Eの自動化は
テスト自体の管理コストもあるので
プロジェクトごとで要相談してほしい

### いつ導入すべきか

**「この機能が動いていれば大丈夫」
が言えると嬉しい時**

基本的な処理ができあがって
直近に大きな変更が無い状態になったら
必要最低限の機能だけでもE2E自動化しておくと良い

見た目にはわからない他の細かいプログラムの修正の際に
それが動くことを確認できれば安心して開発を進めることができる

:::note info
E2E自動化ツール「playwright」
・動画やスクショが簡単に撮れる
・画面操作を自動でコード化する機能がある
:::


## 第2位 DI(依存性の注入)

**DIを行うことで
APIの開発とフロントの開発を同時に進行できるようになった**

> 依存性の注入（いそんせいのちゅうにゅう、英: Dependency injection）とは
コンポーネント間の依存関係をプログラムのソースコードから排除するために、
外部の設定ファイルなどでオブジェクトを注入できるようにするソフトウェアパターンである。
英語の頭文字からDIと略される。
引用： [Wikipedia 依存性の注入](https://ja.wikipedia.org/wiki/%E4%BE%9D%E5%AD%98%E6%80%A7%E3%81%AE%E6%B3%A8%E5%85%A5)

具体的にはaxiosによるAPIの呼び出し処理を
nuxtのinject機能を使ってグローバル関数とし
登録し共通処理で呼び出せるようにした

関数のreturn値をAPIからの返り値ではなく仮のJSONなどにすることで 
APIが無くてもフロント側は実装を進められる

### いつ導入すべきか

モックアップを作り始める段階から可能な限り行なっておきたい
むしろモックアップの段階で一番効力を発揮する

## 第3位 JESTのユニットテスト

**チームでリファクタリングをするうえでの基準にできた
ユニットテストを軸にして自然とコードの画一化が行えた**

チームでコーディングしていると
書くコードのルールがバラバラになっていた

リファクタリングでどんなコードを目指したらいいのかもわからなかったので
鶴の一声 「テストが書きやすいコードがよいコードです」に従い
テストが書きやすいコードを目指すことにした

結果「テストが書きやすいコードがよいコードを書く」
という共通認識をもちながら作業することになったため
意識してルールを作らずとも、自然とコードの書き方も統一されていった

テストそのものがバグを見つけ出す効果よりも
どちらかといえばチーム作業のしやすさに大きな効果があった

1. やりたいテストを書く
1. そのテストがしやすくなるようにコードを直す  

一括で全て直そうとせず上記の流れを何度か繰り返すことで
次第に読みやすいシンプルなコードへと変化していった
主に以下のような修正を行った

- テストパターンを減らしたい → 条件分岐を減らす  
- Mockをしやすくしたい　→ 依存関係をなくす（DI）  

### いつ導入すべきか

E2Eと同じで、リファクタリングの前が良いと思う
もしくは同時でも良い
テストが書きにくいと感じた時点でコードに問題がある

テストから書く場合はテスト駆動開発になるのだろうけど
これは経験したことがないのでわからない

ユニットテストとして効力を発揮しているのかは
まだ体感としては得られていないので難しいところ

# まとめ

一ヶ月以上かけてこれらを経験し
非常に良い勉強になった

コードを書くときの意識がかなり変わったし
より効率的に書けないか常に意識するようになったと思う

プロジェクトの期間や傾向で導入が難しいものがあるのも理解できるが
少しでも参考になることがあれば嬉しい
TrueNASに幾つかアプリケーションを入れて使ってみた：gitlab編

参照元：[TrueNASにアプリを幾つか入れて使ってみた
](https://qiita.com/exthnet/items/523396d4bfedf04674b5)

TrueNASのCommunityプラグイン（Third partyアプリ）にgitlabがあったので試してみた。

（gitlabの説明はいまさら要らないと思うのでしない。）

インストール自体はINSTALLを押すだけ。（手持ちの環境ではインストールに結構時間がかかった。あくまでNextcloudやPlexと比べて、であるが。途中で「invalid option: -har」とか見えるので不安を感じる……。）
インストール後、設定したIPアドレスにアクセスすると「502 Bad Gateway」をくらって困ったが、シェルを起動して`service gitlab onestart`したら解消した。根本的な原因は不明。

設定したIPアドレスにブラウザでアクセスするとパスワードの変更を要求され、設定するとめでたくrootとしてgitlabが利用可能になる。

リポジトリの保存先は`/usr/local/www/gitlab-ce/config/gitlab.yml`の`4. Advanced settings`の`path`で指定されており、インストール時のデフォルト値は`/usr/local/git/repositories/`であった。jailからjail外のディレクトリは通常は参照できないため、jail外のディレクトリを使いたいときはjailのMount PointsのADDで適当なディレクトリをマウントし、gitlab.ymlでそのパスを指定するのが良い。（マウント設定の例は[TrueNASに幾つかアプリケーションを入れて使ってみた：Nextcloud編](https://qiita.com/exthnet/items/49cb2229a256feb1db52)も参照。）
repositoriesディレクトリの中身については、リポジトリそのものは`@hashed`に格納されているが、その他に`.gitaly-metadata`と`+gitaly`も置かれている。少なくとも全てマウント先にコピーしてしまえば正しく動くようだ。（`cp -a`でコピーしたら動いた。）

gitlabは様々な機能を有しているため、もしかしたら何かしっかり設定をしないとうまく使えない機能があるかもしれないが、そのあたりは気がついたら書く予定。
送信ボタンがdisabledのときにテキスト入力欄でEnterを押すと、フォームはどうなるか

送信ボタンがdisabledのときにテキスト入力欄でEnterを押すと、フォームはどのような動きをするでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308595/74862c88-9bf5-01e5-2f72-43d917ffce71.png)
ChromeとFirefoxで試すと、フォームは送信されません。ところが、Safari（macOSもiOSも）では送信されてしまいます。Rails的に言えば、data-disable-withを使うだけではフォームの二重送信を防げないということです。

この挙動はHTMLの仕様ではどうなっているでしょうか。ググったところ、Stack Overflowで次のような記述に行きあたりました。

- https://stackoverflow.com/questions/5629805/disabling-enter-key-for-form#answer-42806658

> Consequently, if the default button is disabled, the form is not submitted when such an implicit submission mechanism is used. (A button has no activation behavior when disabled.)
> https://www.w3.org/TR/html5/forms.html#implicit-submission

「フォームは送信されない」のがHTML5の仕様で、Safariは間違っているようです。

現在の仕様書である[HTML Living Standard](https://html.spec.whatwg.org/)を見てみましょう。テキスト入力欄でEnterを押す話は「4.10 Forms」の「4.10.21.2 Implicit submission」（暗黙の提出）という項に書かれています。

- [4.10.21.2 Implicit submission](https://html.spec.whatwg.org/#implicit-submission)

なんと "Consequently, if the default button is disabled, the form is not submitted when such an implicit submission mechanism is used." の部分がありません。

HTML Living Standard のテキストは、[Githubのレポジトリ](https://github.com/whatwg/html)で管理されています。「Implicit submission」に「Consequently ...」の文があるかないかで時期を絞って探していくと、次のコミットが見つかりました。

- [Align activation behavior with changes to DOM Standard](https://github.com/whatwg/html/commit/7beb920ba2e1a71246b81d86005f223a0d7ac8ab)

2016年10月21日に、「Consequently ...」の文が消されています。その理由は関連するIssueなどを調べるヒマがないので、わかりません。

__結論:__

送信ボタンがdisabledのときにはEnterを押してもフォームは送信されない、という決まりはHTMLの仕様（HTML Living Standard）にない（以前はあった）。Safariは間違っていない。

__対策:__

1. JavaScriptでsubmitイベントを処理して、disabledのときはpreventDefaultする。
2. Enterキーを無効にする。input要素のkeydownかkeypressイベントを処理して、preventDefaultする。
3. form要素を使わずに全部Ajaxで送信する。

わたし的には1.が好きだけど、他の人には分かりにくい。2.は分かりやすいけど、かっこ悪い気がする。
scala sparkの勉強備忘録④ ~spark sqlでdataframeのarray listのカラムにあれこれ~ 

## データ作り
```
scala> val t1 = Array(35, 36, 32, 30, 40, 42, 38)
t1: Array[Int] = Array(35, 36, 32, 30, 40, 42, 38)

scala> val t2 = Array(31, 32, 34, 55, 56)
t2: Array[Int] = Array(31, 32, 34, 55, 56)

scala> val tC = Seq(t1, t2).toDF("celsius")
tC: org.apache.spark.sql.DataFrame = [celsius: array<int>]

scala> tC.show()
+--------------------+
|             celsius|
+--------------------+
|[35, 36, 32, 30, ...|
|[31, 32, 34, 55, 56]|
+--------------------+

scala> tC.createOrReplaceTempView("tC")
# これでspark.sqlで色々弄れるっぽい
# ()内の文字列をspark.sqlでのfromで指定する形になる
```

## transform（）
arraylistの全体の値を色々弄れる

 ```
scala> spark.sql("""
     | SELECT celsius, transform(celsius, t -> ((t*9) div 5) + 32) AS fahrenheit
     | FROM tC
     | """).show()
+--------------------+--------------------+
|             celsius|          fahrenheit|
+--------------------+--------------------+
|[35, 36, 32, 30, ...|[95, 96, 89, 86, ...|
|[31, 32, 34, 55, 56]|[87, 89, 93, 131,...|
+--------------------+--------------------+
# divは除算の小数点切り捨て
```
## filter()
listのデータを条件付けで抽出する

```
scala> spark.sql("""
     | SELECT celsius, filter(celsius, t -> t>38) AS high
     | FROM tC
     | """).show()
+--------------------+--------+
|             celsius|    high|
+--------------------+--------+
|[35, 36, 32, 30, ...|[40, 42]|
|[31, 32, 34, 55, 56]|[55, 56]|
+--------------------+--------+

scala> spark.sql("""
     | SELECT celsius, filter(celsius, t -> t>38 and t<41) AS soso
     | FROM tC
     | """).show()
+--------------------+----+
|             celsius|soso|
+--------------------+----+
|[35, 36, 32, 30, ...|[40]|
|[31, 32, 34, 55, 56]|  []|
+--------------------+----+
#　複数の条件をつけるときはandとかor
# &だとダメだった
```
## exists()
条件に合う値がlist内にあるかのtrue, false

```
scala> spark.sql("""
     | SELECT celsius, exists(celsius, t -> t=38) AS threshold
     | FROM tC
     | """).show()
+--------------------+---------+
|             celsius|threshold|
+--------------------+---------+
|[35, 36, 32, 30, ...|     true|
|[31, 32, 34, 55, 56]|    false|
+--------------------+---------+

scala> spark.sql("""
     | SELECT celsius, exists(celsius, t -> t>38 and t<41) AS threshold
     | FROM tC
     | """).show()
+--------------------+---------+
|             celsius|threshold|
+--------------------+---------+
|[35, 36, 32, 30, ...|     true|
|[31, 32, 34, 55, 56]|    false|
+--------------------+---------+
#こっちもandで複数行ける
```
Debian系のアンインストールコマンドについて(設定ファイルも含め完璧に消したい場合)

個人用のメモ兼
自分みたいに知らない人の為に

# TL;DR(結論)
2021/09/29変更
　設定ファイルを含め完璧に消したい場合、
```　
  apt remove --purge -y
　apt autoremove --purge -y
　apt autopurge -y
```

# 通常紹介されているアンインストール時のコマンド
```
#apt remove <アンインストールしたい物> -y
#apt autoremove -y
```

これはあくまで、そのソフトウェアの実行ファイルを削除しているに過ぎず、ゴミ(設定ファイル)が残る。


# 設定ファイルも一緒にアンインストールするコマンド

```
#apt remove --purge <アンインストールしたい物> -y
#apt autoremove --purge -y
```


## 2021/09/29追記
apt autopurgeや、apt autoremove --purgeでは削除できないものがあるようです。
この場合aptではなく、aptitudeを使用して設定ファイルの削除を行います。

```
#apt install aptitude -y
#aptitude purge ~c -y
```

また、それでも消えない(パッケージ管理外？)ものはUbuntu Cleanerをおすすめさせていただきます。
Chromeのキャッシュ等も自動で消してくれるので便利です。

以上。
PostgreSQL 14がやってくる(6) - pg_read_all_data/pg_write_all_data

#はじめに
にゃーん。
最近、ばたばたしていたPostgreSQL 14の調査をサボってましたが、また見てみようかなと。
今日は、PostgreSQL 14で追加された定義済みロール[^1]について調べてみました。

# 定義済みロール
定義済みロールは、PostgreSQL 9.6から導入された権限分掌強化のための仕組みです。以降、各メジャーバージョンアップごとにさり気なく増えてます。
それぞれの定義済みロールがどのバージョンで増えたのかは以下の表を見てください。

|ロール名|9.6|10 |11 |12 |13 |14 |
|:--               |:--|:-:|:-:|:-:|:-:|:-:|
|pg_signal_backend|●  |●  |●  |●  |●  |●  |●  |
|pg_read_all_settings|-  |●  |●  |●  |●  |●  |
|pg_read_all_stats|-  |●  |●  |●  |●  |●  |
|pg_stat_scan_tables|-  |●  |●  |●  |●  |●  |
|pg_monitor|-  |●  |●  |●  |●  |●  |
|pg_read_server_files|-  |-  |●  |●  |●  |●  |
|pg_write_server_files|-  |-  |●  |●  |●  |●  |
|pg_execute_server_program|-  |-  |●  |●  |●  |●  |
|pg_read_all_data|-  |-  |-  |-  |-  |●  |
|pg_write_all_data |-  |-  |-  |-  |-  |●  |
|pg_database_owner|-  |-  |-  |-  |-  |●  |

# PostgreSQL 14で増えたデフォルトロール
PostgreSQL 14では以下の3つのデフォルトロールが追加されました。

|ロール名|概要|
|:--|:--|
|pg_read_all_data|すべてのテーブル、ビュー、シーケンスに対する読み取り権限を与える。|
|pg_write_all_data|すべてのテーブル、ビュー、シーケンスに対する書き込み権限を与える。|
|pg_database_owner|データベース所有者に一致する定義済みロール。<br>テンプレートデータベースで有用。 |

これらのロールはログイン権限を持っていないので、それ単独でログイン用のユーザとしては使えません。他のロール（ユーザ）にこのロールをメンバとして持つようにGRANT文で設定が必要です。

今回の記事では、上記のうち``pg_read_all_data``と``pg_write_all_data``についてPostgreSQL 14 beta3で動作確認した内容を紹介します。

# 検証モデル
今回の検証では、最初に以下の3つの一般ユーザ（ログイン権限をもったロール）を作ります。

## ユーザと付与するロール
|ユーザ名|このユーザの役割|付与するロール|
|:--|:--|:--|
|db_owner|データベース所有者。そのデータベースに対してなんでもできる。ローカルな神|なし（データベース作成時に所有者に指定する）|
|data_admin|業務データの参照/更新を行うユーザ|pg_read_all_data<br>pg_write_all_data|
|viewer|業務データの参照のみを行うユーザ|pg_read_all_data|

## 作成するデータベース/スキーマ/テーブル

* testdb というデータベースを作成し、所有者を db_owner に設定する。
* db_ownerがtestdb データベースの下にtestスキーマを作成する。
* db_owverがtestスキーマ内にfooテーブルを作成する。

## data_admin/viewerユーザの挙動
上記の設定により、data_admin/viewerユーザは以下のように動作する。

|操作|data_admin|viewer|
|:--|:--|:--|
|testスキーマ上に任意のテーブルを作成する|権限エラー|権限エラー|
|fooテーブルのSELECT|成功|成功|
|fooテーブルのUPDATE|成功|権限エラー|
|fooテーブルのDELETE|成功|権限エラー|
|fooテーブルのTRUNCATE|権限エラー|権限エラー|

ちょっと面白いことに、``pg_write_all_data``を付与した``data_admin``は、DELETEはできるけど、TRUNCATEはできない。
また、今回は``data_admin``には``pg_write_all_data``と``pg_read_all_data``を付与しているが、``pg_write_all_data``しか付与しない場合は、**INSERTはできるけどUPDATEもDELETEも権限エラーになる。**
動きを考えればまあ、そうかとなるんだけど（UPDATEもDELETEもWHERE句での評価を行う以上、対象の行を読めなければいけない）、[PostgreSQL 14 beta3文書のTable 22.1](https://www.postgresql.org/docs/14/predefined-roles.html)を見ると

> Write all data (tables, views, sequences), as if having INSERT, UPDATE, and DELETE rights on those objects, and USAGE rights on all schemas, even without having it explicitly. 

と書いてあって、一見すると``pg_write_all_data``ロールだけ付与すれば、INSERT/UPDATE/DELETEが出来るようにも読めちゃうのよなあ。にゃーん。

# おわりに
ということで、PostgreSQL 14の``pg_write_all_data``と``pg_read_all_data``をうまく使うと、データ更新をさせたいユーザと参照のみしかさせないユーザの管理を簡単にできるかも？という話でした。

# 参考
以前のバージョンの定義済みロール（デフォルトロール）については、以前自分が調べた記事も参考にしてください。

* [監視用デフォルトロール](https://qiita.com/nuko_yokohama/items/6debdd3291c8f27d1da8)
* [PostgreSQLのロール](https://qiita.com/nuko_yokohama/items/085b75ee4c0938936ab9)
 


[^1]: PostgreSQL 13まではデフォルトロール（Default Role）と呼ばれていました。呼び方自体、PostgreSQL 14で変えたみたい。
[Git] 最近のブランチを探す

いろんなブランチで作業しているときに、迷子になることがある。一昨日使っていたブランチの名前が思い出せないときに、この記事の手法を覚えておくと便利。

# 結論

`git branch --sort=-committerdate` とすれば、最近コミットした順にブランチがソートされて表示される。


```shell-session
$ git branch --sort=-committerdate
* feat-add-key-value
  staging
  start-abtest
  stop-abtest
  remove-xxxx
```

git branch の sort オプションが使って実現している。

公式ドキュメント: https://git-scm.com/docs/git-branch#Documentation/git-branch.txt---sortltkeygt


# 昇順/降順の変更

`-` をつけるだけで変更できる。

* `--sort=<key>` 昇順
* `--sort=-<key>` 降順


# key にできるもの

[git-for-each-ref](https://git-scm.com/docs/git-for-each-ref) のドキュメントに書いてある。たくさん指定できるものはあるが、 sort したときに実用的なものは次に挙げるものだけだろう。

* `committerdate`
* `authordate`
* `creatordate`
* `taggerdate`


# Alias による便利な活用

Git には Alias という機能が用意されているので上記のオプションを覚えなくて済む。公式ドキュメント: https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-Git-%E3%82%A8%E3%82%A4%E3%83%AA%E3%82%A2%E3%82%B9

```shell-session
$ git config --global alias.br 'branch --committerdate HEAD'
```

としておけば、次からは `git br` で最近コミットされた順でブランチ一覧を表示できる
【デザインパターン】JavaScriptで学ぶBridge

#はじめに
現在デザインパターンについて勉強中です。
今回はBridgeついてまとめました。

https://qiita.com/suzuki0430/items/d44a83c500993a763c1d

https://qiita.com/suzuki0430/items/abbb433fd49e356e8643

#Bridge
Bridgeはクラスの余計な拡張を防ぐために橋渡しとなるクラスを使う、構造に関するデザインパターンの一つです。

例えば、`Circle`クラスと`Square`クラスが存在するとき、描画方法に関する派生クラス`VectorRenderer~`と`RasterRenderer~`を考えると以下のようになります。
![スクリーンショット 2021-09-05 16.36.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/4de38aaf-ad93-9b17-3b76-0501ca50ad6a.png)
このとき、`VectorRendererCircle`や`VectorRendererSquare`は描画方法が共通なので似たような性質をもち、実質同じようなクラスが2つあることになります。
また、新しい派生クラスを追加しようとすると、`~RendererCircle`と`~RendererSquare`が新しく作られ、コードの重複がさらに増えていってしまいます。

このような問題を解決するために、Bridgeパターンを使います。
まずは親クラス`Shape`と`Renderer`を用意し、それぞれから形状に関するクラスと描画方法に関するクラスを派生(継承)します。

- Shape - Square, Circle, Triangle, ...
- Renderer - Raster, Vector, ...

そして、`Shape`から派生する継承関係は形状のみで、描画方法に関する情報は`Renderer`クラスに委譲(`Renderer`のインスタンスを生成して`Shape`のconstructorに渡す)します。
この構造によって、形状と描画方法はそれぞれ独立して拡張することができ、クラスの数も減らすことができるようになります。
![スクリーンショット 2021-09-05 16.37.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/87e1a4d0-fe7c-83f9-ce4d-c93f8cc2d1e3.png)

#実装例
以上の内容を実装したのがこちらです。
簡単のため、`Shape`から`Circle`クラスのみを派生させて検証しました。

```js
class VectorRenderer
{
  renderCircle(radius)
  {
    console.log(`Drawing a circle of radius ${radius}`);
  }
}

class RasterRenderer
{
  renderCircle(radius)
  {
    console.log(`Drawing pixels for circle of radius ${radius}`);
  }
}

class Shape
{
  constructor(renderer)
  {
    this.renderer = renderer;
  }
}

class Circle extends Shape
{
  constructor(renderer, radius) {
    super(renderer);
    this.radius = radius;
  }

  draw()
  {
    this.renderer.renderCircle(this.radius);
  }

  resize(factor)
  {
    this.radius *= factor;
  }
}
```
描画方法に関するクラスのメソッドについては委譲で使用するため、以下のようにインスタンス(`raster`, `vector`)をつくって`Circle`に引数として渡しています。

```js
let raster = new RasterRenderer();
let vector = new VectorRenderer();
let circle = new Circle(vector, 5);
circle.draw();
circle.resize(2);
circle.draw();
```
結果以下のようになります。

```
Drawing a circle of radius 5
Drawing a circle of radius 10
```

#参考資料

https://www.udemy.com/share/101Bpe3@Wapeed1JE99zGyDGeFWUwPUAL8i7H6iKQ0y-TtL-LINIEnzqVstotj7Ap-XFh22W/

https://www.te-nu.com/entry/2017/11/07/190000
実務未経験でエンジニア転職して感じること。〜5ヶ月目〜

##はじめに
さあ、やって参りました5ヶ月目の振り返りです！あと1ヶ月で半年！！はやい！
**[1ヶ月目](https://qiita.com/makky/items/7fff5aeb1005ce6caf44)**から記事は書いていますが、なぜか**[2ヶ月目](https://qiita.com/makky/items/ba83d51911e1cb39b0ed)**だけ閲覧数が
100倍近くになっていました。。ナゼ？と思いつつ、見ていただけたのは嬉しいです。
ありがとうございます！！！
**[3ヶ月目](https://qiita.com/makky/items/de20b90b74c1ba6acfd1)**、**[4ヶ月目](https://qiita.com/makky/items/8f55ad057d973f45ad49)**も更新していますので
もしよければあわせて読んでいただければと思います！
それでは8月、入社して5ヶ月目の振り返りしていきます！よろしくお願いします！


##この１か月（入社後4ヶ月〜5ヶ月）をざっと振り返る
先月の記事に書かせていただいた開発のリリースを終え、ほっとしている間に夏休み。

![natsuyasumi_title.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883905/351658ca-fea8-b79e-77e8-0a5203b0a2cb.png)

（この画像気に入って使いたかっただけ）


夏休みはせっかくならということで、**[こちらのサイト](https://nn-hokuson.hatenablog.com/entry/2016/07/04/213231)**見ながら、
初めてunityを触ってみたり、実務で使用しているPHPを勉強し直しました。
自分の興味のまま何かをやってみる触ってみるのは楽しいと改めて思ったり。

夏休み明けからは新たな開発に携わらせていただきつつ、開発以外で新しいお仕事もあり
相変わらず楽しいですが、時間があっという間すぎて、少し焦ったり。
開発には**細切れの時間ではなくまとまった時間が必要**という点をひしひし感じています。
30分や1時間では、前回どこまでやったっけ、、？と振り返っているうちに終わってしまうので
時間の確保の工夫はこれから必要だなと。


ここで恒例の今月1ヶ月でおもしろかった、勉強になった記事です。
・**[良いコードとは何か](https://note.com/cyberz_cto/n/n26f535d6c575)**
・**[【新人プログラマ応援】学習用のプログラムと仕事で書くプログラムは何が違うか](https://qiita.com/jnchito/items/c9ca22efa270ff1b7f3d)**
そうです。実は**[2ヶ月目](https://qiita.com/makky/items/ba83d51911e1cb39b0ed)**の記事でも同じものをあげていました。
当初は何となくの理解だったものが、ふと読み返すと理解が深まっていたことに気づけたので
今回はあえて同じ記事をピックアップしてみました。


##１番印象に残ったトピック
###障害対応の緊張感、、

![computer_error_bluescreen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883905/9846af31-ffb5-f6e7-259d-18d7dee7dcf3.png)
（緊張感はこの画像の比じゃない）

まだまだ仮説を立てて切り分けて、原因を見つけて、、、という流れを全て自分で
できているわけではなく、ログをとってきたり、先輩が立てた仮説の検証、調査も多いです。
それでも障害が起こって、解決するまでの緊張感は慣れない、、解決した時のホッとした感はすごい。
障害対応を通して、**仮説を立てる前に情報を正確に把握すること**の重要性を感じました。
「＊＊だから〇〇だろう」の仮説の**＊＊の部分を正確に、事実を把握する必要がある**なと。
文字にすると当たり前やろってツッコミも入りそうですが、これが難しいです。
気づけば〇〇だろうの仮説部分に引っ張られいるのか
「**（多分）**＊＊だから〇〇だろう」、「＊＊な**はず**だから〇〇だろう」みたいなことになっているんですよね。。危ない。

**正確に事実を把握する**というのは障害対応以外でも、例えば不具合やエラー調査でも重要だなと。
極端ですが、
**「何かエラーになる」**と
**「Aの画面でBの操作をした時にCのエラーメッセージが表示される（キャプチャ付き）」**では
そのあとの進め方も進捗速度も全然違うかなと思います。

事実を正確に把握することはログを見て分かる部分もありますが、
ヒアリングも重要だと思うので、このあたりのスキルも伸ばしていきたいです。


###雑談
チーム内でオンライン懇親会を開催しましたが、その時に「**死ぬまでにやりたい100のこと**」を
スプレッドシートを共有しながら各自作成してみました！これが結構おもしろかったです。
それぞれ似ている部分もあれば全然違った部分もあり、
皆さんのパーソナリティの理解に繋がった感覚がありました。
個人的には他にも100はいかなくても半分の50ぐらいまでは
スラスラ出てくるのではと思っていましたが、意外にも**30ぐらいで手が止まりました**。
やりたいこと実はあんまりない、、？思いついたら追記していきたいです。
あとは後日、実行に移したくなり調べたりしていくうちに、
実現方法を具体的に考えるようになったり、**更に１つ実際に叶えられたり**。
とても発見が多い時間でした。




##最後に
8月は夏休みもあり、本当にあっという間でした。。記事も少しさっぱりめかも(?)
少しずつですが前に進んでいる感覚はあるので、この感覚を継続できるようにしていきたいです。
未経験から転職したエンジニアがどうなっていくのか、、、~~乞うご期待！~~ 



【初学者向け】JavaScriptの『forEach / for of / for in』のまとめ

配列を使い
-for文
-for in
-for of
-forEach 
の違いをまとめてみました。


##事前準備

①まずはこのような**配列**を用意します。(添字と混ざらないように奇数にしてます。)

```js
const arry = [1, 3, 5, 7, 9];
```

**②変数名は自由につけることが可能**ですが、

**[for文/for in]** の場合は
`iを使用(※index(添字)の意味がある）`

**[for of]** の場合は
`vを使用(※value(値)の意味がある)`

しています。

##①『for文』だと
```js
for(let i = 0; i < arry.length; i++) {
    console.log(i);         //0 1 2 3 4   (インデックス取得)
    console.log(arry[i]);   //1 3 5 7 9   (インデックスを使って配列の値を取得)
}
```

##②『for in』だと
**point: indexが取得できる。ひと手間いるが値が取得できる**

```js
for(let i in arry) {
    console.log(i);          //0 1 2 3 4   (インデックス取得)  
    console.log(arry[i]);    //1 3 5 7 9   (for文同様この形で値取得)
}
```

##③『for of』だと
**point: 値が簡単に取得できる。対応していないブラウザがある。**

```js
for(let v of arry) {
    console.log(v);          //1 3 5 7 9    (すぐに値を取得)
}
```

##④『forEach』
**point:変数の定義がないのでスッキリ記述できる。引数を3つ取れる。**

```js
arry.forEach((v, i, arry) => {
   console.log(v);                 //1 3 5 7 9
   console.log(i);                 //0 1 2 3 4
   console.log(arry);              //[1, 3, 5, 7, 9] [1, 3, 5, 7, 9] [1, 3, 5, 7, 9] [1, 3, 5, 7, 9] [1, 3, 5, 7, 9]
 })
```


##まとめ
慣れるまではfor文からfor in を使うのがいいのかなと感じます。
慣れてきたらforEachがおすすめです。
【MySQL】GROUP_CONCATの結果が切れていたりNullで返ってくる

## GROUP_CONCATの結果が切れている…
MySQLでGROUP_CONCATを利用して、Group Byの結果の文字列を結合させたところ、結果の文字列が途中で切れていたことがわかりました。
そういうときはドキュメントを参照しましょう
[GROUP BY (集約) 関数 - GROUP_CONCAT](https://dev.mysql.com/doc/refman/5.6/ja/group-by-functions.html#function_group-concat)
>結果は、group_concat_max_len システム変数で指定された最大長まで切り捨てられます。

ということなのでgroup_concat_max_lenの値を確認

```sql
show variables like 'group_concat_max_len';
```
を実行すると `1024` が返ってきました。実際の文字列ををみると1024だったのでこれを変更すれば良さそうです。
my.cnfのを編集すればいいのですが、今回はとりあえず

```sql
SET GLOBAL group_concat_max_len = 1000000;
```
と修正後に再度SELECT文を実行したところ想定していた文字列が返ってきました。

## GROUP_CONCATの結果がNull
上記対応で想定していた文字列が返ってきていたのですが、一部何故かNull値が返ってきていました。こちらも[ドキュメント](https://dev.mysql.com/doc/refman/5.6/ja/group-by-functions.html#function_group-concat)を確認すると
>戻り値の有効な最大長は、max_allowed_packet の値によって制約されます。実行時に group_concat_max_len の値を変更するための構文は、次のとおりです。ここで、val は符号なし整数です。

戻り値が大きすぎるために、制約を受けていたようです。

```sql
show variables like 'max_allowed_packet';
```
これも現在の値を確認後

```sql
SET GLOBAL max_allowed_packet = 123456789;
```

と一旦十分に大きい値を設定して一度SQLを試したところ、Nullではなく欲しい値が返ってきていました。
もちろんmax_allowed_packetは大きければ大きいほどよいというわけではなさそうなので、サーバーや実際に取得する値を考えて設定するべきでしょう。
[備忘録] IntelliJ系のエディタでキャレット位置をファイル先頭や末尾に移動させたい

## IntelliJ系のエディタでキャレット位置をファイル先頭や末尾に移動させたい
- VSCodeやXcodeだと `⌘↑`　でファイル先頭、 `⌘↓` でファイル末尾にキャレット位置を動かしたり `⌘⇧↑` や `⌘⇧↓` で行選択しながらキャレット位置を動かせるのですが、IntelliJ系のエディタだとデフォルトで `⌘↘︎` `⌘↖️`　や `⌘⇧↘︎`　や `⌘⇧↖️` というキーマップが割り当たっていて、他のエディタと同じような操作ができず戸惑うことがあったので、備忘録的にキーマップ変更の方法を書いておこうと思います。

## 設定
- Preferences -> Keymap -> 検索バーに `move caret to text` と入力

![スクリーンショット 2021-09-05 16.51.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84888/458b14a7-293a-0ee1-f1b5-44221827dabe.png)

- それぞれのKeymapに対して `Add Keyboard Shortcut` から、ショートカットキーを設定する

![スクリーンショット 2021-09-05 16.58.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84888/0642dbe1-3f48-d465-47b6-21e087618d37.png)
コンピュータ回路について　[論理演算]

#そもそもコンピュータの回路とは

コンピュータは電気のオンオフで物事を考えている

**<font color="red">1ならオン、0ならオフ</font>**

そしてコンピュータは論理演算によって処理を行なっている

###論理演算とは

**1を真、0を偽として処理を実行すること**

この処理を実行するためには論理回路という論理演算するための回路が必要

##回路の種類

論理積（AND回路）　→  ○◯ かつ　　××　　　→ <font color="red">これに当てはまれば　"1" </font>→ 電気オン

論理和（OR回路）　　→  ○◯ または　　××　　　→ <font color="red">これに当てはまれば　"1" </font>→ 電気オン

否定（NOT回路）　　→  ○◯ ではない　　　→ <font color="red">これに当てはまれば　"1" </font>→ 電気オン

これら３つを**<font color="red">基本回路</font>**という

##組み合わされた回路

３つの回路だけでは拾いきれないものがたくさんある

否定論理積回路（NAND回路）
　→  ○◯ かつ　　××　　<font color="red">ではない</font>　→　これに当てはまれば　"1" 

否定論理和回路（NOR回路）　
　→  ○◯ または　　××　　<font color="red">ではない</font>　→　これに当てはまれば　"1" 

排他的論理和回路（EOR回路またはXOR回路）
　→ 簡単にいうと片方だけが　○◯　の時に"1"になる


>参考文献
>>きたみりゅうじ　『キタミ式　イラストIT塾　基本情報技術者　令和０３年』 技術評論社 2020年
CodeDeployを使ってLaravelをEC2にデプロイした時のメモ

## リポジトリを作成する
CodeCommitにリポジトリを作成する
sshかhttpで接続出来るようにしてプッシュ

## EC2を作成する
コンソールからEC2を作成する
CodeDeploy Agentをインストールする

```sh
sudo yum update
sudo yum -y install ruby wget
cd /home/ec2-user
wget https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
sudo service codedeploy-agent status
# sudo service codedeploy-agent start
```

## IAMロールを作成する
EC2用のIAMロール
- AmazonEC2RoleforAWSCodeDeploy
CodeBuild用のIAMロール
- AmazonSSMReadOnlyAccess
- (kms:Decryptを許可するポリシー)
CodeDeploy用のIAMロール
- AWSCodeDeployRole

## CodeDeployの設定
CodeDeployのアプリケーションを作成する
CodeDeployのデプロイグループを作成する
Codepipelineを作成する
appspec.ymlを作成する
appspec.ymlは必ずしもルートディレクトリに置く必要はなく、ビルドプロジェクト毎に別のファイルを使用することも可能

```yml:appspec.yml
version: 0.0
os: linux
files:
  - source: /
    destination: /var/www/app

hooks:
  BeforeInstall:
    - location: scripts/beforeinstall.sh
      runas: root
  AfterInstall:
    - location: scripts/afterinstall.sh
      runas: root
  ApplicationStart:
    - location: scripts/applicationstart.sh
      runas: root

permissions:
  - object: /var/www/app/scripts
    pattern: "**"
    owner: ec2-user
    group: nginx
    mode: 774
    type:
      - file
```
buildspec.ymlを作成する
buildspecはルートディレクトリに置く必要がある

```yml:buildspec.yml
version: 0.2

phases:
  install:
    runtime-versions:
      php: 7.4
      nodejs: 12
  pre_build:
    commands:
      - echo "pre-build"
      - aws ssm get-parameter --with-decryption --name .env.production --query Parameter.Value | sed -e 's/^"//' -e 's/"$//' -e 's/\\\"/\"/g' | awk '{gsub(/\\n/,"\n")}1' > .env
  build:
    commands:
      - echo "build"
      # Composerインストール
      - composer install
      - npm install
      - npm run prod

artifacts:
  files:
    - '**/*'
```
Azure SDK for Goの管理ライブラリーセットがリニューアル

Microsoft AzureをGoでプログラミングして管理/制御する「[Azure/azure-sdk-for-go: Microsoft Azure SDK for Go](https://github.com/Azure/azure-sdk-for-go)」の管理ライブラリーセットが、v56.0.0から通称「Track 2」と呼ばれていた Azure SDK デザイン ガイド に準拠したものになりました。

- [Go Guidelines: Introduction | Azure SDKs](https://azure.github.io/azure-sdk/golang_introduction.html)

新セットのパッケージは `sdk/` ディレクトリーに置かれています。

v55.8.0までの旧セットのパッケージは `services/` ディレクトリーに置かれています。

パブリックプレビューのパッケージは `services/preview/` ディレクトリーに置かれています。メジャーバージョンに昇格するまでは破壊的な変更が入る可能性がありますので、その点に注意にて使用してください。

旧セットには、まだ新セットに移行＆対応できていないパッケージが含まれています。対象サービスのパッケージが新セットになくて旧セットにはある場合は、旧セットのパッケージを使用することになります。

コードの記述を旧セットから新セットへ移行させるためのガイドも用意されていますので、移行時の参考にしてください。

- [azure-sdk-for-go/MIGRATION_GUIDE.md](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/MIGRATION_GUIDE.md)

クイックスタートは、新と旧の両方が用意されています。

- 新セット：[Quickstart tutorial for new releases](https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/compute/armcompute/README.md)
- 旧セット：[Quickstart tutorial for previous versions](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/previous-versions-quickstart.md)

詳細につきましては、Azure/azure-sdk-for-goのv56.0.0以降（＝mainブランチ）の[README.md](https://github.com/Azure/azure-sdk-for-go/blob/main/README.md)をご参照ください。
【必須】Font Awesomeを使ってアイコンを挿入しよう！！

#はじめに
Font Awesomeを使って自作のHPやアプリにアイコンを挿入することで画面が格段に良くなるので、どんどん使っていきましょう。

#Font Awesomeの使い方
1) [公式サイト](https://fontawesome.com/)にログインして、以下のコードをコピーし、HTMLのheadタグ内に貼り付けます。
　①右上の人のマークをクリックして、Font Awesome CDNをクリックすると、以下のコードがあります。


```html
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm" crossorigin="anonymous">
```

②右上の人のマークをクリックして、Kitsをクリックすると、「Your Kits」の下に、アイコンとKit名（数字とアルファベットの組み合わせ）が書いてある部分があるので、そこをクリックします、
すると、以下のコードがでてきます。

```html
<script src="https://kit.fontawesome.com/0722d56e11.js" crossorigin="anonymous"></script>
```
※コードが書いてある場所はサイトの仕様によって変わるかもしれないので、変わっていたら自分で探してみてください。


2)サーチボックス(Search icons...と書いているところ)に必要なアイコンが表示されそうなキーワードを英語で入力しする。

3)検索結果が出たら、好きなアイコンをクリックする（濃く表示されているアイコンが無料のものです）。

4)アイコンの名前の下あたりにあるiタグの部分をクリックして、コピーする。

5)HTML内のアイコンを表示したい部分に先ほどのiタグを貼り付ける。
※私は現在Laravelで開発中のため、以下のindex.blade.phpに貼り付けています。

```php:index.blade.php
<a href="{{route('menu.create')}}"><i class="fas fa-magic pr-1"></i>新規登録</a>
```

#おわりに
使い方も簡単だし、アイコンを文字と同じように扱えるので、とても便利ですね。
ExcelVBA 2次元配列の指定した行で文字列を検索して列を返す関数

```
'--- 2次元配列の指定した行で文字列を検索して列を返す関数 ---
Private Function Return_Column_From_2Darray(ByVal Item, ByVal row, ByRef arr() As Variant)
    Dim i As Long

    For i = 1 To UBound(arr(), 2)
        If arr(row, i) = Item Then
            Return_Column_From_2Darray = i
            Exit For
        End If
    Next i

End Function
```
IBM Cloudの新認定試験IBM Cloud Professional Architect v5を受けてみた

# IBM Cloud Professional Architect v5とは

IBM Cloudの認定技術者の1つで、2021年8月中旬から受験可能になりました。レベル感としては、1～3年程度の実務経験を積んだ中級レベルの試験です。

IBM Cloud Professional Architect v5に合格すると、**IBM Certified Professional Architect - Cloud v5**の認定資格を得ることができます。もちろんOpen Badgeももらえます。

<img width="160" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/65c54322-db33-77e9-c90f-c06cd301b6a2.png">

試験の概要はこちら。

> https://www.ibm.com/certify/exam?id=C1000-118

認定資格の概要はこちら。

> https://www.ibm.com/certify/cert?id=C0001403

# 学習方法

難易度は高めです。実務経験なしで座学だけでの合格は難しいと思います。実務経験があっても、試験範囲の経験が乏しいと難しいかもしれません。下記サイトでラーニングパスが公開されていますので、一通り目を通すことをお勧めします。

> https://www.ibm.com/training/path/ibmcloudprofessionalarchitect

# 受験方法

PearsonVUE社のサイトで予約して受験してください。

https://www.pearsonvue.co.jp/Clients/IBM.aspx

以前は最寄りのテストセンターでしか受験できなかったのですが、最近はカメラ付きPCがあれば自宅でも受験可能になりました。こういうご時世ですので、可能であれば自宅での受験をお勧めします。ただし部屋の片づけはきちんとしておいてください。

# 合格点

61問中39問以上の正解で合格です。正答率は63%です。IBMの認定試験では甘い方だと思いますが、これでも私はかなりぎりぎりでした。

# 出題内容

試験規約により具体的な問題文は書けませんので、雰囲気になりますが、いくつか問われそうな箇所を書きます。

* VMware Solutions
* Storage
* Network (Direct Link 2.0, VPC, Security)
* Kubernetes, OpenShift
* Security
* Backup
* Monitoring
* Hybrid Cloud
* Watsonサービス
* IBM Cloud Databases, Db2 on Cloud

独り言ですが、VMware Solutionsの未経験者は念入りに勉強しておくといいかもしれません。

# 感想

前バージョンのv4は非常に簡単で、むしろ初級レベルのSolution Advisor v2と難易度が逆転していた印象がありましたが、Technical Advocate v3が易化し、Professional Architect v5が難化したので、名目通りのレベル感になったのかなと思います。

https://qiita.com/teruq/items/b36655d0b31ddc8861fe

https://qiita.com/teruq/items/1aa4da4a4b2d74a2abbe

https://qiita.com/teruq/items/c1086dd52bd427aec224
ExcelVBA 1次元配列が空かどうか調べる関数

```
'--- 配列が空の場合はTrueを返す関数 ---'
Public Function Is_Empty_Array(ByRef arrayTmp As Variant) As Boolean

On Error GoTo ERROR_

    'UBound関数を使用してエラーが発生するかどうかを確認
    If UBound(arrayTmp, 1) >= 0 Then
        Is_Empty_Array = False
    Else
        Is_Empty_Array = True
    End If

    Exit Function

ERROR_:

    'エラーが発生した場合
    Is_Empty_Array = True

End Function
```
git push の際にpre-receive hook decliedというエラーが出たときの対処

#環境
OS: Windows10

```console
$ php -v
PHP 8.0.9 (cli) (built: Jul 29 2021 14:12:27) ( NTS Visual C++ 2019 x64 )
Copyright (c) The PHP Group
Zend Engine v4.0.9, Copyright (c) Zend Technologies

$ chocolatey -v
0.10.15

$ php artisan --version
Laravel Framework 7.30.4
```

#事象
Herokuにアプリを作成してgit pushしようとしたら以下のエラーが発生してpushが完了できない。

```console

// 省略
remote:  !     Push failed: cannot parse Procfile.
remote:  !     Please try pushing again.
remote:  !     If the problem persists, see https://help.heroku.com/ and provide Request ID eab36261-ec85-5190-cec3-fa34be370f7b.
remote:
remote:
remote: Verifying deploy...
remote:
remote: !       Push rejected to appname.
remote:
To https://git.heroku.com/appname.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/appname.git'


```

#原因
Procfileの文字コードがUTF16になっていた。

###Procfileの作成時のコマンド

VSCodeのTERMINALタブで以下のコマンドを実行してProcfileを作成した。
```console
echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile
```


#紆余曲折

###調べたキーワード

```
// これで調べまくったけど、無限にうまく行かなかった
pre-receive hook declined

```

###試したこと

 ①herokuのアプリを削除して、別の名前でherokuアプリを作成 → git push
②ダミーのファイルを作成してgit add . からpushまで
③pull してからpush

pre-receive hook declinedで調べると上記のような対策が出てくる。けど、検討違いでした。
調べるべきは

```

Push failed: cannot parse Procfile.

```

解決策が見い出せた記事が↓↓↓↓
https://teratail.com/questions/197422

先人たちに感謝！

とりあえずVSCodeでProcfileを開いて文字コードを変更しました。
右下あたりに次の画像のような部分に文字コードが表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668402/00e4c331-c246-41aa-54ec-81148b6ff9a5.png)








UTF-8ってところがUTF-16になっていたので、その部分をクリック。すると上の方に文字コードが選べるようなものが出てくるのでUTF-8を選択。

文字化けするので全部削除してもう一度下記内容を手打ちする。
```
web: vendor/bin/heroku-php-apache2 public/
```

これでpushができるようになります！！！
puppeteerを用いたブラウザ操作自動化 メモ


## puppeteerとは

* プログラムから API で Chromeブラウザ を制御できる Node.jsライブラリ。
* ブラウザ制御にはコマンドラインAPI といった開発者モードで使用できる API をそのまま使用できる。


## 事前準備(puppeteerインストール)

※Node.jsはインストール済みとする。

```shell
npm init
npm install puppeteer
```



## コード

`test.js`

* `puppeteer`でGoogle検索を行い、検索結果の1番上のページにアクセスし、スクリーンショットを取得する。

```javascript
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  // Googleページを開く
  await page.goto('https://www.google.com/');
  // 検索boxに`puppeteer`を入力
  await page.type('input[name="q"]', 'puppeteer');
  // 「Enter」ボタン押下
  await page.keyboard.press('Enter');
  // 検索結果要素の表示まで待機
  await page.waitForSelector(".LC20lb", {visible: true});
  // 検索結果のタイトル・リンク一覧取得
  const searchResults = await page.evaluate(() => 
    [...document.querySelectorAll(".LC20lb")].map(e => ({
      title: e.innerText,
      link: e.parentNode.href
    }))
  );
  console.log(searchResults);
  // 検索結果のページ1番目をクリック
  await page.click(".LC20lb");
  // スクリーンショットを取得
  await page.screenshot({ path: 'screenshot.png'});

  await browser.close();

})();
```

## 動作確認

```shell
node test.js
[
  {
    title: 'puppeteer/puppeteer: Headless Chrome Node.js API - GitHub',
    link: 'https://github.com/puppeteer/puppeteer'
  },
  {
    title: 'puppeteerで始めるブラウザ操作の自動化 - 株式会社クレスコ',
    link: 'https://www.cresco.co.jp/blog/entry/15215/'
  },
  {
    title: 'ヘッドレス Chrome Node API 「Puppeteer」 - Qiita',
    link: 'https://qiita.com/bezeklik/items/c6448d50ff0efb45829e'
  },
  {
    title: 'Node.jsでPuppeteerを使いChromeを実行して画面キャプチャ ...',
    link: 'https://www.4peace.co.jp/tech/456/'
  },
  {
    title: 'Puppeteer | Tools for Web Developers | Google Developers',
    link: 'https://developers.google.com/web/tools/puppeteer'
  },
  {
    title: 'Puppeteer の概要 - Microsoft Edge (Chromium)',
    link: 'https://docs.microsoft.com/ja-jp/microsoft-edge/puppeteer/'
  },
  {
    title: 'Puppeteerでできることまとめ - GMOアドパートナーズ ...',
    link: 'https://techblog.gmo-ap.jp/2018/12/28/puppeteer%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%93%E3%81%A8%E3%81%BE%E3%81%A8%E3%82%81/'
  },
  {
    title: 'Puppeteerを使用したHeadless Chromeの操作 - ZOZO TECH ...',
    link: 'https://techblog.zozo.com/entry/puppeteer'
  },
  {
    title: 'puppeteer を使用する - Jest',
    link: 'https://jestjs.io/ja/docs/puppeteer'
  },
  {
    title: '「Puppeteer」とは？ マウスやキーボードなしでブラウザ操作 ...',
    link: 'https://www.sbbit.jp/article/cont1/34562'
  }
]
```

※ブラウザ操作が行われ、`screenshot.png`がテストコードと同一フォルダに保存される。

※ヘッドレスモードで実行したい場合、以下のように変更する。

```javascript
const browser = await puppeteer.launch({ headless: true });
```



## 参考情報

* [puppeteer/puppeteer](https://github.com/puppeteer/puppeteer)
* [puppeteerで始めるブラウザ操作の自動化](https://www.cresco.co.jp/blog/entry/15215/)
* [ヘッドレス Chrome Node API 「Puppeteer」](https://qiita.com/bezeklik/items/c6448d50ff0efb45829e)
* [Node.jsでPuppeteerを使いChromeを実行して画面キャプチャを撮る](https://www.4peace.co.jp/tech/456/)
* [Scraping Google search result links with Puppeteer](https://stackoverflow.com/questions/67515088/scraping-google-search-result-links-with-puppeteer)
Windowsの名前付きパイプにおける通信方向ごとの設定

# 概要
Windowsの名前付きパイプは通信方向をINBOUND, OUTBOUND, DUPLEXの3種類が設定でき、サーバとクライアントの設定も通信方向で異なるのだが、これらの3パターンに対しての設定方法をわかりやすく設定した文献を見つけることができなかった。
そこで、試しなが少し苦労してパターンを理解したので、この記事では自分の理解をまとめて共有することとした。間違いなどがあればぜひ指摘いただきたい。

# 詳細
3種類のパターンを図にまとめると以下のようになった。
![Windows名前付きパイプINBOUND-OUTBOUND-DUPLEX図解.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84768/5dfd61bb-8e81-a753-45ed-3aa9c6196f4a.png)
ここではサーバはパイプを作成する側、クライアントはサーバの作成したパイプに繋ぐ側としている。以下ではそれぞれ個別の設定内容を説明する。

## OUTBOUNDの場合
OUTBOUNDはサーバがパイプに書き込んだデータをクライアントが受け取るという一方通行の通信を表す。

サーバは`CreateNamedPipe()`を呼び出すときに`PIPE_ACCESS_OUTBOUND`を設定する。サーバはデータを読まないためREADMODEは設定しない。

クライアントは`CreateFile()`を呼び出す時に`GENERIC_READ`を設定する。一般のファイルを読み込みモードで開くのと似ている。他のパターンでは`SetNamedPipeHandleState()`を呼び出すが、クライアントが書き込みを行わないOUTBOUNDの場合は不要である。（むしろ呼び出すとエラーが出る。）

## INBOUNDの場合
INBOUNDはOUTBOUNDとは逆にクライアントがパイプに書き込んだデータをサーバが受け取るという一方通行の通信を表す。

サーバは`CreateNamedPipe()`を呼び出すときに`PIPE_ACCESS_INBOUND`を設定する。サーバはデータを読むためREADMODEを設定する。

クライアントは`CreateFile()`を呼び出す時に`GENERIC_WRITE`を設定する。INBOUNDのパターンでは`SetNamedPipeHandleState()`を呼び出す。これは推測だが書き込む側がどのような書き込みを行うかを決める設計になっているということかもしれない。


## DUPLEXの場合
DUPLEXの設定はINBOUNDとOUTBOUNDの組み合わせである。クライアントは`GENERIC_WRITE`と`GENERIC_READ`をORにより両方設定する。

以上。