OmniAICreator/Qiita-1.07M huggingface dataset:
MariaDBの実行計画を参照する

MariaDBには、クエリの実行計画の参照方法がいろいろあって、MariaDB初心者が混乱したというお話です。

あくまで`参照する方法`なので、この記事を読んでも、実行計画を読み解く方法も、クエリをチューニングする方法もわかりません。とりあえず手がかりとなる情報を表示できるだけです。

##EXPLAIN
以前触ったことのあるDBMSの知識をもとに思いついたキーワードで検索するとありました。クエリの頭にこのキーワードをつけるだけのようです。

さっそくやってみます。（クエリは適当です）

```
EXPLAIN SELECT school.name, student.grade, student.name FROM student INNER JOIN school ON student.school_id = school.id WHERE grade = 3;
```

するとこんな感じ。（見にくいのでIDEで行列を入れ替えています）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/921971/38a5f0f6-b98f-6973-a2d9-9825fd926fc0.png)

想像していたものよりあっさりしています。検索の種類（`type`）、使用するインデックス(`key`)、keyで絞り込まれる行数の見積もり(`row`)などの情報はあるのですが、どこで時間がかかっているのかが素人には分かりにくいです。

##EXPLAIN EXTENDED
何かオプションがあるのかなと思いドキュメントを読むとありました。`EXTENDED`キーワードをつけられるようです。

再チャレンジです。

```
EXPLAIN EXTENDED SELECT school.name, student.grade, student.name FROM student INNER JOIN school ON student.school_id = school.id WHERE grade = 3;
```

`filtered`（反転させた行）が追加されました。その条件で絞り込める割合(%)の見積もりのようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/921971/8c405dae-173f-f6e2-a746-cd483e9eda12.png)

MariaDBがどう考えてクエリを処理しようとしているは分かってきましたが、実際に実行した結果がどうなのかをもう少し知りたいところです。

##ANALYZE
ドキュメントを読みすすめるとお隣のページに`ALNALYZE`というものがありました。どうやらこっちのほうが強力そうです。

えいっ。

```
ANALYZE SELECT school.name, student.grade, student.name FROM student INNER JOIN school ON student.school_id = school.id WHERE grade = 3;
```

`r_rows`と`r_filtered`（反転させた行）が追加されました。接頭辞の`r_`は多分`real`とか`reality`の意味で、`r_rows`は実際に抽出された行数、`r_filtered`は実際に絞り込まれた割合(%)のようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/921971/2b082d5f-bb6b-fb13-0f62-4d4aa5f15b6e.png)

これでオプティマイザーの見積もりと実際の乖離が分かるようになりました。

##ANALYZE FORMAT=JSON
でもやっぱりかかっている時間が知りたいので探してみると`FORMAT=JSON`をつけると分かるようです。`FORMAT`なのにまさか情報が増えるとは思いませんでした。ドキュメントは別ページだし、完全に見落としていました。

```
ANALYZE FORMAT=JSON SELECT school.name, student.grade, student.name FROM student INNER JOIN school ON student.school_id = school.id WHERE grade = 3;
```

フォーマットが違うので雰囲気が変わりましたが、これまでの情報に加えていくつか情報が追加されています。その中にありました`r_total_time_ms`:grin:。上位のノードの時間は、下位の時間を包含するようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/921971/e2490db6-2bd3-8fe1-fb65-7d4189762283.png)

##結論
クエリの情報を詳細に知りたいときは、`ANALYZE FORMAT=JSON`を使っておけばよさそうです。
なお、`ANALYZE`は`EXPLAIN`とは違い、実際にクエリを発行します。本番環境でいきなりUPDATE文やDELETE文を`ANALYZE`したりするとたぶん怒られます。

##その他
####調べるのを邪魔してくれたキーワードたち

* `EXPLAIN ANALYZE` ・・・ MariaDB 10.1以降は`ANALYZE`に取って代わられたので使えません。
* `SHOW EXPLAIN` ・・・ スレッドIDを指定して実行中のクエリの実行計画を出力します。`SHOW PROCESSLIST`でスレッドIDを調べられます。

####試したバージョン
* MariaDB v10.2.21
参照しやすいインシデントチケットの書き方

弊社のSRE部門では、商用環境に問題が発生した場合、Redmine上で「インシデントチケット」と呼ばれるチケットを作成することで、その顛末を管理しています。

このインシデントチケットの書き方について、日ごろ思っているポイントをこの機会にまとめてみました。チケットのみならず、手順書なども含めたドキュメントの書き方にまつわる話になりそうです。

※本記事は「[Develop fun!を体現する Works Human Intelligence Advent Calendar 2020](https://qiita.com/advent-calendar/2020/whi)」の12/9を担当したものです。

#インシデントチケットとは何か

商用環境に起きた問題に対して1対1で作成し、その顛末をまとめたものです。チケット管理にはRedmineを利用しています。

問題発生時には初動として同一事象を扱っているチケットがないかを検索し、もしヒットしたらそのチケットに書かれている対応方法等を参考にして対処します。

インシデントチケットには主に以下のような内容が含まれています。

* 問題の発生箇所
* 問題発生時のログ
* 対応担当者
* 一次対応の方法
* 根本原因
* 恒久対応の方針

#インシデントチケットの目的とは？

インシデントチケットを書く目的は大きく分けて以下の通りだと考えています。

* 同一事象が発生した場合に問題解消までのリードタイムを短くする
* 問題発生までの経緯や後続の対応を紐づけて管理して俯瞰できるようにする

そのため、この目的を達成することができない書き方のチケットは「よくないチケット」と考えることができます。

いずれにしても言えるのは「チケットはあとから参照するためのもの」ということで、書くだけで効果がある魔除けのお札ではありません。

#良いチケットを書くためのポイント

参照しやすいチケット、もう少し言うなら「読んでわかりやすいチケット」を書くためには、大事なポイントがいくつかあると考えています。

###見た目を整える

ソースコードのインデントなどもそうですが、人に読まれることが前提のものは見た目を整えることが非常に大事です。節ごとに見出しを付ける、ログやコードの部分をブロックで指定する、などを最低限使いたいです。

Redmineの場合はテンプレート機能を使ってあらかじめ用意しておくと便利です。

###省略せずに具体的に書く

チケットを書いた人と参照する人で必ずしも同じだけの知識・知見があるとは限りません。特に一次対応をどう行ったかを書く際、具体的な手順や言葉については省略せずになるべく具体的に書くようにしています。

* 悪い例

```
アラートが出ていたのでコンソールから再起で解消
```

* よい例

```
監視システムでアラートの発生を確認。
AWSコンソールから対象インスタンスの再起動を実施。
その後、監視システム上でアラートの解消を確認した。
```

###判断の流れが追えるようにする

上の”具体的に書く”と似ていますが、一次対応や根本原因の調査において、何を見てどういった基準で判断したかという流れもなるべく明記します。

結論だけが書いてある場合、後からそのチケットを見た人はその判断を再現することができず、同じ対処をすべきかどうかが決定できません。それではインシデントチケットの意味は薄れてしまいます。

また、これを書くことで部署内で他の人が書いたチケットを見てその判断方法を踏襲することができ、知見の共有や教育コストの削減にも効果があると考えています。


#チケット管理の問題は…

ここまで色々と書きましたが、これを全員が認識したからといってインシデントチケットの運用が良くなっていくとは限りません。なぜなら、そもそも**問題発生時に必ずチケットが切られる前提**で話しているからです。

チケットを切ることそれ自体が問題を解決してくれるわけではありません。チケットを書くぐらいなら具体的な修正のために手を動かしたいと感じる場合も多く見受けられ、他のタスクが山積みになってる状況では容易に忘れ去られてしまいます。

なので、実は内容なんかよりチケット作成の自動化のほうがよっぽど大事なのではと思ったり…

戦いはまだまだ続きます。
マークダウン記法について

#マークダウン記法とは
早速Qiitaに投稿しよう！！と思ったらマークダウン記法で書きましょう♪と書かれている。
マークダウン記法とはなんぞや、ということで調べてみました。
https://backlog.com/ja/blog/how-to-write-markdown/
にまとまってました。

よく使いそうな記法を以下にまとめました。

*改行：行末で半角スペース２個
*見出し：頭に#　#の数で大きさ変わるらしい

#１個
##２個
###３個

*箇条書き：文字のあえにアスタリスク*

いっぱいあるな。。。徐々に追加していきます。
BSD版sedで粘る〜GNU sedとのコマンド比較〜

この記事は、[上智大学エレクトロニクス研究部Advent Calendar](https://qiita.com/advent-calendar/2020/sophia_ele_lab)第9日目の記事です。

## まえがき

シェルスクリプトを勉強すると最初の方に出てくる `sed` コマンドですが、実はMacの `Command Line Tools` へ同梱されている `sed` コマンドはBSDライセンスのもので、Linuxで広く使われているGNU版のものとは異なります。そのせいでネットでコピペした `sed` コマンドのワンライナーが動かないということが発生します。この記事ではBSD版の `sed` と GNU版の `sed` で同じことをしようとしたときにどのようにコマンドが異なるのかを比較します。

## ちなみに

Homebrew を使えば簡単にGNU版 `sed` をインストールできます。

```bash
brew install gnu-sed
```

以下のように `gsed` と打ち込むとLinuxと同じように使えることがわかります。

```bash
echo hogehoge | gsed 's/hoge/fuga\n/g'
```

```
fuga
fuga


```

なので、以下は読む必要はありませんが、宗教的な理由でGNUコマンドを使いたくないという方、少しでも余計なツールを入れずに標準環境で頑張りたいという方の参考になればと思います。

## BSD版 `sed` と GNU版 `sed` の対応表

| コマンドの内容    | GNU | BSD |
| ---------- | :-: | :-: |
| 改行文字に置き換える | `sed 's/;/;\n/g'`| `sed -e 's/;/;\'$'\n/g'`    |
| 直接編集(バックアップを作らない) | `sed -i '1d' hoge.txt`| `sed -i '' '1d' hoge.txt`    |
| 直接編集(バックアップを作る) | `sed -i.backup '1d' hoge.txt`| `sed -i '.backup' '1d' hoge.txt`    |

## 参考文献
- https://qiita.com/YumaInaura/items/24ea5c111e8e06253612
【Swift】これでワカッタ！なるほど！オプショナル型ってそーゆーこと

# というわけで

つづき。
前回はこれを見てね。

**【Swift】オプショナル型の何が嬉しいのか**
<https://qiita.com/antk/items/2d780f152c26a3733109>

今回はこのオプショナル型を活用してみる。

## ラップ

ラップとは？
とりあえず置いといて、前回「**nilが使える**」ということで定義したオプショナル型。

```swift
var hoge: String?
```

この `hoge` という**オプショナル型の変数**は**そのままではいじることができない**。
どういうことか？
上記のように文字列型（String）だとわかりにくいので、例えば

```swift
var number: Int? = 2
```

という数値型（Int）のオプショナル型の変数を定義して、こいつに `2` を入れている。例えばこれを出力すると

```swift
print(number)

// 出力 Optional(2)
```

という結果が出る。
逆に、 `?` を付けない**非オプショナル型**だと

```swift
var number: Int = 2

print(number)

// 出力 2
```

さっきの `Optional` が付いていない、ただの `2` が出力される
非オプショナル型と違い、**オプショナル型で定義されているのはただの `2` じゃない**のである。
[paiza.io](https://paiza.io/ja)とかで試してみるといい。
これはなんなのかと言うと、 `Optional` という殻、カプセル、シェルター、バリアー……まあなんでもいいが、オプショナル型は要素がそういうものに入っていると考える。
これを『**ラップ（wrap）されている**』という。
ラップされている `number` は**殻**に入っているので

```swift
var number: Int? = 2

print(number + 4)

// エラー
```

このように数字を足して `6` にしようとしても `Optionatl` の殻に弾かれてしまうのでうまくいかないのである。
これをやるには殻を解く、**アンラップ**という作業が必要になる。

## アンラップ

オプショナル型変数の後ろに `!` を付ける。

```swift
var number: Int? = 2

print(number! + 4)

// 出力 6
```

こうすることで望みの結果が出た。
全然関係ないがデーモン小暮閣下は昔『!（エクスクラメイション）』という名義でアルバムを出していた。
【受験記】Python 3 エンジニア認定基礎試験

# はじめに

この記事は、先日合格した**Python 3 エンジニア認定基礎試験**の簡単な受験記録になります。

この試験に関する一般的な情報は充実してきていると思いますので、ここでは**試験に関する個人的な感想**（難易度を含む）と、準備の過程でお世話になった**（無料）模擬試験**に絞って記したいと思います。

これから受験される方にとって、少しでも参考になれば幸いです。

# 公式情報
- 試験ついてはこちらの[**公式サイト**](https://www.pythonic-exam.com/exam/basic)でご確認ください。
  - **受験方法**・**試験概要**・**試験範囲と出題の割合**などが載っています。

# 試験の感想
- 難易度としては、後述の模擬試験が十分参考になると思いました。模擬試験で700点（1000点満点）を安定的に超えていれば、合格のチャンスは十分にあると思います。と言うのも、全体的な感想として後述の模擬試験の方が難しいと思いました。

- なお、出題の一部には「例外」や「継承」など、初学者にとっては馴染みがなかったり、書き慣れなかったりする内容も含まれていました。しかし、全体に占めるそれらの割合はさほど多くはないので、合否を左右するとまではいかないと思います。

- 主教材である**「Pythonチュートリアル 第3版」**(ライリー・ジャパン)については、
  - 1章から14章までの内容の全を理解している必要はなく、量にしてその半分ぐらい、レベルで言えば基礎的なところが分かっていれば、合格も狙えるという印象でした。
  - なお、チュートリアルに載っているコードを題材にしたと思われる出題があるので、基本的なコードはウェブで一通り目を通しておいて損はないとお思います。

- 合否結果は試験終了後にモニターに表示されます。また、スコアと分野別得点率を印字した紙を別途もらえます。この点に関しては、試験終了後に不正解だった箇所の確認ができないのが残念です。試験直後にせめて5分でもいいので、振り返りができるセッションがあれば、受験者にとってより教育的で有意義な試験になると思いました。

# 無料模擬試験

公式サイトでは、以下の2つの模擬試験が紹介されています。私もこれを利用させていただきましたが、とても役に立ちました。

## DIVE INTO EXAM

こちらが一つ目の[模擬試験のサイト](https://exam.diveintocode.jp/exam)になります。

### ①全体的な特徴

- 試験は複数回受けることができます。（このことは、ぱっと見では分かりませんでした。）つまり、ここの模擬試験を本試験直前の「総仕上げ」として最後までやらずに残しておく必要はありません。むしろ、必要な回数受験しながら、その都度、直しをして、安定して合格点を超えることを目標にするスタイルで利用するといいと思います。

- なお、２回目以降の受験では既出の問題と新出の問題が混ざって出題されます。（この点については、過去に正解した問題は次回以降は全く出題されないか、または低頻度でランダムに出題されるような仕掛けがあると、より効率的に学習できると思いました。無料で利用させていただいておいて、わがままな意見ですね。。）

- 受験後は問題・採点結果・正解をウェブ上で確認できます。（ただし、各問題の選択肢がどうなっていたかは、後から確認することができません。ですから、模擬試験終了後に振り返りと直しを丁寧におこなうつもりであれば、試験中に選択肢をその都度どこかにコピペしておく必要があります。）

- 複数回受験すると、点数の推移が表示されます。

- 実際のスコア（1000点満点）にあわせて採点されます。

### ②出題の特徴

- 全体的な質問の傾向は本試験と概ね同じでした。

- また、難易度は本試験に比べて模擬試験の方が若干難しかったと思います。


## PRIME STUDY

こちらがもう一つの [模擬試験のサイト](https://study.prime-strategy.co.jp/)になります。

### ①全体的な特徴

- 試験は３回分あります。

- なお、各回で問題が全て新しくなるわけではなく、前回の問題の単語を一部入れ替えたような「使い回し」の問題も少なからずあります。（これは学習の計画や見積もりにも影響する話で、ここの模擬試験を３回受験したからと言って、経験値が単純に3倍になる訳ではありません。）

- 受験後は問題・採点結果・自分の解答と正答がメールで送られてきます。（ただし、各問題の選択肢がどうなっていたかは、後から確認することができません。ですから、模擬試験終了後に振り返りと直しを丁寧におこなうつもりであれば、試験中に選択肢をその都度どこかにコピペしておく必要があります。）

- 一度受験した回も、再度受験することができます。（完全に同じ問題を解き直ししたい時や、気になった問題を後から確認したい時に有効です。）

- こちらの模擬試験は100点満点で採点されますが、本試験と問題数が同じことから、換算の際には点数を単に10倍するだけで大丈夫です。

### ②出題の特徴

- 特に文章題において、選択肢群に盛り込まれる話題の量と種類が多いと感じました。（これは、限られた問題数の中で模擬試験としての網羅性を高めようとした結果だと思います。ただし、本試験の出題では、選択肢はもう少し狭い範囲内で構成されていました。）

- 上記にも関係しますが、本試験に比べて難易度が高いというか、出題のスタイルが若干（初学者には）マニアックな方向にズレている気がしました。

- それでも、少し余裕のある初学者にとっては、本試験という枠組みを超えて、やっておいて損はない内容だと思います。

# まとめ

模擬試験を利用した感想を踏まえると、**PRIME STUDY**の模擬試験は**学習編**として準備期間の前半に、**DIVE INTO EXAM**の模擬試験は**実践編**として準備期間の後半に利用する、というスタイルも考えられます。

**＊ただ、上記は私個人の意見ですし、今後、本試験も模擬試験も内容が更新されていくことが予想されますので、あくまで本記事執筆時点での一つの考えとして、参考にしていただければ幸いです。**

最後まで読んできただきまして、ありがとうございました。
未経験から開発への入口

### 初めに
開発に携わりたい！と思って求人を探してもどこも開発経験〇年以上ばかり・・
未経験から開発に携わるにはどうすればいいんだ！というのを経験談含めて書いていきます。

### ざっくり概要
 - 未経験正社員で入れるところを探す
 - アルバイト・社会人インターンから入る
 - 知り合いづてで入る
 - 開発以外の現場で経験を積んで開発に移動


### ①未経験正社員で入れるところを探す
一番王道です。

 - メリット

応募しやすい。
求人情報から誰でも探して応募ができます。

 - デメリット

・最初開発から携われる求人は非常に少ないです。
特に受託開発、自社開発はハードルが高くなります。
・ミスマッチが起きやすい
会社のことを知れる内容が求人情報、面接のみになるので情報量が少ないです。
また、採用側も面接のみでしか接することができないためミスマッチが起きやすくなります。
思っていたイメージと違う・・・となってしまうかもしれません。


### ②アルバイト・社会人インターンから入る
- メリット

・正社員から入るよりかハードルが低い。
また、最初から開発のタスクを振っていただける可能性が高いです。
・働き方を自由に選びやすい。
少し働いてみて、合わないから辞める/正社員雇用を目指す/とりあえず職歴を積む・・等
将来の働き方を自由に選びやすいです。


 - デメリット

・給与、社会的立場が不安定になる
アルバイト、インターン中は給与が低いです。
また、企業側から合わない/伸びしろが低いと判断された際契約打ち切りになる可能性があります。
正社員雇用してもらえるかわからないところもリスクです。

### ③知り合いづてで入る(リファラル採用)

 - メリット
 
・一般求人よりも入社しやすい。
一般求人の場合、人材会社に紹介料、求人掲載料を支払っています。
特にエージェント経由での募集は紹介料が高く、平均的に入社者の年収3割(400万なら130万程)手数料を取られます。
そのため一般求人は採用側も厳しく求人を見ています。

一方、リファラル採用は手数料が低いです。
一般的には紹介者に謝礼金を支払っていますが、エージェント経由と比べたら微々たるものです。
手数料的に安い＆紹介者の信用があるので一般求人より入社しやすいです。

 - デメリット

・IT業界から無縁で入ってきた人には厳しい
知り合いにエンジニアがいる前提の話なので、いない場合はリファラル採用の話自体がないです。
・経験者を応募している企業が多い


### ④開発以外の現場で経験を積んで開発に移動
 - メリット
・他の未経験者と比べて就活が有利
開発以外だとしてもIT業界歴があるのは非常に大きいです。
志望動機も言いやすいですし、採用側も業界歴がある人を優先します。


 - デメリット

・開発に携わるまでの空き期間ができてしまう
どうしても遠回りになるので、それまでモチベーションを保つのが難しいです。

### まとめ
どの選択肢でも、その会社の社風、方針、サービスと合っているかが何よりも重要です。
個人的な意見ですが、未経験から開発に入るのは基本的にハードモードになります。
就活も新卒理系の人と争わないといけないし、入社後も他の人より覚えることが多いため残業も多くなります。
プログラミング初心者が作るIoTRCカーの製作 1-3 ESC、サーボのハック 実装検討

![IMAG2741.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933473/61fa7694-d663-0aaa-c513-6446e03edd2a.jpeg)
#ハックしちゃった！
もうハックハクですよ。

載せているのは予定とは違うシャーシ（2駆）ですけど、モーターとサーボが付いていたのでそのまま付けてみました。PCからこの状態で操作出来るって結構感動ものですよね……。

#ブレッドボードへの部品取り付け
![IMAG2743.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933473/299e3af7-6432-d347-841c-773647be07ab.jpeg)
正直写真だと分かりにくいんですが、実際のRCカーと同様バッテリーから電源を取って、ESC経由でサーボとObnizに電源供給しています。

#ESCのPWM
TEU-105BKについて値を色々探ってみた所、周波数：50Hzにおいて

- 6.75％以下でバック方向最大回転
- 7.4％でバック方向ギリギリ回るくらい
- 7.4～7.9％の間ではモーターは回らない
- 7.9％で前方向ギリギリ回るくらい
- 8.7％以上で前方向最大回転

という感じでした。ただESCのキャリブレーションをプロポ側で終わらせているもので確認しているので、いわゆるポン付け状態ではどういった値になるかは何とも言えません。

#レギュレータ：FUTABA PS-01
![IMAG2745.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933473/321daf01-4f98-9a0b-6b39-f8fc7ea24741.jpeg)
バッテリー電圧は7.2V（実際は最大8.0V位あります）、ESCのBECで6.0VなのでObnizの5.0Vに対して高すぎます。なのでレギュレータを導入しました。
元々空用サーポ用なのですが、
なお出力電流は1Aとのことですが、現在の所問題なく駆動しています。

#おぼえがき
ESCもサーボも、何らかの形でObnizのGNDに接続しないと動きません。今回は電源供給のためにJ1端子のGNDに配しましたが、回路を考える時は忘れないようにしないといけません。

#この後の予定
動いたとは言ってもまだブラウザ上のボタンを押したらステアが動くか進むかバックするかという所までで、このままでは操作すらままなりません（マウスはマルチタッチ出来ないので）。なのでUIを作り直してスマホとかで操作出来るようにするとか、あるいはPCにコントローラーを付けたりキーボードで操作出来るようにしたりということをやりたいです。

もしくはObnizのスターターキットにある距離センサーや人感センサーを使って自動運転への一歩というのもいいかもしれません。

並行して本来使いたいESCとサーボのPWM検証でしょうか。正直動かせるまで1週間は掛かると思っていたので、この調子でもっと先に進めたいところです。
Git/GitHubの初期設定について簡潔に触れてみた

#はじめに
Python/DjangoでWebアプリ作成を行う過程で、
必要不可欠なバージョン管理システムGitについて
今回は、簡潔に触れていきます。

#初期設定
初期設定を行います。ターミナルを起動。

※[公式サイト](https://github.com)にてアカウントを作成しておきます


①アカウントのユーザー名を登録
　以下のコマンドを実行します。

```
$ git config --global user.name "ユーザー名"
```

②アカウントのメールアドレスを登録
　以下のコマンドを実行します。

```
$ git config --global user.mail gihub@example.com
```

③使用したいエディターを登録
　以下のコマンドを実行します。※VSCodeの場合

```
$ git config --global core.editor "code --wait"
```

　""の中は、エディターによって変更します。
　例：Atomであれば、"atom --wait"

④設定内容を確認
　以下のコマンドを実行します。

```
$ git config --list 
```

設定が反映されていることを確認できます。
以下のコマンドで設定ファイルを確認することも可能です。

```
$ cat ~/.gitconfig
```


#まとめ
Git/GitHubの初期設定を確認しました。

Gitの基本的なコマンド操作や、ブランチ・マージ・プルリクエスト等についても、内部の動きまで理解を深めていきたいと思います。

ありがとうございました。
CURL の代わりに IntelliJ でカンタン API の動作確認【JetBrains IDE】

# はじめに

この記事は [ちょっとした工夫で効率化！パソナテック Advent Calendar 2020](https://qiita.com/advent-calendar/2020/pasonatech-tips) の9日目の記事です。

昨日は @ta1fukumoto さんの記事でした: [【Macユーザー必見】BetterTouchToolで極限まで作業効率をあげよう！！](https://qiita.com/ta1fukumoto/items/1d8199d53fed3be74996)

# API の動作確認

皆さん API の動作確認ってどうしてますか？

シンプルな GET API だとブラウザで確認できますが、リクエストヘッダが必要だったり、POST メソッドだったりすると、ブラウザでは動作確認しづらいです。

かといって `curl` コマンドを書くのは結構大変。

Postman なんていうツールもあります。curl を GUI で叩けるツールです。

* [APIの開発がむちゃくちゃ捗る「Postman」の使い方](https://www.webprofessional.jp/master-api-workflow-postman/)

しかし、 **IntelliJ も HTTP リクエストできることを知り、最終的に IntelliJ に落ち着きました**。多分 IntelliJ 以外の JetBrains IDE でもできるかと思います。 PyCharm とか PHPStorm とか。

# IntelliJ から HTTP リクエストする方法

まずは拡張子が `.http` のファイルを作成します。

今回は、サクッと叩ける [niconico コンテンツ検索 API](https://site.nicovideo.jp/search-api-docs/search.html) を叩いてみようと思うので、 `niconico_search.http` というファイル名にしました。

内容には、リクエスト内容をそのまま書きます。

```niconico_search.http
POST https://api.search.nicovideo.jp/api/v2/video/contents/search
Content-Type: application/x-www-form-urlencoded;
TestHeader: Something

q=ゲーム&targets=tags&_sort=-viewCounter&_context=test&fields=contentId,title
```

* 1行目は `メソッド URI`
* 2行目以降はリクエストヘッダ `Key:Value` 
* 空行を挟んでその下がリクエストボディ

左側に三角ボタンが出ているので、「Run ...」をクリックすると API リクエストが実行されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29024/03db2dcc-3e6c-aa55-a962-c4ce4e7b345e.png)

実行結果はこんな感じです。表示形式は、text, JSON, XML, HTML に対応しています（HTMLはレンダリングされるわけではないので、見づらいです）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29024/b72048e3-c7fe-001d-b6b9-93e723378137.png)

`###` で区切ると、複数のリクエストを1つのファイルに記述することができます。ファイルは保存できるので、いつでも同じリクエストをすることができます。API の動作確認に便利です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29024/54ca0dcb-23a1-95c0-c5b9-dde2334df2a9.png)

niconico の検索 API は GET でも叩けるのですが、今回は例としてわかりやすいように POST で叩きました。

# なぜ IntelliJ がいいのか

通常は、開発しながら API の動作確認をすることが多いので、**コーディングから動作確認まですべてが IntelliJ で完結するのがめっちゃ便利**です。

しかも、ファイルをリポジトリに追加しておいたり、文字列を Slack に貼り付けたりすれば、他の人でも簡単に動作確認ができます。

GET のクエリパラメータが長くなると見づらいのが欠点です。この場合は Postman とかのほうが便利かも。

# まとめ

IntelliJ で `.http` という拡張子で API リクエスト等を保存しておくと、動作確認に便利！

IntelliJ 以外にデバッグツールを開く必要もなく、 IntelliJ ひとつで完結できるのでオススメです。

他にも開発便利情報をブログに書いていたりするので、気になった人は確認してみてください。↓は PHP アドベントカレンダーの記事です。

* [PSR-2 に変わって新しく制定された PSR-12 のチェックを PHP_CodeSniffer で行う - 猫でもわかるWebプログラミング]
(https://www.utakata.work/entry/php/phpcs-psr12-intellij-jenkins)
PHPでクラスを作成する

#PHPでクラスを作成


####以下の通り、PHPのクラスのコードを書いていく<br>


```
<?php
class Human{     
```

⇦クラス名を定義する。クラス名はPHPでは慣例的に大文字で記載する。
 
```
public $name;
public $gender;
```

⇦プロパティ(クラス内で定義された変数)を記載。


```
public function __construct($name,$gender){
     $this->name = $name;
     $this->gender = $gender;
}
}
```

コンストラクタはクラスからオブジェクトがnewによって作成される時に自動的に呼び出されるメソッド。
←メソッドはクラス内で定義された関数のこと。

```
$human = new Human('suzuki','female');
echo $human->name;
echo $human->gender;
?>
```

$humanをsuzuki,femaleの名前でオブジェクトを作る(インスタンス化)
echoで名前と性別を出力。<br>


###出力結果

```
xxxxxx@xxxxxx test-php % php class.php
suzukifemale
```
HSP3最新版のインストール方法

#0.初めに
しがないHSPerのあめふりてるです。
HSP3のインストール方法を詳細に書いた記事が見当たらなかったので、投稿時に書いている記事の見やすさをとるためにインストール方法を書こうと思い筆をとりました。HSPをこれから始める方もわかりやすいように書いたつもりです。

なお、今回はWindows環境のみの話をします。Mac環境の方は、[macOSでもスープが飲みたい！ (著:@kotambourineさん)](https://qiita.com/kotambourine/items/4503718f2690af136892)を参考にするといいかもしれません。とても分かりやすく書いてあります。

それでは、インストールしていきましょう。

#1.HSP3のダウンロード

早速、ダウンロードをしていきましょう。

1.[HSP3最新版のダウンロードリンク](http://hsp.tv/idman/download.html)を踏んだら、「Free Download HSP」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/97164093-e3da-a65e-914a-27a039211f6e.png)

2.クリックするとVectorさんに飛ばされるので「ダウンロードページへ」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/37959cd3-cedd-9538-c33c-3a51d324ffb8.png)

3.ページが更新されたら「今すぐダウンロード」をクリックするとダウンロードが始まります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/e53187a3-8d1e-96bd-0920-7a8e90811639.png)

これでダウンロードは終わりです。

#2.HSP3のインストール
では、インストールしていきましょう。

1.ダウンロードが終わったら、ダウンロードしたexeファイルを実行します。実行するとこのような画面が出てくるので「次へ」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/d27f2c87-9128-7758-b310-acfdd36f57ac.png)

2.インストール先を指定して「次へ」を押します。今回は標準設定にしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/5f1f5b6a-948a-62ec-f615-840ba33a7e46.png)
3.この後は基本、「次へ」を押すだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/60299a35-c4d2-c812-e231-cf83191a1355.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/a01a8876-848a-7321-6ba1-a88c22c01d35.png)
4.「インストール」を押すとインストールが始まります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/59a601d7-04b8-9c35-859c-cda7a99c3c80.png)

5.インストールが終了するとこの画面が出てくるので、「完了」を押してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/de2f06ce-d2b1-fff5-0e58-cdf3176240a5.png)
6.すると、「HSP3.5 Demonstration」というソフトが立ち上がります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/d2f629a6-e4e4-df56-686e-87d02cca33bb.png)

これで、インストールは終了です。

#3.最後に
ここまで読んでくださった方、ありがとうございました。
HSP3は、とても奥深いプログラミング言語なのでぜひ、遊んでみてください！！

HSP3で遺伝的アルゴリズムをしたりして遊んでいます。こちらの記事もよろしくお願いいたします。

[HSP3で遺伝的アルゴリズムをした話 〜遺伝的アルゴリズムの概略と「ムダにクリエイティブ」な"Hello,World!"〜](https://qiita.com/AmefuriTell/items/74f4e7049994e26096cd)

それでは、またどこかで。
Apple M1で使えるSIMDビット論理演算命令


「Apple M1の速さの秘密って他にない新命令の影響じゃないの？」みたいな発言がSNSで目立つので、では実際役に立ちそうな新命令について、考察して見ることにする。


## ARM NEON(ASIMD)からサポートされている64/128ビット論理演算命令

<dl>
<dt>NOT (論理否定)</dt>
  <dd>D = ~A</dd>
<dt>AND (論理積)</dt>
  <dd>D = A & B</dd>
<dt>BIC (否定 + 論理積)</dt> 
  <dd>D = A & ~B</dd>
<dt>ORR (論理和)</dt>
  <dd>D = A | B</dd>
<dt>ORN(否定 + 論理和)</dt>
  <dd>D = A | ~B</dd>
<dt>EOR (排他的論理和)</dt>
  <dd>D = A ^ B </dd>
<dt>BIF/BIT/BSL (ビット単位選択)</dt>
  <dd> D = (Mask & A) | (~Mask & B) ※ソース破壊型命令</dd>
</dl>

BIF/BIT/BSLはvselq_u32などの組み込み関数に割り当てられており、どのソースを破壊するかによって命令名が分かれているがコンパイラが勝手に選んでくれるので、C/C++以上のレイヤーで使う分にはプログラマーが特に意識する必要はない。

## SHA3サポートによって追加された128ビット論理演算命令(Apple A13/A14/M1対応)

<dl>
<dt>BCAX (否定 + 論理積 + 排他的論理和)</dt>
  <dd> D = A ^ (B & ~C)</dd>

<dt>EOR3 (3入力排他的論理和)</dt>
  <dd>D = A ^ B ^ C</dd>
</dl>

排他的論理和はパリティを取るための処理に多用するので、連続するEORはEOR3に可能な限り置き換えた方がパフォーマンスが向上する傾向がある。他、BCAXもBIC+EORを置き換え可能な箇所があれば使いたい。
また、0xFFをブロードキャストしたベクトルをソースの一つに指定することでXNOR操作などの代替にもなる。
3入力の論理演算はビットスライス型暗号アルゴリズムで重宝するので有効に使っていきたい。
ただしclangでは組み込み関数は未サポートなので、インラインアセンブラを使うか、対応したコンパイラをビルドする他ない。

EOR3は光るが、トータルで劇的に速いというほどでもない。

なお、Appleがサポートするのは128ビットまでのSIMDである。Intelのように256ビットとか512ビットのSIMDはサポートしないので、当然SIMDによって相対的優位性を得ているはずはないという考察もできる。

## どういう演算で速くなるのかの具体例
わかりやすい例として64ビット整数版Mersenne Twitsterを例に出すと、新命令を使うことによってビット論理演算を纏めることができる箇所は、この程度には存在する。

![スクリーンショット 2020-12-08 22.53.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136367/e7805020-b70a-fd57-3602-7902c5eede93.png)

## SHA3はM1以外のARMでもサポートするか
ARM社公式のアプリケーション向けCPUコアの実装としては最新のCortex-A78(Snapdragon 888もこれに基づくと思われる)でもSHA3をサポート予定がないので、M1以降のMacかA13/A14以降のiOSデバイス専用にコードを組むことになる。
Laravelですでにあるマイグレーションファイルを書き換えてテーブル定義を変更する

「テーブル作成のマイグレーションファイルに外部キー制約書き忘れた！」みたいなときの対処法です。
マイグレーションファイルが増えるのが気にならない場合や、複数人で管理している場合は、新しくマイグレーションを追加してテーブル定義を変更したほうがいいと思います。

## 1. テーブルを出力する
対象のデータベースのテーブルを全て出力します。

```sh
$ mysqldump --no-create-info --ignore-table=database_name.migrations -u user_name -ppassword > ~/dumps/database_name_20210101.dump
```

### ポイント
* `--no-create-info`オプション : マイグレーションでテーブルは作成するので、`CREATE TABLE ~`を出力しないオプションです。`INSERT INTO ~`のみが出力されます。
* `--ignore-table=database_name.migrations` : マイグレーションデータが保存されているテーブルを出力しません。


## 2. マイグレートする
ファイルを書き換えたあと、マイグレーションを実行します。

```sh
php artisan migrate:fresh
```

> **注意**
> `migrate:fresh`はデータベース内の全てのテーブルをDropするので、データベースをLaravelアプリケーション以外と共有している場合は`migrate:refresh`等を検討してください。


## 3. 挿入する
出力したデータを再度データベースに追加します。変更したテーブル定義が、変更前と互換性がないと、挿入できないので注意してください。

```sh
mysql -u user_name -ppassword -D database_name < ~/dumps/database_name_20210101.dump
```

エラーがでなければ、大丈夫です。
Flutterのroute設定

[Routeについてのチュートリアル](https://resocoder.com/2019/04/27/flutter-routes-navigation-parameters-named-routes-ongenerateroute/)を紹介します。


# named routeを使うとシンプルに書ける
## named routeを使わない方法

ボタンを押すとページ遷移するアプリケーションを考えます。

以下のように`MaterialPageRoute`を記述することはできますが、Viewのコードが複雑になる、コードが重複する等の不便があります。

```dart
RaisedButton(
  child: Text('Go to second'),
  onPressed: () {
    // named routeを使わずに直接routeをpushする書き方
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (context) => SecondPage(data: 'Hello there from the first page!'),
      ),
    );
  },
)
```

## named routeを使う方法

1、 named routeを使ってrouteを生成するクラスを作成します。これはMaterialAppの`onGenerateRoute`に設定するメソッドになります。


```dart
class RouteGenerator {
  static Route<dynamic> generateRoute(RouteSettings settings) {
    final args = settings.arguments;

    switch (settings.name) {
      case '/':
        return MaterialPageRoute(builder: (_) => FirstPage());
      case '/second':
        return MaterialPageRoute(
          builder: (_) => SecondPage(data: args),
        );
    }
  }
}
```

2、 先程作成したコードを参考にMaterialAppに`initialRoute`、`onGenerateRoute`を設定します。

```dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
/// ...省略
      // Initially display FirstPage
      initialRoute: '/',
      onGenerateRoute: RouteGenerator.generateRoute,
    );
  }
}

```

３、`Navigator.of().pushNamed`の引数でnamed routeを使えるようになります。`arguments`で次のページに引数を渡せます。

```dart
RaisedButton(
  child: Text('Go to second'),
  onPressed: () async {
    Navigator.of(context).pushNamed(
      '/second',
      arguments: 'Hello from the first page!',
    );
  },
),
```

# ついでに色々遊んで見る

## 遷移先から戻る際に引数を受け渡す

1、`SecondPage`に`Navigator.of.pop()`するボタンを設置します。`pop()`に引数を渡します。

```dart
// SecondPage
RaisedButton(
  child: Text('Go to second'),
  onPressed: () {
    Navigator.of(context).pop('I\'m back from second page!');
  },
),
```

２、`FirstPage`のボタンの`onPressed()`を非同期にメソッドにして、`Navigator.op().pushNamed()`の戻り値で引数を受け取ります。
この非同期メソッドは画面遷移されるまでの、とても長い`await`をします。

```dart
// FirstPage
RaisedButton(
  child: Text('Go to second'),
  onPressed: () async {
    // 遷移先から戻る際に引数を受け取る
    var result = await Navigator.of(context).pushNamed(
      '/second',
      arguments: 'Hello from the first page!',
    );
  },
),
```

## モーダル表示する

以下のように`fullscreenDialog: true`となるnamed routeを追加すると、モーダル表示（下から表れる形式）ができます。

```dart
class RouteGenerator {
  static Route<dynamic> generateRoute(RouteSettings settings) {
// ...省略
      case '/second_modal':
        // Validation of correct data type
        if (args is String) {
          return MaterialPageRoute(
            builder: (_) => SecondPage(
              data: args,
            ),
            fullscreenDialog: true,
          );
        }
// ...省略
```

Navigatorはよく使うので色々触っておくと良いと思います。
Webサーバーの仕組み【実際にどうなってるの？】初学者用

Webサーバーの仕組み、知りたいですよね。とりわけ、PHPやRubyなどを使う人にとって必須のことなので学んでおきましょう。私自身、勉強してまとめてみました！

![Webサーバーの仕組み.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437473/a1fa2824-2339-1a5d-354f-f320d8b60de9.jpeg)


##http通信の仕組み

まずは通信について、つまりhttpの流れについて復習してみましょう。下記のことが行われています。

* パソコンのブラウザからURLをクリックもしくはタイピング（リクエスト）
* URLに対応したものをWebサーバーはパソコンに返す（レスポンス）


サービスを受けたい客（クライアント）からのお願いを、サービスを提供するもの（サーバー）が応えるという形でhttp通信は行われています。

少し難しい言葉で説明すると...

HTTP（決まりごと）を処理できるプログラムがWebサーバーというわけです。アプリケーションを作ってもサーバーがなければ公開ができないので、絶対に必要なことですね。

##Webサーバー（常駐プログラム）の中で何が起きているか

サーバーをPC内に準備したことを考えてみましょう。

サーバー用のPCに「Webサーバー・ミドルウェア」を用意します。Webサーバーとして__Apache（アパッチ）__もしく__はNginx（エンジンエックス）__を使います。

MAMPというサービスには、Apacheが入っています。PHPをローカル開発するには必須ですね。簡単にインストールして使えるのでおすすめ。

###Apacheとは

* オープンソースなもの
* 利用の際の制限がほぼなし
* PHPはApacheと相性がいい

###Nginxとは

* 発音を間違えそう...
* 最近人気が出ている
* 並行処理性能が高い
* メモリ消費が少ない。

##PHPで主に使うApacheについて知ろう！

Apacheは、リクエストされたURLに対応したものをレスポンスとして返すのが仕事です。

例えば__http://ドメイン/index.php__というリクエストが来たら、Apacheはindex.phpを探して、レスポンスとして返してくれます。

もし存在しないものを要求されたら、__404 Not Foundエラー__を返してくれます。要求に応えてくれる賢いロボットのよう！

###Apacheの設定ファイルについて

https.confがApacheの設定ファイルです。

```
vi /etc/httpd/conf/httpd.conf
```

この中の__DocumentRoot__にあります。DocumentRootの下にあるものをレスポンスとして返してくれます。

リダイレクトの設定やphpの設定を変更したい場合は、以下の二つのうち一つを使います。

* httpd.conf
* .htaccess

###リダイレクト（転送処理）について

Apacheは、サーバー内にあるものを返すだけでなく、他のサーバーにリダイレクトすることもできます。古いサーバーから新しいサーバーにサービスが移ったという時に働いてくれるので、助かりますね。

	Apacheの設定ファイル
		リダイレクトの設定やphpの設定を変更したい場合...

		１）httpd.conf
		２）.htaccess

##まとめ

「Webサーバーは毎日生活する際に、大変お世話になっているものだ」ということがわかりましたね。Webエンジニアを目指す人は必ず知っておくべきことなので覚えておきましょう！

私はまだまだ知らないことだらけなので、間違っていたら教えてくださいませ。（コメントを送ってくださる方、いつもありがとうございます！）
Rspec問題２

##事前準備

ターミナル上で下記コマンドを実行してcloneする。

```
git clone https://github.com/Shu-Hos/pictweet_error.git
cd pictweet_error
bundle install
yarn install
rails db:create
rails db:migrate
```

###問題１
ターミナルで下記コマンドを実行してください。

```
bundle exec rspec spec/models/user_spec.rb
```

すると`NoMethodError:
undefined method name=' for #<User:xxxxxxx>’`のエラーが発生するかと思います。
まずはこちらをヒントなしで解決しましょう。



###問題2
上記のエラーが改善されて再度こちらのコマンドを実行してください

```
bundle exec rspec spec/models/user_spec.rb
```

しかしテストの結果は、`Failure/Error:expect(user.errors[:nickname]).to include("is too long (maximum is 6 characters)")`が残ってしまっているかと思います。
こちらを修正してuserのモデル単体テストを成功させてください。

<details><summary>ヒント</summary><div>
binding.pryでuserの中身を確認すると条件分岐の結果がtrueになっているかつエラーメッセージが空になっているかと思います。
バリデーションが怪しいかも？
</div></details>

###問題3
問題2まで解き終えたら次はtweetのmodel単体テストです。
以下のコマンドを実行してください。

```
bundle exec rspec spec/models/tweet_spec.rb
```
すると正常系のテストコードがすべてfailuresになってしまいます。
こちらの修正をお願いします。


<details><summary>ヒント</summary><div>
binding.pryで@tweetの中身を確認してみましょう。

</div></details>

###問題4
次はtweets_controllerの単体テストです。
以下のコマンドを実行してください。

```
bundle exec rspec spec/requests/tweets_spec.rb
```

すると、`ActionController::UrlGenerationError`が発生するかと思います。
エラー文をよく読んでこちらの問題を解決しましょう。

<details><summary>ヒント</summary><div>
 エラー文はP`No route matches {:action=>"show", :controller=>"tweets"}, missing required keys: [:id]`と出ているはずです。必要に応じてrails routesコマンドでshowアクションのパスを確認してみましょう。
</div></details>


ここからはtweet機能の結合テスト問題です。

###問題5
以下のコマンドを実行してください。

```
bundle exec rspec spec/system/tweets_spec.rb
```

ログインページでログインができずに`Capybara::ElementNotFound:Unable to find field "email" that is not disabled`というエラーが発生するかと思います。
まずこちらを解決しましょう。

<details><summary>ヒント</summary><div>
ElementNotFoundと出ているので検証ツールで要素の中身を確認してみましょう。
</div></details>

###問題６
こちらで最後の問題になります！
再度以下のコマンドを実行してください。

```
bundle exec rspec spec/system/tweets_spec.rb
```

以下のエラーが起きたかと思います。
`Failure/Error: expect(page).to_not have_no_selector 'form'expected to find css "form" but there were no matches`


<details><summary>ヒント</summary><div>
テストの実行文とexpectedの実行結果の英文の意味を調べてみると良いかも知れないです。

</div></details>
お疲れさまです！！
何かご不明点とかあれば、今後ぜひ教えてください！
ArchUnit 実践：ドメイン層で発生した例外は UI 層やアプリ層で捕捉しきる（大域例外ハンドラで捕捉しない）

```
// 実行環境
* AdoptOpenJDK 11.0.9.1+1
* Spring Boot 2.4.0
* JUnit 5.7.0
* ArchUnit 0.14.1
```

## アーキテクチャテストのモチベーション

ドメイン固有の例外は、そのユースケースを制御する責務をもつコントローラーやアプリケーションサービスで捕捉し、適切な後処理を行うべき。

Spring Boot でいうと、`@ExceptionHandler` を付与したメソッド（大域例外ハンドラ）が、ドメイン層の例外を捕捉しないことを担保したい。

## アーキテクチャテストの実装

```java
package com.example;

import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import org.junit.jupiter.api.Test;
import org.springframework.web.bind.annotation.ExceptionHandler;

import java.util.List;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.methods;

class ArchitectureTest {

    // 検査対象のクラス
    private static final JavaClasses CLASSES =
            new ClassFileImporter()
                    .withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
                    .importPackages("com.example");

    @Test
    void ドメイン層で発生した例外を大域例外ハンドラで捕捉しない() {
        methods().that().areAnnotatedWith(ExceptionHandler.class)
            .should()
            .notHaveRawParameterTypes(new DescribedPredicate<>("ドメイン層の例外クラス") {
                /**
                 * @param params `@ExceptionHandler` でアノテートされたメソッドの引数のリスト
                 * @return 引数にドメイン層の例外クラスを含む場合、true
                 */
                @Override
                public boolean apply(final List<JavaClass> params) {
                    JavaClass exceptionClass = params.stream()
                            .filter(clazz -> clazz.isAssignableTo(Exception.class))
                            .findFirst()
                            .orElseThrow();

                    return exceptionClass.getPackageName().startsWith("com.example.domain");
                }
            })
            .check(CLASSES);
    }
}
```
Mac今昔

ども。
Hiro_Matsunoです。
Mac歴は16年になります。
あえて今回は今昔物語でも書こうかなと思っています。
[macOS Advent Calendar 2020](https://qiita.com/advent-calendar/2020/macos "macOS Advent Calendar 2020")の８日目になります。
#Macとの出会いとその遍歴
Macとの出会いは実は高校時代になります。
母親がパソコンに興味をもち姉が当時MacでCADを作る仕事をしていた関係で自宅にも一台ということで買ってきたのが一番最初だった気がします。
実はあの名機MacSE/30でして実は俺自身が電源ぶっ壊しまして筐体とご対面することになりました。
なんとサイン入りというのは本当で当時英語読む気がなかった自分でさえなんでパソコンにサインが入ってるんだろうと思ったくらいでした。
実は専門学校卒業するまでの間家で活躍してくれたのもこのマシンでした。
実は有名人のサインが山ほど書かれていたと知ったのは実は電源壊して１０年後に知ることになります。
当時はMacOSとは名乗れなく漢字Talkと名乗ってました。
実は母校にも持ち込んで使ったことがありますｗ。
その後うちに来たのがPowerMac８１００でして姉の仕事をよくサポートしてくれてました。
実はあのころのMacはやっと日本でもMacOSと名のれるようになりましてMacOS８時代を支えてくれました。
あのあとはこれも名機のiMac（電気スタンド）でした。
あの頃のMacOSXは使いにくかったので実はWindowsに浮気しました。
Windows機４台乗り継ぎスマホ育成生になったときの師匠からMacBookWhite２００８を２万で譲っていただいてからはひたすらMac人生を歩んでいます。
SnowLeopardまでMacBookWhite2008に付き合ってもらいこのあとはMacBookAir2013LateのCPUカスタムに乗り換えしました。
こいつはまだまだ現役でして実は２TBのハードディスクを実装しています。
このあとは今の現役機MacBookAir2018Late１．５TBメモリ１６GBモデルに乗り換え今に至ります。
#MacOSはどう思っていたのか
最初はすげぇ高いパソコンで画面が使い勝手欲っていいなぁと思ってましたが。
半分遊び道具でした。
出会った当時は高校生だったしね。
今ではなくてはならないUnix機としても相棒としても鬼に金棒ですね。
今はVisualStudioCodeがあれば何でも開発できるのでｗ。
#M1に興味があるのか
興味がないと言ったら嘘になるので興味があると言っておきます。
M1はまだ出立ててARMアーキテクチャに強引にBSDを動かしている状況なのでなんとも言えません。
BSDの機能の半分もARMアーキテクチャに実装できていないと思っています。
まぁ、これからオープンソース陣営が大挙して実装に取り組むみたいなので期待をしたいと思っています。
正直言うと開発環境が整っていないと仕事ができないのでなんとも言えないなぁという気持ちで一杯です。
#AWSにMacMiniがやってきた。
これには半分びっくりしています。
AWSが大マジでMacMiniをクラウドの世界に持ってくるなんて思いませんでした。
正直これから自分の相棒がIntelMacではなくなってもAWS上では使えるわけですから(￣ー￣)ﾆﾔﾘ。
これには大変嬉しいということだけは伝えておきたいと思います。
WindowsユーザもこれでMacの実機がクラウドに持てるんだからこれほどいいことはないでしょう。
M1MacMiniも来るらしいので期待できると思います。
#MacOSを愛してますか
もちろん大好きですよ。
一時期Web開発してまして２年半ぐらいずっと夜もはばからず盆暮れ正月無しで仕事をしていた時期があります。
その時言われて傷ついたことはMacばっかで開発しやがってと言われOpenOffice使ったときなんかこれ使ってほしくないんだけどと言われすごく凹んだ時期もありましたが今でも正直言うとLinuxと同じくらいMacOSが好きです。
BashじゃなくてZshに変わっちゃったけど。
やっぱりコマンドが効くOSが好きなんですよね。
実は一時期本業としてUnixのシスオペだったりLinuxサーバ構築だったりしていた人間としてはやっぱりCUIがないと生きられませんｗ。
今はPHPerとして開発者を本業としてWindowsで開発していますが裏ではAWSいじってたりもします。
Macは開発者としてもすごく使える相棒なのでこれからも使い尽くしてやりたいなぁと思います。
実は三台とも家にあるのですが愛着があり手放せません。
たとえOSの対応が終わったとしても使ってやりたいなぁと思ってます。
将来的にはM1Macに乗り換えるんだけど当分の間はIntelMacで行こうかなと思っています。

今日は長々とすいませんでした。
jsで外部サイトのファイルをダウンロードする

## ファイルをダウンロードさせたい
aタグの`download`属性を指定するとページ移動ではなくファイル保存させることができますが  
同一originでしか動作しません。


## 代替手段
fetchでファイルを取得後に「FileSaver」のsaveAsで保存させることで実現することができます
https://github.com/eligrey/FileSaver.js/

```js
const videoDownload = async (url: string) => {
  const data = await fetch(url);
  const blob = await data.blob();
  saveAs(blob);
};
```

```html
<a onClick="videoDownload('http://[ダウンロードさせたいファイルのURL]')"></a>
```
Ruby で解く AtCoder Educational DP Contest D ナップサック問題

# はじめに
*[AtCoder Problems](https://kenkoooo.com/atcoder/#/)* の Recommendation を利用して、過去の問題を解いています。
AtCoder さん、AtCoder Problems さん、ありがとうございます。
# 今回のお題
*[AtCoder Educational DP Contest - D - Knapsack 1](https://atcoder.jp/contests/dp/tasks/dp_d)*
Difficulty: ---

今回のテーマ、動的計画法

以前の投稿 [Ruby の Hash における keys.each と each_key の違い](https://qiita.com/superrino130/items/965ac708eb2d48f47952) では、ハッシュや配列にマーク代わりとして`1`を代入していましたが、ナップサック問題は重さ(weight)と価値(value)の二次元になりますので、価値を代入していきます。
# Array コピー
```ruby.rb
n, mw = gets.split.map(&:to_i)
p = n.times.map { gets.split.map(&:to_i) }
dp = Array.new(mw + 1, 0)
p.each do |w, v|
  dp_tmp = dp.dup
  w.upto(mw) do |i|
    dp_tmp[i] = dp[i - w] + v if dp[i] < dp[i - w] + v
  end
  dp = dp_tmp
end
puts dp[mw]
```
```insert.rb
    dp_tmp[i] = dp[i - w] + v if dp[i] < dp[i - w] + v
```
`1`の代わりに、価値を代入しています。
# Array 後ろから
```ruby.rb
n, mw = gets.split.map(&:to_i)
p = n.times.map { gets.split.map(&:to_i) }
dp = Array.new(mw + 1, 0)
p.each do |w, v|
  mw.downto(w) do |i|
    dp[i] = dp[i - w] + v if dp[i] < dp[i - w] + v
  end
end
puts dp[mw]
```
詳しい内容は、けんちょんさんの [ナップサック DP を in-place 化](https://qiita.com/drken/items/68b8503ad4ffb469624c#%E3%83%8A%E3%83%83%E3%83%97%E3%82%B5%E3%83%83%E3%82%AF-dp-%E3%82%92-in-place-%E5%8C%96) ここら辺を参照願います。

~~Hash版もトライしたのですが、うまくいかなかったです。~~
# Hash （追記）
```rb:Hash
n, w = gets.split.map(&:to_i)
wv = Array.new(n){ [0, 0] }
n.times do |i|
  wv[i][0], wv[i][1] = gets.split.map(&:to_i)
end
dp = Hash.new(0)
dp[0] = 0
wv.sort_by{ |wv| [wv[0], wv[1]] }.each do |wv|
  dp.keys.sort.reverse.each do |k|
    if k + wv[0] <= w && dp[k + wv[0]] < dp[k] + wv[1]
      dp[k + wv[0]] = dp[k] + wv[1]
    end
  end
end
puts dp.values.max
```

||Array コピー|Array 後ろから|Hash|
|:--:|:--:|:--:|:--:|
|コード長 (Byte)|257|221|375|
|実行時間 (ms)|852|864|1514|
|メモリ (KB)|75024|15044|108348|
# まとめ
+ D - Knapsack 1 を解いた
+ Ruby に詳しくなった
Amazon Rekognitionでユーザーがアップロードしたアレな画像を<del>収集</del>ブロックする

AWSのML系のサービスに[Amazon Rekognition](https://ap-northeast-1.console.aws.amazon.com/rekognition/home?region=ap-northeast-1#/)というのがあり、画像の認識に使えるAPIが用意されています。

ユーザーからアップロードされた画像をサイト上に表示する場合などに、まあ何というかいろいろとアウトな感じの画像をアップロードされるとよろしくないですね。そこでこのRekognitionを使うと、inappropriateな要素にタグ付けをしてくれます。

## 実装例

Node/TypeScriptでの実装例です。画像をBufferで受け取って、アウトっぽい画像なら`false`を返します。以下のドキュメントの内容を基にしています。

https://docs.aws.amazon.com/rekognition/latest/dg/procedure-moderate-images.html

```ts
import * as AWS from 'aws-sdk';

AWS.config.update({
  region: 'ap-northeast-1'
});

export class RekognitionModerator {
  public async moderate(image: Buffer): Promise<boolean> {
    const rekognition = new AWS.Rekognition({apiVersion: '2016-06-27'});
    const params: AWS.Rekognition.DetectModerationLabelsRequest = {
      Image: {
        Bytes: image,
      },
      MinConfidence: 99.5
    };

    const res: AWS.Rekognition.DetectModerationLabelsResponse = await rekognition.detectModerationLabels(params).promise();
    if (res.ModerationLabels && res.ModerationLabels.length > 0) {
      return false;
    }

    return true;
  }
}
```

ユーザーがアップロードしてきた画像をこのクラスでチェックすれば、いかがわしい画像をブロックできます。登録はさせないけどサーバーのどこかに保存しておく、みたいな邪悪なことをやるのはやめましょう。

いくらなんでもここにテスト用画像貼ると怒られるので貼りませんが、画像いくつか集めてきて試してみると

健全なしずかす絵

```json
{ ModerationLabels: [], ModerationModelVersion: '4.0' }
```

不健全なしずかす絵

```json
{
  ModerationLabels: [
    {
      Confidence: 99.9688949584961,
      Name: 'Explicit Nudity',
      ParentName: ''
     },
    {
      Confidence: 99.9688949584961,
      Name: 'Illustrated Explicit Nudity',
      ParentName: 'Explicit Nudity'
    }
  ],
  ModerationModelVersion: '4.0'
}
```

7ct Kindle版11ページ

```json
{ ModerationLabels: [], ModerationModelVersion: '4.0' }
```

Rekognitionからはこんな感じのレスポンスが返ってきます。`Confidence`は結果の信頼度、どのくらいの精度でアウトなのかを示す数値です。高いほど結果が信頼できるということになります。

サンプルコードでは`MinConfidence: 99.5`という指定をしていました。この場合Rekognitionは`Confidence`が99.5以上の結果しか返さない、という動きになります。ちなみにデフォルト値は50なので相当緩く設定しています。

いろいろ試してみた感じ、特に二次元にはわりと厳しいようで、別にR指定が付くような画像でなくても露出度高めの衣装とかだと98とか99とかそんな値が返ってくることが時々あります。二次元の画像を主に扱う場合は99.5あたりを機械検出の閾値にして、後は人間がモデレーションする（適宜巡回する、通報を受け付ける）のが現実的なところかな、というのが個人的な感覚です。
AtCoder過去問を使って新人にSwiftを練習させてみると良かった

# はじめに
チームに入ってきた新人が、Swift/iOS開発を[N予備校](https://www.nnn.ed.nico/)などでやったものの、
関数もかけない状況というのが判明しました。

AtcoderでSwiftを練習させてみたので振り返りです。


# 訓練のフォーマット
1. A問題を5問とく。B問題を1問とく。
2. 全部完答したら、ACした他の人の回答をみる。初めてみるAPIを調べる。
3. 自チームのプロジェクトでそのAPIを全文検索して、何をしているか議論してみる。


## A問題を5問とく、B問題を1問とく
A問題を説いていくことで、程よい達成感を得てもらい、慣れたらB問題で少し考える問題にも挑戦してもらいます。

問題を説いてSwiftをガシガシ書いてもらいたいというフェーズです。
やってない問題は[AtCoder Problems](https://kenkoooo.com/atcoder#/table/)で確認します。

## 全部完答したら、ACした他の人の回答をみる。初めてみるAPIを調べる。

他の人の回答が見られるのは、AtCoderの良さの１つだと思います。
提出結果の全ての提出から`Swift`を選択して見ていきます。(Swiftは人少ない！w)　

![スクリーンショット 2020-12-08 20.26.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199256/9f9438ea-08a6-dea3-d80b-c22eb96a357f.png)

自分の書いた答えと、他の人が書いたコードを比べてみてもらいます。

その中で、自分の見たことのないAPIを調べてもらいます。（僕が説明したものもあります）
新人が見たことのないやつというのは、`map`や`filter`、`reduce`などです。


## 自チームのプロジェクトでそのAPIを全文検索して、何をしているか議論してみる。
学んだAPIがちゃんとプロジェクトでも使われているよ！ということを知ってもらうために検索してもらいました。
使い方やコードリーディングの練習のためです。

ここはどのように使われているかなど解説したり議論しました。

# AtCoderでの落とし穴

Swiftが最初の[A - Welcome to AtCoder](https://atcoder.jp/contests/practice/tasks/practice_1)という問題の例にありません！

初心者が解くのは難しいので、以下のコードを教えてあげる必要があります。
[[AtCoder]Swiftでも競プロがしたい！ - Qiita](https://qiita.com/kntkymt/items/4f02c6b90462f354de6d)より引用

```swift
// 標準入力からIntを読み込む
let a = Int(readLine()!)!

// 標準入力からInt配列を読み込む
let bc = readLine()!.split(separator: " ").map { Int($0)! }

// 標準入力から文字列を読み込む
let s = readLine()!

// bcは配列なので、bc[0]にb bc[1]にcが入っている
let sum = a + bc[0] + bc[1]

// スペース区切りで出力
print(sum, s)
```

# AtCoderでの初心者教育のよかった点
* ちょうどいい問題の大きさで、プログラミングで問題を解く楽しさがわかる
* 他の人のコードを見て学べる
* 業務外でも勉強するきっかけになる (ちゃんと勉強しているらしい！)
* 仕様を読んで、実装する訓練になる

実務でも重要な点が詰まってますね！

# おわりに
初心者がプログラミングの教本や入門動画を見ただけだと、いざ書いてみると全くできないことが多いと思います。

競技プログラミングでは、読んで、理解して、プログラムという流れが細かいリズムで体験できるので、プログラミングに慣れるのに適していると感じました。
7日目：メリーゴーラウンドで学ぶアニメーションをボタンで実行する方法

この記事はアドベントカレンダー「[【VCI】テーマパークを作ろう](https://adventar.org/calendars/5855) 」の7日目の記事です。

# 今回の内容
今回はメリーゴーラウンドを作成しながら以下のことを学びます

* アニメーションの設定方法
* ボタンを押して何かを動かすスクリプトの書き方

# アニメーションとは
アニメーションとは作成したオブジェクトに動きをつけることのできるUnityのコンポーネントとなります。
ここで作成したアニメーションをVCIで実行することで、複雑な動きもほぼスクリプトを書かずに実行できます。
VCIでは使えるアニメーションが限られてたりします。詳細は以下参照
　・VCIのアニメーションページ一覧(https://virtualcast.jp/wiki/doku.php?id=vci:sample:animation)

# Unityでのアニメーションの設定
今回はメリーゴーラウンドにラウンドに回転のアニメーションを付けていこうと思います。
作成したモデルは以下のように回転する部分(RotateObject)とそうでない部分(Static)に分けておきました。
このRotateObjectを回す設定を作成していきます
![20201207-030021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/6a013efc-98b2-0d2c-9b4b-65d639d21f54.png)

まず、オブジェクトを選択し、animationウィンドウでcreateを押してアニメーションクリップを作成します。この際にanimatorコンポーネントがオブジェクトに自動で付きます。
[注意] このanimatorをつける部分は動かしたいオブジェクト(今回ではRotateObject)より1つ以上上の階層である必要があります。**動かしたいオブジェクトそのものにanimatorをつけると正常にエクスポートできません**

次にanimationウィンドウでanimationを設定します。今回は5秒後から約1分回るような設定を入れました。
回転アニメーションはこのままではVキャスでは動かないため、Rotationの右側のひし形>Interpolation>EulerAngles(Quaternion)を選択してください。(よく把握できてないが回転の計算方法の切り替えをやっている？)
![20201207-030021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/f8aafe45-59fc-405b-e997-1eb8fe4fcc33.png)

# ボタンの作成
次に回転のアニメーションを実行するためのボタンを用意します。
とはいってもボタンオブジェクトのようなものはないため、CubeObjectにグリップで反応できるようにSubItemコンポーネントを使用して実現していきます。


### 設定方法
まず空オブジェクトを作成し子にCubeオブジェクトを作成します。
空オブジェクトにはSubItemコンポーネントを追加します。
今回はCubeをどっかにもっていかれると困るため、RigitBodyのConstraintsの設定を行います。
Constraintsはどの軸の移動・回転をさせないようにするかを設定できます。今回はいずれの軸も移動も回転もさせたくないため全部チェックを入れます。
![20201206-231859.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/1670e192-51da-43d6-e2c2-411c5e3ee8c3.png)

Unityでの設定は以上です。
完了したらエクスポートしてseedOnlineに取り込んでください。

### スクリプトの作成 
ここからはVキャス及びエディタでの作業となります。

今回はアニメーションを設定したいため、以下のページを参考にコードを書いていきます
　・ [vci.assets(ExportAnimation)](https://virtualcast.jp/wiki/doku.php?id=vci:script:reference:exportanimation)

上記ページを参考に作成したコードが以下のようになります。

``` lua
-- アニメーションの設定の作成。
local table = { wrap_mode="once", speed=1 }
local carouselAnimeSetting = json.serialize(table)

---[SubItemの所有権&Use状態]アイテムをグラッブしてグリップボタンを押すと呼ばれる。
---@param use string @押されたアイテムのSubItem名
function onUse(use)
  --今回作成したボタン「Start_Carousel」が押されたときのみ実行される
  if use == "Start_Carousel" then
    --Carouselに紐付いたアニメーションを取得する。
    local anime = vci.assets.GetTransform("Carousel").GetAnimation()
    --RotateCarousel(作成したアニメーション)を作成した設定で再生する。
    anime._ALL_PlayWithState("RotateCarousel", carouselAnimeSetting)
    -- 速度変更しないのであれば以下の記載でもOK(第2引数はloopするかどうかのフラグ)。この関数の場合設定の作成は不要。
    -- anime._ALL_PlayFromName("RotateCarousel",false)
  end
end
```
onUseを関数ですが、こちらはサブアイテムのオブジェクト(またはその配下のオブジェクト)がグリップされたときに実行される関数です。
引数のuseにはグリップしたSubItem名が入ります。コライダーが入ってるオブジェクト名ではないので注意してください。
また、onUseの関数はグリップした本人のみ処理が走ります。そのため_ALL_なしでアニメーションを再生するとグリップしたひとのみしか動かないため、_ALL_付きの関数を呼び出すことで全員再生されるようにしています。

実際にCubeをグリップして動きだせば完了です。
(Vキャスには座る機能がないため立ったまま回ってます。Vキャスに座る機能が来るのを気長に待ちましょう。)
![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/a72ca536-b2ca-202e-87f9-ddeff35afa6b.gif)

# 終わりに 
いかがでしたでしょうか？
今回は回転だけでしたが、もちろん馬を上下させるアニメーションを設定することも可能です。
次回はスポーンポイントの設定を書こうと思います。
プリザンターの一覧画面で特定条件の行に色をつける（サーバスクリプト）

本記事は [Pleasanter(プリザンター) Advent Calendar 2020](https://qiita.com/advent-calendar/2020/pleasanter) 8日目の記事です。

# 最新機能

12/3にリリースとなったサーバスクリプトの最新機能が続々とリリースになっています。昨日のセルにCSSで装飾できる機能に続き、行にCSSで装飾できる機能が完成しました。条件に合わせて行単位にCSSを出力する機能はこれまでありませんでしたが、サーバスクリプトにより簡単に実装可能になりました。

|製品|バージョン|
|---|---|
|.NET Framework版|0.50.202.*|
|.NET Core版|1.1.11.0|

※ CentOSなどのLinux環境で動作させるためには下記の追加のセットアップ手順が必要です。
https://pleasanter.net/fs/publishes/2396324

# スタイルの登録

テーブルの管理からスタイルタブを開き、下記のスタイルを登録します。出力先は一覧画面とします。

```css
/* 自分が担当のレコードを目立たせたい */
.own {
    background-color: yellow;
}
```

# サーバスクリプトの登録

テーブルの管理からサーバスクリプトタブを開き、下記のスクリプトを登録します。条件は「行表示の前」とします。

```javascript
// 条件は「画面表示の前」にチェック
// 管理者または担当者が自分の場合にスタイルを適用する
if (model.Manager === context.UserId || model.Owner === context.UserId) {
    model.ExtendedRowCss = 'own';
}
```

# 適用結果

登録したサーバスクリプトにより、管理者または担当者が自分の場合に行を目立つようにすることができました。クライアントサイドのJavaScriptで実装するより、かなり簡単に実装することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/3e887dd9-4598-3b94-36e7-961552439cd8.png)

このサンプルは、デモ環境の「プロジェクト管理の例」の「WBS」テーブルでご確認いただけます。デモ環境は下記からご利用いただけます。
https://pleasanter.azurewebsites.net

今後も無料で使えるオープンソースのプリザンターの機能強化に取り組んでまいります。ぜひご期待ください！メリークリスマス！🎅
Markdownのテスト仕様書を管理したい！

## 忙しい方へ

おそらく、大抵のソフトウェアの仕様書はExcelで管理することが多いと思います。しかし、バージョン管理や差分がGitHubと比べてイマイチだと思っていました。

そのような問題を解決するために、まずは（個人的に）取り組みやすいテスト仕様書をMarkdown+GitHubで管理するという試みをしてみました。バージョン管理や差分管理は確かにやりやすくなりました。ついでに、一覧で眺めたり集計したいときに変換するpythonスクリプトも作成しました。

変換ソースコードは [GitHub](https://github.com/k-watanb/md_test_case_to_excel) で公開しています。

![image-20201130175253467.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285702/94df0c02-61b0-5996-e3a8-271cde3ec54f.png)

## 不要なExcelを撲滅したい

未だにソフトウェアの仕様書にExcelを管理する場合が多いと思います。私はこのExcel管理に嫌気がさしていました。

- **バイナリデータのため、GitHubなどのバージョン管理ツールとの相性が悪い。**"〇〇\_最終版.xlsx", "〇〇\_最終版\_new.xlsx", "〇〇\_最終版（これを使う）.xlsx"のようなファイルが同一ディレクトリ内にあると禿げそうになります。
- 誰がいつどのように編集したのか、という差分管理もイマイチ。
- ファイルが大きくなると、オープンや保存にも異様に時間がかかる。
- そもそも仕様書がどこにあるかが、誰かに聞かないとわからない

等、挙げればキリがありません。ソースコードはGitHubで管理しているのだから、同じ場所・同じツールで仕様書を統一管理したいという思いが強くなっていきました。

とはいってもいきなり全部を置き換えるのは難しいため、まずは個人的に取り組みやすかったテスト仕様書Excelの撲滅に取り組みました。

## Markdown+GitHubによるテスト仕様書管理

Markdown+GitHubならば上記の悩みをほぼ解決してくれましたが、Markdownはテキストベースのため、一覧表示ができなかったり、集計作業はできませんでした。そこで、Markdown型テスト仕様書をExcelに変換するpythonスクリプトを作成しました。ソースコードは [GitHub](https://github.com/k-watanb/md_test_case_to_excel) で公開しています。

## 実際に使ってみて

実際のプロジェクトで運用してみて、良い点もあれば課題も見えてきました。

### 良かった点

- ソースコードと同じディレクトリ階層で仕様書を管理できるため、仕様書を探す手間が省けた。
- 仕様書内まで一括検索・置換ができるようになった（Excelは開くまで中身がわからなかった）。
- バージョン管理や差分管理がものすごく快適になった。
- オープンにもほとんど時間がかからず、生産性が向上した。
- IDEだけで作業が完結するようになった。IDE/エディタとExcelのにらめっこ作業がなくなった。

### 課題

- 図表現が弱い。テスト結果のスクリーンショットの貼り付けができない。
- 集計作業ができない。ここはさすがにExcelに軍配。

## さいごに

Markdownによる仕様書管理はまだまだ発展途上ではありますが、正直従来のExcel管理よりかは恩恵が大きいと感じました。旧式の方法を一新するのは中々骨が折れますが、できる範囲で続けていこうと思いました。次はもっと別の仕様書で。

## 参考文献

- [Excelな設計書をMarkdownにしてみた](https://qiita.com/fuga___/items/e77e5f3acd536536613d)
- [torisawa/convert.py](https://gist.github.com/toriwasa/37c690862ddf67d43cfd3e1af4e40649)
IE11だとFullCalendar5.4.0の日本語化ができない？「SCRIPT1003: ':' がありません。」エラー

# こんな人向け
* fullcalendar-5.4.0\lib\locales\ja.jsを使っていて、IE11でも表示させたい
* FullCalendarを日本語化させて使いたい
* 「SCRIPT1003: ':' がありません。」エラーが出る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/347716/b55f3ba1-27d5-0fa1-3bdd-b6fa518bb7d0.png)

# 修正箇所
```javascript

moreLinkText(n) {
    return '他 ' + n + ' 件'
},
```

↓このように修正してください。

```javascript
moreLinkText: function (n) {
    return '他 ' + n + ' 件'
}
```
省略するとIE11では使えません。

# 元のja.js
```javascript
FullCalendar.globalLocales.push(function () {
  'use strict';
  var ja = {
    code: 'ja',
    buttonText: {
      prev: '前',
      next: '次',
      today: '今日',
      month: '月',
      week: '週',
      day: '日',
      list: '予定リスト',
    },
    weekText: '週',
    allDayText: '終日',
    moreLinkText(n) {
      return '他 ' + n + ' 件'
    },
    noEventsText: '表示する予定はありません',
  };
  return ja;
}());
```
フリーランスで案件獲得する為に覚えておきたい事（WEBアプリケーションエンジニア）

# 概要
私は、SEとして10年以上、WEBアプリケーションエンジニアとしてやってきました。

今回フリーランスとして案件を探すうえで、それなりに苦労したので、
フリーランスで案件を獲得するために覚えておきたい事について、私が思った事を書いていこうかと思います。

<b>※　あくまで、私の主観の記事ですので、皆さまの案件獲得の参考程度に、留めて頂けたら幸いです　※</b>

本書を読むにあたって、私のスペックとしては以下の通りです。

> 年齢：30台半ば（アラフォー手前）
> リーダー経験有・社会人経験10年
> 要件定義～試験まで、基本的に何でもいけます。
>
> バックエンド開発　　6年（Javaメイン）
> フロントエンド開発　1年（TypeScript/Angular）
> インフラ構築　　　　特になし（AWS何それ？オンプレしか使った事アリマセン）

他にもC言語系の組み込み系開発の経験もあったりしますが、ここでは割愛します。
基本的に、バックエンドの開発が得意なWEBアプリケーションエンジニアと思って頂ければかまいません。

# 案件獲得にあたって
今回案件獲得にあたって、以下の事を重視して案件を探すことにしました。

・新しい技術にチャレンジする！（今回私は、Pythonサーバサイト＆AWSの案件メインで探す！</b>

おそらく本記事を見て頂いている方は、上記のように、
新しい案件で、新しい技術に取り組もうとする人も多いのではないかと思います。

# 実績
上記を基に、20社くらい案件にエントリーしましたが、
面談までたどり着いたのは、<b>3社</b>でした。ことごとく書類選考で落される始末でした。

自分の技術には自信を持っていたのでショックだったのですが、
今回はそれについて思った事を考察してみようと思います。

# 企業がフリーランスに求めている事
今回面談を受けているうちに感じてきた事は、
企業がフリーランスに求めている事は、<b>何でも屋</b>という事です。（※もちろん一概そうとは言えませんが）

例えば、企業が求める要求スキルが以下だったとします。
> [必須]
・バックエンドの開発経験3年以上
[歓迎]
> ・フロントエンドの開発経験がある方
> ・AWSの構築経験がある方

この場合、「バックエンド10年やっています！バックエンドに関してはベテランです！」って方よりも、
「バックエンドもフロントエンドもAWSもほどほどに出来ます」って方のが、採用されやすいと思いました。

企業がフリーランスに求めているものは、<b>業務遂行する上で不安要素が少ないエンジニア</b>かなと思います。
今回の面談の中で、「t_suzukiさんは、バックエンドとフロントエンドは活躍してくれそうですが、AWSの経験がないのがやっぱりちょっと。。」といった形でお断りされた事もありました。

# 言語というものは、実はそこまで重要ではない！？
今回、Pythonのサーバーサイド案件をメインに探していました。
実はPython自体は経験あっても、私は、<b>Pythonのサーバーサイドの実務経験が無かった為</b>、
その点は少し不安に思っておりました。

しかし、実際に面談を受けてみると、
「t_suzukiさんは、<b>バックエンド開発が豊富なので、Pythonのサーバーサイドでは活躍してくれそう</b>だと感じています。」
という意見を頂けたり、バックエンドの開発に関しては、特に問題ないというフィードバックを受ける事が多かったです。


確かに自分の中では、Javaのバックエンド開発を今まで主体でやってきた分、
他の新しい言語でそれを実践するとなっても、それなりに出来る自信はあります。
おそらく企業側の判断としても、そういった判断をして頂けるケースが多いと思います。

上記は、私の経験に基づいた話ですが、
フロントエンド開発でも、 <b>ReactとVueをこれだけ使っていれば、Angularも問題なく出来るだろう</b> と判断されたり、
インフラ構築でも、 <b>GCPの構築経験があれば、AWSも問題なく出来るだろう</b> と判断されたりするかもしれません。

# 年齢に関して
私は、30半ばでエンジニアとしては中堅の位置にいると思っていますが、
「うちは20代が多いですが、t_suzukiさんはコミュニケーションについては問題ないでしょうか？」と聞かれる事がここ最近増えてきました。

ベテランエンジニアとして、指導にも期待しているという評価を頂ける事もありますが、
歳をとっていくにつれて、年齢の理由で、案件数が減ってしまう傾向もあるので、
早いうちに地盤を固めるという事は大事な事なんだろうなと思いました。

# Mac使える？
企業様のPCが<b>Mac</b>である事が非常に多くなってきました。
<b>※※ 私がフリーランスになって、これまで面談受けてきた中で、半数以上がMacでした。※※</b>

一昔前まではこのような事が無かったかと思いますが、
Windowsしか扱った事がないエンジニアは、Macでの開発に慣れていった方が、今後とも良いかもしれません。

# まとめ（フリーランスが案件獲得する為に）
色々と思った事を書きましたが、
大事なのは<b>インフラ・フロントエンド・バックエンド</b>を幅広く扱えるような、スキルと実績が大事なんだろうなと思いました。

今まではバックエンドだけ出来ればいいや！って思って、エンジニアとして生きてきたところもありますが、
そういう考え方だと、逆に案件の幅を狭めてしまい、エンジニアとしての寿命を逆に縮めてしまいかねないなと思いました。

あとは、<b>自分のスキルに見合った単価の案件か？</b>ということです。
単価の高い案件であればある程、競争率もあがり、案件獲得が難しくなります。
自分の実力を客観的に見たら、このくらいの単価が妥当かな？という線を自分の中で持っておくことも大事かもしれません。


以上となります。ここまで見て頂きありがとうございました。
皆さまの案件獲得の参考になれば幸いです。