OmniAICreator/Qiita-1.07M huggingface dataset:
Cookieとは

HTTPは`ステートレス`なプロトコルであるため、特定のWebクライアントとそのクライアントから送信される複数のHTTP通信を関連づけることができない。
`Cookie`とはWebサーバーがWebクライアントに預けておく固有のデータのことで、このデータを用いてWebサーバーはWebクライアントを識別することができる。

Cookieの送信にはメッセージヘッダーが使用される。初回のHTTPレスポンス時にメッセージヘッダーに`「Set-Cookie」ヘッダー`を含めることによって、CookieをWebクライアントに送信する。
逆に、WebクライアントはHTTPリクエスト時にメッセージヘッダーに`「Cookie」ヘッダー`を含めることによって、CookieをWebサーバーに送信する。

`セッションCookie`とは有効期限が設定されていないCookieのこと。Webブラウザを閉じるとCookieが削除され、WebサーバーはWebクライアントを識別できなくなる。
有効期限が設定されたCookieはWebブラウザを閉じてもCookieが削除されない。セキュリティの観点から有効期限が設定されたCookieの使い所は慎重に選ばなければならない。


# 参考
[【Net】SSL/TLS ハンドシェイクをわかりやすく図解](https://pkiwithadcs.com/ssltls_handhshake/)
[イラスト図解式 この一冊で全部わかるWeb技術の基本](https://www.amazon.co.jp/%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88%E5%9B%B3%E8%A7%A3%E5%BC%8F-%E3%81%93%E3%81%AE%E4%B8%80%E5%86%8A%E3%81%A7%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8BWeb%E6%8A%80%E8%A1%93%E3%81%AE%E5%9F%BA%E6%9C%AC-%E5%B0%8F%E6%9E%97-%E6%81%AD%E5%B9%B3/dp/4797388811)
うぉ！Pythonで引数のデフォルト値をミュータブルな型にした結果

Pythonで初心者ネタを投稿します。
タイトル見てニヤニヤしながら結果を予想して来た皆様、ご想像の通りなのでそっと閉じてください。

Pythonにはミュータブル（変更可能）な型と、イミュータブル（変更不能）な型があります。
bool、int、float、strなどは、イミュータブルな型。
list、dict、setなどはミュータブルな型です。

以下のように、Pythonの引数にデフォルト値を指定したとします。
ショッピングカートの配列に商品を入れる関数です。
デフォルト値には空の配列、つまりミュータブルな型の値を指定しました。

```python
def add_to_cart(product: str, *, cart: list = []) -> list:
    cart.append(product)
    return cart


taro_shopping_cart = add_to_cart("Playstation5")
print(f"太郎さんのカート :{taro_shopping_cart}")

hanako_shopping_cart = add_to_cart("みかん")
print(f"花子さんのカート :{hanako_shopping_cart}")
```
太郎さんはプレステ5をカートに入れ、花子さんはみかんをカートに入れました。
自然ですよね。
この関数を使った結果はどのようになるでしょう。

```
太郎さんのカート :['Playstation5']
花子さんのカート :['Playstation5', 'みかん']
```

花子さんのカートにプレステ5が入ってしまいました。
ワンクリックで決済してたら、卒倒しますね。

Pythonでは、引数のデフォルト値が評価されるのは、関数が定義された時だけです。
なので最初の定義でcartに空の配列が入ってからは、その空の配列がずっと使いまわされます。

解消方法としては、単純でデフォルト値にミュータブルな値を設定しないことです。
ここではNoneを指定しました。

```python
def add_to_cart(product: str, *, cart: list = None) -> list:
    if cart is None:
        cart = []
    cart.append(product)
    return cart


taro_shopping_cart = add_to_cart("Playstation5")
print(f"太郎さんのカート :{taro_shopping_cart}")

hanako_shopping_cart = add_to_cart("みかん")
print(f"花子さんのカート :{hanako_shopping_cart}")
```

実行結果

```
太郎さんのカート :['Playstation5']
花子さんのカート :['みかん']
```


理由は知っている人にとっては当たり前のことですし、PyCharm先生もちゃんとハイライトして"Default argument value is mutable"って注意してくれるので、ハマる人はたぶんいないと思います。

ただただ、adventカレンダーにちょっと参加したかっただけです。
そしてまだこれを知らなかった人が検索してこの記事を読んで理解してもらえたら嬉しいです。
declare(strict_types=1); でPHPのstrictモードの設定をする

業務でPHPファイルに `declare(strict_types=1);` を導入するにあたり調べたことをまとめます。

## declare(strict_types=1); の意味を解く

### declare
    
あるコードブロックに対して、何らかの設定をするための構文。
`declare(ディレクティブ)`のように書いて使う。
    
現在のところ使用できるディレクティブは `ticks, encoding, strict_types`の3つ。

https://www.php.net/manual/ja/control-structures.declare.php

### strict_types=1
PHPの暗黙の型変換を禁止して、型指定に厳密にチェックする設定のこと。

PHPのデフォルトでは自動変換モード（詳しくは後述）になっているが、 `declare(strict_types=1);` をファイル先頭に書くことでそのファイルはstrictモードに設定することができる。
> スカラー [型宣言](https://www.php.net/manual/ja/language.types.declarations.php) には二つの方式があります。デフォルトの自動変換 (coercive) モードと、 厳密に判断する strict モードです。
> 

https://www.php.net/manual/ja/migration70.new-features.php

> strict モードを有効にするには、[declare](https://www.php.net/manual/ja/control-structures.declare.php) 文を `strict_types` 宣言と一緒に使います。
    
>strict モードでは、型宣言に正確に対応する値のみを受け入れ、 そうでない場合、[TypeError](https://www.php.net/manual/ja/class.typeerror.php) がスローされます。 このルールに関する唯一の例外は、int の値が float 型の宣言に渡せることだけです。

https://www.php.net/manual/ja/language.types.declarations.php#:~:text=%E5%88%A9%E7%94%A8%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82-,%E5%8E%B3%E5%AF%86%E3%81%AA%E5%9E%8B%E4%BB%98%E3%81%91,-%C2%B6
    

## coerciveモードとstrictモードの違い

PHPのデフォルトでは、与えられた値の型を期待される型に自動的に変換する。(coercive モード)。

たとえば関数の引数に int が与えられたが、 引数には文字列が期待されていた場合、int を文字列型に変換した値を取得する。（戻り値も同様に、自動で型変換される。）

strictモードを有効にすると、与えられた型が期待する型と異なる場合TypeErrorになる。

↓　PHPのプレイグラウンドのようなサイトで書いたサンプルコードです。
何かコードを編集して、青い `eval();` というボタンを押すと実行できます。

https://3v4l.org/ZVG4j

**int と float の例**

```php
// declare(strict_types=1); が無い場合

<?php

function int(int $a){ return $a; }

function float(float $b) { return $b; }

print_r([int(2.5), float(2.5)]);

// 結果
Array
(
    [0] => 2
    [1] => 2.5
)
```

```php
// declare(strict_types=1); がある場合

<?php
declare(strict_types=1);

function int(int $a): int { return $a; }

function float(float $b): float { return $b; }

print_r([int(2.5), float(2.5)]);

// 結果
Fatal error: Uncaught TypeError: int(): Argument #1 ($a) must be of type int, float given, called in /in/42G2d on line 10 and defined in /in/42G2d:6
```

## 注意点

- 適用したいPHPファイルごとの先頭にセットする必要があり、php.iniに記載したりしてまとめて適用することは出来ない。
- `<?php` の直後に書かなければいけない。（ファイルの途中に記述不可）
- declare(strict_types=1); の影響範囲はそのファイルで完結している。
    - 関数を定義するファイルと関数を呼び出すファイルが異なる場合は、定義するファイルがstrictモードであるかは動作に影響がなく、関数を実行するファイルがstrictモードかどうかで動作が決まる。
    - ファイルをrequireする際も、requireするファイル・requireされるファイルのstrictモードが相互に影響することはない。
- PHPの型宣言でユニオン型（int | float）を使えるのはPHP8から。もしPHP8以前のバージョンであれば、intでもfloatでも良い、もしくはnullも含めたいといった場合にstrictモードが足枷になることも。

## 参考記事

https://wonwon-eater.com/php_strict_types/

https://qiita.com/Hiraku/items/734f0666ab3d34c52efa#:~:text=%E3%81%A4%E3%81%BE%E3%82%8A%E3%80%81strict_types%E3%81%A8%E3%81%AF%E4%BB%A5%E4%B8%8B%E3%81%AE%E3%82%88%E3%81%86%E3%81%AA%E6%8C%99%E5%8B%95%E3%81%AA%E3%81%AE%E3%81%A7%E3%81%99%E3%80%82
JavaScriptでjsonの中身を確認したら[object Object]と表示された場合の対処法

## はじめに
最近、API開発をしていて外部API時のエラーオブジェクトの構造を知りたい時がありました。
しかし、対象オブジェクトをログ出力しても[object Object]と表示されてしまいます。
そこで、オブジェクトの中身を表示する方法を調べたので紹介します。

## 方法1 : JSON.stringifyを使う
以下のようにJSON.stringifyを使う方法です。

```
console.log(JSON.stringify(object))
```

他の記事でもよく見かけます。
確かにこれでオブジェクトの中身が表示されるのですが、正直みづらいです。
そこで、次の方法が個人的におすすめです。


## 方法2 : console.dirを使う
以下のようにオブジェクトをconsole.dirで出力すると、良い感じに見やすく表示されます。

```
console.dir(object)
```
AWS EC2インスタンスの終了保護設定について

今回は、AWS EC2インスタンスの終了保護設定についてご紹介していきます！

##初めに
本来、インスタンスを停止する際には、下記画像の「インスタンスを停止」から行うのですが、似たような表現で「インスタンスを終了」というボタンも存在します。

万が一、「インスタンスを終了」を押してしまった場合、`インスタンスのデータが全て削除されてしまいます！`
せっかくデプロイしたアプリが、ちょっとした誤操作により消えてしまわないよう`終了保護の設定`をしておきましょう！

![スクリーンショット 2021-12-24 22.22.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601015/8e4b4efc-3de2-0b52-625a-2e64e8fbb2ae.png)

##終了保護の設定

1.該当インスタンスにチェックを入れ、「アクション」から「終了保護を変更」をクリック。

![スクリーンショット 2021-12-24 22.17.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601015/67d9c0f9-149e-d199-102f-ac945753cdda.png)

2.「有効化」にチェックを入れて保存。
デフォルトだと「有効化」にチェックが入っていないので、終了保護が無効化になっている状態です。

![スクリーンショット 2021-12-24 22.18.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601015/a560e40e-a5d8-7197-87b5-54250f208902.png)

3.設定完了確認
画面上部に「終了保護が有効化されました。」とメッセージが表示されれば設定完了です！
これで「インスタンスを終了」をクリックしてもインスタンスの削除に失敗するようになります！

![スクリーンショット 2021-12-24 22.19.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601015/d7954c2b-0caf-efa4-ba7f-f339be641dee.png)
政府統計e-Stat APIを使ってデータ分析しましょう

## はじめに
自分は人事給与ERP製品を開発する会社で、統計帳票の開発を担当しまいます。
統計帳票というのは、毎月勤労統計表や賃金台帳、公務員調査表など、全国調査にあってはその全国的変動を毎月、毎年明らかにすることを、地方調査にあってはその都道府県別の変動を毎月、毎年明らかにすることを目的とした調査です。
日々大量なデータを見る私は、これらのデータを分析することで、社員の退職や昇給などの原因がわかるではないかを気づきました。

ビッグデータ活用が近年話題になり、国や民間企業等が提供している主要な統計データを分析し、提供しているWebサービスもあります。
https://dashboard.e-stat.go.jp/
ただ、分析した内容と画像がややシンプルであり、データをもっと深堀りできるではないかを考えています。
もし、これらのデータを手には入れたら。。。と思いつつ、e-State APIがあることに気づきました。

e-State APIというのは、政府統計の総合窓口(e-Stat)で提供している統計データを機械判読可能な形式で取得できるAPI機能です。今回e-StateのAPIを使って簡単なデータ分析をやってみます。
https://www.e-stat.go.jp/api/
## e-stateのAPIの使い方
基本以下の流れです。
**アプリケーションID取得→統計対象データの選択とAPIクエリー取得**
####  アプリケーションID取得
API経由でデータを取得する際に、アプリケーションIDというパラメータを指定しないとデータが取得できません。ですのでユーザー登録して、マイページで発行ボタンをクリックすると、アプリケーションIDを取得します。
https://www.e-stat.go.jp/mypage/user/preregister

アプリケーションIDは以下のようなハッシュコードです。
```"appId" : "6tt320sfjagagiadkghijgjngdkgoda"```
####  統計対象データの選択とAPIクエリー取得
指定した統計表ID又はデータセットIDに対応する統計データ（数値データ）を取得します。
e-State APIから提供できるデータは以下のようになります。国勢調査や人口推計、家計調査などいろいろあります！
https://www.e-stat.go.jp/stat-search/database?page=1&layout=normal
![統計できるデータ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188697/cc273d7f-3750-d3e5-291e-98ca455e8861.png)
統計したい調査を開いて、**API**ボタンをクリックします。
![api.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188697/c4ee13ff-1816-e1e7-df72-b926c00e4944.png)
**API**ボタンをクリックすると、データ取得の時に使われるAPIリクエストのURLが表示されます。
クエリーは三つの形式があり、今回JSON形式でデータを取得します。
![url.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188697/c05c0aca-6ff7-91fb-4b04-fa0ac6829a20.png)
####  JSONを解析
Pythonの```requests.get(url, params)```でデータを取得します。
```url```はAPIクエリーの一番左側から```?```までのurlです。
```params```に、ユーザー登録時にもらったアプリケーションIDとAPIクエリーに書いた```statsDataId```を記入します。
```statsDataId```は統計表IDです、異なる統計表のIDは違います。
![dataget.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188697/399031d2-f854-c7e7-ee05-ab498fe7b23a.png)
今回JSON形式のクエリーをもらいましたので、```json.loads()```でデータを取得します。
簡単ですね！！
####  numpyでデータを分析する
今回の毎月勤労統計表のデータは8個統計項目がありますので、それぞれ取得して2年度の平均値をnumpyで計算します。
![numpy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188697/73b8caf1-df4e-3433-3c79-15a3d5e93f8a.png)
####  matplotlibで可視化する
![lib1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188697/0dc53f03-cd1c-a2b8-1e1a-c8df8f5bbe9f.png)
![lib2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188697/2ed8f735-6909-81a7-5515-ecc68bf4f514.png)

![img0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188697/e73fad63-8ae0-bb60-81e2-d3f6d66c0e4f.png)
![img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188697/8d40dd32-d276-e74d-aea4-b1635a23e251.png)
## 最後に
ふたんデータ分析をしたく、データがない場合、e-State APIを活用すれば、いろいろなデータ分析ができ、楽しいですね。
No such module ‘RealmSwift’が出た時にまずやること

#対象
ビルドしてもクリーンしてもxcode再起動してもエラーが消えない。
RealmSwfitをCocoapodsから入れている。
シミュレータでビルドしている。

#解決方法
すでにQiitaに上がっているのは下記の参考URLに書いてあるので、今回自分が見つけた手順を書きます。

**シミュレータのバージョンを`ios13`に変更し、ビルドする。**
（Excluded Architectureには何も設定しない。`ios14`以降は`arm64`を記述しないとビルドできないことがあるが、13の場合はなくてもビルドできるため）

これだけでビルドが通ります。あとは任意のosに変更しても問題なくビルドが成功するはずです。

#上記で解決しなければこちら
https://qiita.com/gentuki/items/a90a4a793a24612355d5
https://qiita.com/m-h5510/items/72f2b5eb8fdb4b2d81a6
PdMとして誰よりも考えるということ

## 「狂人PM」について
詳細は以下の記事を参照頂ければと思う。  

https://note.com/specialoffer/n/n550399bb341a

今回は、この記事を見て改めて考えたこと・思い出したことについてつらつらと述べていく。  

（本記事は[プロダクトづくりのための挑戦とその成功・失敗談を綴るアドベントカレンダー powered by プロダクト筋トレ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/product-kintore-challenge)の18日目です。前日の記事は↑の「狂人PM最強説について」です。）

## 「100倍考える」ということ
```
一方、それらは、相手から行動を引き出すためのコミュニケーションとしてのあるべき姿であって、考えていることとコミュニケーションは違うよね、という面もある。

ＰＭは、プロダクトの作り手、創造主、アーティストなのだから、当然人より100倍考えてないといけないよね、という話だ。
その100倍部分には常人には理解しがたい感覚や聞きなれない話が含まれているだろう。それをクロック下げずに話そうものなら狂人に映るだろうと。
```

私の上司にあたるPMも「俺がアイデアを話す時は脳内で100個以上のアイデアをシミュレーションして、生き残ったものだけを厳選している」とよく言っている。正直、本当に100個もシミュレーションしているのだろうかとか疑問に思い、あまりピンと来ていなかった。

しかし上記の記事を見て、私はようやく、上司の言っていることがわかった気がした。

## プロとは何か・狂人とは何か
私は下手ではあるが麻雀が好きである。今はABEMA TVでMリーグという麻雀のリーグ戦が行われているのだが、そこで最強とされるプレーヤーの一人に多井隆晴という人物がいる。  

https://www.youtube.com/channel/UCihYMokYrglpPKgjzbZYgqA

彼はYoutubeで麻雀の理論を語っているのだが、とにかく全ての一打や選択に対して一家言を持っている。常人なら「ここではこの牌を切って終わりだよね」と考える局面でも彼は「いやここでこれを切ることによって後々こういう展開になることもある」「そもそもこの局面に対する見方は10個くらいある」と言った具合に、対戦相手の一挙一投足も含めた全ての事柄を注視し、膨大な数のシミュレーションを行っている。おそらく麻雀に限らず、将棋でも囲碁でも同じようなことは言えると思う。一般人からしたらどうでも良いような一手でも、極限まで研ぎ澄まされた思考や膨大な量の検証を行うのがプロというものなのだろう。

しかし傍から見ている分にはその思考量は伝わらない。どんなに考えていようと満貫は満貫でしかないし、最終的には戦績でしか評価されない。そこに彼は常に忸怩たる思いを抱えているように見える。彼自身はとてつもなく強いためあまりそういうことはないのだが、同じように深く考えている他のプレイヤーが負けて批判されると、「お前ら何も知らないくせに」と吠えるシーンをよく見る。これは運の要素が特に強い麻雀だからこそ起きる現象だと考える。

麻雀に限らず、プロダクトでも同じようなことはままある気がする。優れたエンジニアはコードの一行一行、変数の一つ一つにとてつもない拘りを持つ。デザイナーであればパッと見では区別がつかないような色遣いの違いに延々と頭を悩ませる。優れたPMはバックログの何気ない表現、エンジニアやデザイナーの発する言葉、プロダクトのWeb広告のほんの僅かな違いにも敏感に反応し、口をはさむ。しかしどれもコードは所詮コード、カラーコードは所詮カラーコード、バックログは所詮バックログである。極限までこだわったところで、その発露は外部からは殆ど見られない。

「俺がアイデアを話す時は脳内で100個以上のアイデアをシミュレーションして、生き残ったものだけを厳選している」というのは、今の私の解釈によれば、「脳みそが壊れるほど考えても1/3も伝わらない」ということになる。確かに私自身も2年以上PMをやるなかで、LPサイトの作り方、ワイヤーの書き方、事業責任者とのコミュニケーション、ユーザーインタビューの一言一句に対して多分鬱陶しいと思われる程度にはこだわりを持つようになってきた。狂人の領域というのは、多分そうした拘りや信念の膨大な積み重ねを経てたどり着けるものなのだろう。

https://www.youtube.com/watch?v=0tWbScMyBLM

## 希望
この事実は私にとってはある種の希望である。つまり上司が何言っているのか分からないという時、これまでの私は「自分には永遠にその領域へたどり着けない」と考えてきたが、拘りが膨大にありすぎて言葉として表現しきれていないのだろうと考えるようになった。つまり常人でもたどり着ける可能性があるということだ。
膨大な量なので、いつその境地にたどり着けるかの具体的な年数がわかったわけではないが、もしかすると、うまくやれば、いつかその境地にたどり着けるのかもしれないという希望が見えた。

このアドベントカレンダーを企画してなければ、そういったことに気づかず2021年を終えていた可能性が高い。
正直面倒ではあったが、これを企画してよかったと思った。
最近の中途エンジニア採用手法について

# はじめに

私は3年前にこちらの記事を書きました。3年前と比較して現在の中途エンジニア採用は、大枠は変わっていないと思っていますが、新たな採用手法が出てきていますので、アップデートという意味で、この記事ではまとめたいと思います。

採用広報も3年前から随分進化してきますが、採用広報についてはこちらの記事では扱いませんのでご了承ください。

https://qiita.com/kenji_sakai/items/a01adb2deca269b4e37f

※前回投稿時とアカウントが変わっているのは、前回投稿時は前職のアカウントを使用していたからです。


# 新しい採用手法が出てきた背景

こちらの記事にも書いてありますが、エンジニア 技術系（IT・通信） の求人倍率は依然として、全職種中トップです。新型コロナウイルス感染症拡大の影響を受けて、2020年には下がりましたが、また増加傾向にあります。エンジニア採用担当にとっては苦しい状況が続いています。

https://doda.jp/guide/kyujin_bairitsu/

今までと同じ採用手法ではなかなかエンジニアが採用できない、転職サービスを提供している企業も、今までと同じサービスでは差別化ができないため、新しい採用手法が出てきました。

# 新しい採用手法

下記の4つが最近出たきた新しい採用手法になります。
どれもエンジニアと出会うハードルを何らかの方法で下げるサービスになっています。

* まずは副業からの正社員化
* 本当にカジュアルな面談
* お金を払って面談
* キャリアSNS

# まずは副業からの正社員化

正社員ではなく、副業として会社にジョインしてもらって、副業として働く中で、会社のことを好きになってもらって、正社員として採用する方法です。

まずは副業からスタートにして正社員よりもハードルを下げることができる反面、副業として社員を迎え入れられる環境の整備が必要だったり、副業するだけで終わってしまっては意味がないので、副業で働いてくれる社員が正社員になってくれるように配属チームと協力して組織的に動いていく必要があります。

https://offers.jp/

# 本当にカジュアルな面談

転職のことを抜きにして、ただ本当にカジュアルな面談して接点をつくって、そこから採用につなげていく方法です。
すでに多くの会社が利用しているので、その中でも面談に来てもらえるように魅力的なコンテンツをつくること、面談に来てもらった後、どう採用につなげていくのか工夫が必要です。

https://meety.net/

# お金を払って面談

企業側からお金を払ってエンジニアに面談してもらう方法です。1面談で3万円なので、最終的に採用まで行き着けばペイします。ただ、エンジニア側が面談する一つのモチベーションはもちろんお金になるので、こちらも面談に来てもらった後、どう採用につなげていくのか工夫が必要です。

https://pay-career.com/

# キャリアSNS

LinkedInは以前からありましたが、日本のキャリアSNSができました。
知り合いの知り合いからのスカウトなのでエンジニア側からすると受け入れやすく返信率が高いという特徴があります。ただ、自社のエンジニアの協力が不可欠になるので、社内のエンジニアをいかに採用に巻き込んでいくか工夫が必要です。

https://youtrust.jp/

# 最後に

どれもエンジニアと出会うハードルを何らかの方法で下げるサービスですが、ハードルをさげた分そこから採用につなげるには工夫が必要になりますね。

それではメリークリスマス。
クリスマスプレゼントには…エンジニアの仲間がほしいですね。
AWSの各種サービスまとめ

AWSは提供しているサービスが多く、それぞれのサービスが何をしてくれるものなのか分からなくなることが多いので、簡単にリスト化してメモしておきたいと思います。

#仮想サーバ
* Amazon EC2：仮想サーバ（OS、CPUスペック、メモリスペックなどを自由に選択できる)
* Amazon Lightsail：Webサーバを構築する際に利用できる仮想サーバパッケージ

#データベース、ストレージサーバ
* Amazon RDS：MySQL、　PostgreSQL、OracleDBなどを選択してデータベースサーバを構築できる
* Amazon Aurola：MySQL、PostgreSQLと互換性がありつつも性能を向上させたデータベース
* Amazon S3：データストレージ、大容量ファイルなどを置いておくことができる

#機械学習
* Amazon SageMaker：機械学習用環境を構築するための仮想サーバパッケージ
* Amazon Comprehend：機械学習の知識がなくても使えるテキスト分析サービス

#バージョン管理
* AWS CodeCommit：GitHubのようなリボジトリサービス

#その他
* Amazon QuickSight：クラウドベースでBIを構築できる
Azureで参考になるブログまとめ



## ブチザッキ

国内のAzure系のブログではかなり著名なブログ。

https://blog.azure.moe/2021/12/23/azure-updates-2021-12-23/#more-35113

## Ohina Work

Azureの資格試験対策や、Azureで発生した課題などの記事をまとめたブログ

https://ohina.work/tags/azure/

https://zenn.dev/ohina/books/a094e5e8177aa0e48407

https://zenn.dev/ohina/books/a094e5e8177aa0e48408

##　くらう道

日本マイクロソフトの方のブログ。

https://www.cloudou.net

## しばやん雑記

Azure Functionsや、Web Apps系の記事が充実しているブログ。

https://blog.shibayan.jp

## クラウドおじさんの備忘録

https://blog.kokoni.jp

## Always on the clock

MS認定トレーナーのブログ。

http://azuread.net
NetBSDカーネルモジュールの依存関係を考慮しながらモジュールをアンロードしてみる

[NetBSD Advent Calendar 2021](https://qiita.com/advent-calendar/2021/netbsd) 11日目の記事です。今日は[10日目の記事](https://qiita.com/furandon_pig/items/a809ed817ab38ac9d046)で紹介した、カーネルモジュールの依存関係可視化の結果を応用して、不要なカーネルモジュールの除去手順を紹介しようと思います。

## compatモジュール

カーネルモジュールの依存関係を眺めていると、 `compat_*` という名称のモジュールが存在していることが分かります。どうやらNetBSDのシステムコールについて、後方互換性を持たせるための機能のようです。

![nbsd1211_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61137/a9785e3a-1698-a6be-2487-866ee19d38b4.png)

この `compat_*` モジュールを例に、依存関係にあるモジュールの除去を試してみます。

## カーネルモジュールの除去

カーネルモジュールの依存図を参照しながら `modunload` コマンドでモジュールを除去してみます。
例として、 `compat_netbsd32_16` と `compat_16` を除去してみます。

```sh
# modstat | egrep 'NAME|compat_16|compat_netbsd32_16'
NAME                       CLASS    SOURCE   FLAG  REFS    SIZE REQUIRES
compat_16                  exec     builtin  -        1       - compat_20
compat_netbsd32_16         exec     builtin  -        0       - compat_netbsd32_20,compat_16
```

依存図から `compat_16` は `compat_netbsd32_20` に必要とされている(依存している)ことが分かります。 `modstat` コマンドの出力においても、 `compat_netbsd32_16` のREQURESに `compat_16` が表示されていることと、 `compat_16` のREFSが `1` になっており、別のモジュールから参照されていることが分かります。

ここで、試しに `compat_16` をアンロードしてみます。 `compat_netbsd32_16` に必要とされていることから、アンロード処理はエラーとなります。

```sh
# modunload compat_16 ; echo $?
modunload: compat_16: Device busy
1
```

次に `compat_netbsd32_16` → `compat_16` の順番でアンロードしてみます。

```sh
# modunload compat_netbsd32_16 ; echo $?
0
# modunload compat_16 ; echo $?
0
```

今度は無事にアンロードできました。ただし、 `modstat` で確認してみるとカーネルに組み込まれた"builtin"なモジュールはメモリから解放されるのではなく、単に参照されなくなる( `REFS` が `-1` になる)だけのようです。そのため、本当に不要なモジュールを読み込ませたくない場合はカーネルコンフィグ側で設定することになりそうです。

```sh
# modstat | egrep 'NAME|compat_16|compat_netbsd32_16'
NAME                       CLASS    SOURCE   FLAG  REFS    SIZE REQUIRES
compat_16                  exec     builtin  -       -1       - compat_20
compat_netbsd32_16         exec     builtin  -       -1       - compat_netbsd32_20,compat_16
```

## まとめ

カーネルモジュールの依存図をもとに不要なモジュールの削除を試してみました。ただし、カーネルに組み込まれているモジュールについては単に参照されなくなるだけであり、モジュール自体を読み込ませないようにするにはカーネルコンフィグ側で設定を行ったのち、カスタムカーネルを作成する必要があるようです。
「コミットメッセージ」をわかりやすく書く方法

## はじめに
フロントエンドエンジニアをしているズッキーです。
アルバイトを含めるとXHTMLの流行りが終わり始めたぐらいの時代から、フロントエンドエンジニアを経験してます。

さて昔と比べると
昨今のクライアント側のマシンスペックの向上や、
ブラウザ機能の発展に伴い、
「フロントエンドに対する、要件や要求」
が年々上がってきているなぁと感じております。
（とても良いこと）

伴い、**複数人でフロントエンドを開発するシーンが増えてきました。**

最近はフロントエンドエンジニアチームの組織化を色々頑張っているのですが、その中の取り組みの一つである、コミットメッセージの最適化をご紹介させてくださいませ！

## 良いコミットメッセージとは
個人的な見解ですが、
**なぜ（why）、どこ（where）の何（what）**を修正したのかが、
ぱっと読み取れるメッセージだと思ってます。

【良くない例】
「バグ修正」
これだと何を修正したのか、第3者がソースコードを見ないとわからない。。👴

【良い例】
「XXXのXXXフィールドの値がない場合に意図しない空白ができるバグを修正」
なぜ（why）、どこ（where）の何（what）が入っていてわかりやすい！☺️

## 規約にのっとろう
ということで、チームでの開発となると、ルールが必要になりますが、ここでは「Conventional Commits」を紹介します。

### Conventional Commits

:::note info
明示的なコミット履歴を作成するための簡単なルールです。
:::

【公式ドキュメント】
https://www.conventionalcommits.org/ja/v1.0.0/
※ GitHubのStarは3.6kある（2021年12月24日時点）

### 概要
下記が公式で紹介されているフォーマットです。
どういう事かわからないと思いますが、詳細は後述するのでまずは共有まで。

【フォーマット】
> <型> [任意 スコープ] : <タイトル>
> [任意 本文]
> [任意 フッター]


【適用した例】

```
feat(トップページ): XXXのXXXフィールドの値がない場合に意図しない空白ができるバグを修正

XXXフィールド配列が空で返却された場合に、「〜はございません」のテキストを表示するように修正

Refs: #111
```

### 使い方
例を元に、下記の順番で説明します！

1. 型を指定する
2. 任意でスコープを設定する
3. タイトルを記載する
4. 任意で本文を記載する
5. 任意でフッターを記載する

**1. 型を指定する**
「どういった作業を行ったのか」を型として指定します。

例でいうと`feat`の箇所になります。
下記がよく利用される型の認識です。

| 型 | 意味 |
|:-----------|:------------|
| feat     | 新しい機能を追加したときに指定 |
| fix       | バグの修正        |
| BREAKING CHANGE       | 破壊的な変更 |
| docs       | ドキュメントのみの変更 |
| style       | フォーマットの変更（コードの動作に影響しないスペース、フォーマット、セミコロンなど）  |
| perf   | パフォーマンスの改善のための変更 |
| refactor   | リファクタリングのための変更（機能追加やバグ修正を含まない） |
| test | 不足テストの追加や既存テストの修正 | 

**2. 任意でスコープを設定する**
対象ページや対象コンポーネントなどのスコープを任意で指定します。

例でいうと、`(トップページ)`の箇所になります。

**3. タイトルを記載する**
コミット内容の概要を簡潔に指定します。
このときに、「なぜ（why）、どこ（where）の何（what）」を意識して書くと良いと思います。

例でいうと`XXXのXXXフィールドの値がない場合に意図しない空白ができるバグを修正`の箇所になります。

**4. 任意で本文を記載する**
コミット内容の詳細を説明します。

例でいうと`XXXフィールド配列が空で返却された場合に、「〜はございません」のテキストを表示するように修正`の箇所になります。

**5. 任意でフッターを記載する**
課題番号（Refs）やレビュワー等（Reviewed-by）を指定します。

例でいうと`Refs: #111`の箇所となります。


## 対話形式でコミットメッセージが作れるライブラリ
ここでは深く説明しませんが、このようなツールをチームで使う事で、チーム内でのコミットメッセージの統一や、規格を守ってもらうための一助となります。
https://github.com/commitizen/cz-cli

## 最後に
フロントエンドが複雑になってきているが、頼もしい仲間と共同で作業できる時間はすごく楽しいです。
これからも力を合わせて、頑張れるように色々な施策を考えて実行できればと思ってます。

読了いただき誠にありがとうございました！
Developer eXperienceの向上に貢献できていれば、
嬉しく思います。

## 参考記事
https://dev.classmethod.jp/articles/commitizen/
multipassで仮想マシン作ったら名前をつけると便利

手軽に仮想マシンが作れるmultipassが便利で重宝しています。

- [M1 Macでmultipassを使ってUbuntuを実行](https://zenn.dev/kujirahand/articles/7cf343b6dbea18)
- [Macでmultipassを使ってUbuntu Desktopを使う](https://zenn.dev/kujirahand/articles/f70183a6f19879)
- [MultipassをM1 Macで使う備忘録](https://zenn.dev/kujirahand/articles/57c367702ed1f2)

multipassでは、`multipass ls`コマンドを実行すると、現在実行している仮想マシンの一覧を見ることができます。そして、その際に仮想マシンに割り当てられているIPアドレスも確認できます。

```
% multipass ls
Name                    State             IPv4             Image
hogehoge                 Running           192.168.64.10    Ubuntu 20.04 LTS
fugafauga                Stopped           --               Ubuntu 20.04 LTS
docker                   Stopped           --               Ubuntu 20.04 LTS
```

それで、よく使う仮想マシンは、IPアドレスも覚えてしまっても良いのですが、何かしらの原因でその仮想マシンを壊して、新規で別の仮想マシン作って、そのマシンに役割を引き継がせたい場合もありますよね。その場合、IPアドレスを直で指定していると不便です。そこで、IPアドレスに別名をつけて管理しています。

例えば、自分のマシン内でメモ帳代わりにしているWIKIとか、いろいろなWebアプリとか・・・機能ごとに適当なローカルドメインをつけて使っています。

# /etc/hostsファイルに別名を記述する

それで、仮想マシンに割り振られているIPアドレスに名前をつける方法ですが、`/etc/hosts`ファイルに名前を記述します。ターミナルで`sudo nano /etc/hosts`などのコマンドを実行して、ファイルを編集しましょう。sudoが必須です。

```/etc/hosts
##
127.0.0.1	localhost
255.255.255.255	broadcasthost
::1             localhost

# Multipassの仮想マシンに名前をつける
192.168.64.10   wiki.example.com
192.168.64.11   keiri.example.com
192.168.64.12   hoge.example.com
```

上記のように、`IPアドレス   名前`のように書いておくだけで、ブラウザなどで`wiki.example.com`にアクセスすることで、仮想マシンにアクセスできます。（もちろん、仮想マシンでWebサーバーなど起動しておく必要ありますが。。。)

## ***.localの名前は使わない

ただし、`***.local`の名前は使わないようにします。以前は、`wiki.local`とか`keiri.local`などの適当な`***.local`という適当なアドレスをつけて使っていました。

しかし、これがもの凄く遅いんです。`***.local`のアドレスはAppleのBonjourサービスによって、外部に問い合わせをしてしまうようです。せっかくローカルPCに仮想マシン建てているので、.localアドレス以外の適当なアドレスに割り当てると良いでしょう。

# まとめ

機能ごとに覚えやすい名前をつけておくと、PCを乗り換えたり、仮想マシンの割当を変更した時にも便利です。
Nervesでファイルベースのデータベース「CubDB」を使ってみる


ある程度複雑な[Nerves]ファームウエアを作ると何らかのデータを保存したくなることがあると思います。
[Nerves]はファームウエアは意図しないデータの破壊を防ぐために基本的には読み取り専用になっているのですが、一箇所だけ[書き込める場所](https://qiita.com/torifukukaiou/items/9dd5cfa81109a2e0a5eb)があります。`/data`ディレクトリーです。

```elixir
iex> ls "/data"
.cache  .erlang.cookie  last_shutdown.txt  lost+found  vintage_net

iex> File.write!("/data/hello.txt", "こんにちは!\n")
:ok

iex> ls "/data/hello.txt"
/data/hello.txt

iex> cat "/data/hello.txt"
こんにちは!

iex> File.rm("/data/hello.txt")
:ok
```


`/data`ディレクトリーには自由にファイルを作って保存ができるのですが、頻繁にデータ保存をしたい場合にはデータベースが欲しくなります。

[Nerves]で使えるファイルベースのデータベースはいくつか挙げられます。

- [ecto_sqlite3]
- [dets]
- [cubdb]

個人的に特に気に入っているのが[cubdb]です。

## [cubdb]の特徴

- 100％[Elixir]で書かれている。
- 活発にメンテナンスされている。(2021年現在)
- [Nerves]コアチームも使っているらしい。（特に[Jon Jonさん](https://twitter.com/joncarstens)）
- [関数がシンプルでわかりやすい。](https://hexdocs.pm/cubdb/CubDB.html)
- データ汚染を防ぐ仕組みも実装されている。

## [IEx]で試運転

- `data_dir`に対して複数のプロセスを立ち上げるとプログラムがクラッシュするので、それを未然に防ぐためにプロセスに名前をつけておくのがコツです。

```elixir
# IExを起動
iex

# cubdbをインストール
Mix.install([:cubdb])

# データの保存先とプロセス名を指定してcubdbサーバーを起動
data_dir = Path.join(System.tmp_dir!(), "database")
{:ok, _db} = CubDB.start_link(data_dir: data_dir, name: :my_database)

CubDB.put(:my_database, :feeling, "awesome")
#=> :ok

CubDB.get(:my_database, :feeling)
#=> "awesome"

CubDB.delete(:my_database, :feeling)
#=> :ok

CubDB.get(:my_database, :feeling)
#=> nil
```

## [Nerves]ファームウエアに搭載

[cubdb]を依存関係リストに追加して、`mix deps.get`コマンドでインストール。

```elixir:mix.exs
  defp deps do
    [
      {:cubdb, "~> 1.1"},
    ]
```

アプリ起動時に[cubdb]サーバーを起動する。

```elixir:lib/hello_nerves/application.ex
defmodule HelloNerves.Application do
  @moduledoc false

  use Application

  def start(_type, _args) do
    opts = [strategy: :one_for_one, name: HelloNerves.Supervisor]

    children = [
      {CubDB, [
        # Nervesで書き込める場所`/data`配下の任意のディレクトリーを指定
        data_dir: "/data/database",
        # CubDBプロセスに名前をつける
        name: HelloNerves.Database]}
    ]

    Supervisor.start_link(children, opts)
  end
```

後は[IEx]での試運転同様に[Nerves]ファームウエアで自由に読み書きできます。

:tada::tada::tada:

# <u><b>Elixirコミュニティに初めて接する方は下記がオススメです</b></u>

**Elixirコミュニティ の歩き方 －国内オンライン編－**<br>
https://speakerdeck.com/elijo/elixirkomiyunitei-falsebu-kifang-guo-nei-onrainbian

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/f891b7ad-d2c4-3303-915b-f831069e28a4.png)](https://speakerdeck.com/elijo/elixirkomiyunitei-falsebu-kifang-guo-nei-onrainbian)

https://autoracex.connpass.com/

<!-- Links -->

[Elixir]: https://elixir-lang.org/
[Nerves]: https://www.nerves-project.org/
[ecto_sqlite3]: https://hex.pm/packages/ecto_sqlite3
[dets]: https://www.erlang.org/doc/man/dets.html
[cubdb]: https://hex.pm/packages/cubdb
[IEx]: https://hexdocs.pm/iex/IEx.html
新卒3年目のScM体験記

[mediba Advent Calendar 2021](https://qiita.com/advent-calendar/2021/mediba "mediba Advent Calendar 2021") の25日目を担当します、新卒3年目の川北 (@hiromasa-fun)です。
この記事は24日クリスマスイブに書いてます。イブ書き。

今回は、
ScM体験記ベースで、PJ特徴/あるあるなどをまとめてみました。
個人的観点なので鵜呑みにせず一意見として見てもらえればと。

# ScM経験
新卒3年目からScMの経験をさせてもらっていて、下記が3年目以降のプロダクトになります。
規模感も結構違いますので、( )でだいたいのスクラムメンバー数を書いてます。

* 4-10末
    * 自社開発運営PJ (10)
* 10末-Now!
    * 協業開発での受託PJ (30)

この2つは自社開発と受託開発の対極的な環境なので、それぞれでまとめようと思います。

**注意事項として言っておきますが、
現在壁にぶち当たっていることもあり現在Joinしている受託PJの方が悪い印象を受けるかもしれません、そこだけご了承下さい。(受託が悪いと言っているわけではない)**


# 自社開発運営PJ
私が、ScMとして初めて経験したプロダクトになります。
このプロジェクトは新卒2年目からバックエンドエンジニアとしてJoinしてたので、仕様や流れもある程度把握してたのもあり、結構入りやすかった印象です。

## 自由度が高い
PO,PMによるかもですが、自由度が高かったです。自社開発運用なので、ユーザに事前告知等していなければ**納期がありません。**
スプリントプランニング時点でスプリントバックログを確定させますが、デイリースクラムやリファインメント等でできないものは削ぎ落とせるので精神衛生上は楽なことが多いです。もちろんスプリント内に入れたものはできるだけ完了させることが一番ですっていうのは言っておきます。
また、スクラムメンバー内で何をするか、この時期は何に力を入れるか等を決めていくので、ある程度プロダクトコントロールができます。(ここは人数によるかな？)

## スクラムを組みやすい
「自由度が高い」でも言いましたが、納期がないので、納期までの最短スケジュールを引くようなガチガチ計画はやりません。
基本的にスクラムイベントに沿って周期的に開発・改善すること、アジャイル思考の中でPJに合うやり方をしているので、計画→実行ではなく、実行→改善→改善...という手法が納期がないと容易にできます。
なので、スプリント周期を基盤とし、その中でプロダクト価値・メンバー価値を高めることは比較的容易にできると思ってます。(PJ人数やプロダクト規模にもよります)

## ScMとしてチャレンジしやすい
自社開発運用であれば、**他社の柵もない**ので、やりたいように改善できますし、動きやすいと思ってます。
このときは、同じPJで1年間バックエンドエンジニアしたこともあり、その時に課題として思っていたことを具現化して提案したり、レトロスペクティブ時に出たものをグルーピングし多い順に議論して改善しようってなったり、初ScMなりにたくさんのチャレンジができたかなと思ってます。メンバー数にもよりますが他社が関わると、全員集まる時間が取れなかったり、他社メンバーの文化/風土に合うかどうかでなかなか決まらないことが多い印象です。
また、開発陣に関しても、**新規開発・技術の取り入れが比較的できる**と思います。受託だと新しい技術を取り入れるためにこのくらいの工数になります。なんて言ったら、それって売上に繋がるんですか。みたいなイチャモン付けてくる場合もあるので、難しかったりしますw


# 協業開発且つ受託PJ
現在Joinしているプロジェクトになります。
最初からScM/PMOというロールでJoinしたのもあり、プロダクトの理解やメンバー、どういう流れで進行しているのか、どんなPJルールがあるのか、みたいな部分はかなりInputするのに大変だった印象です。

## 制約が多い
**納期という制約**があります。受注元はお金を払っているので、あまり時間をかけたくありません。なので、無理な納期を言ってきたりします(全国共通)。なので、納期から逆算してリソースプランニング、スケジュール引いてウォータフォールみたいな形になりがちです。進むにあたってなにかスケジュール上問題があったら。。。と思うことがあるので精神的に強くなれます。
あと、**コミュニケーションコストがかなり高くなりやすい**です。私の場合は、協業開発且つ受託PJなので、制約上の問題から他社はAツール、受注元はBツール、みたいな事が起きちゃいます。なので、コミュニケーションするときは、AツールでもBツールでも共有・報告しないといけなくなってしまい、結果コミュニケーションコストが高くなってしまいます。報連相強者になれます。

## スクラム導入が難しい
**納期があるので、スクラムイベントそっちのけでウォータフォールのようにガチガチで進行することがあります。**そうなると、スクラムイベントって必要なのか、みたいな話が出てきてPJの仕組みを再整理することになってしまいます。うまいことスプリント周期に合わせてやることはできると思いますが、結構大変です。(受託PJでスクラム導入しているところでうまくいっている企業さんいればお話が聞きたい)

## ScMとして改善するするとしても動きづらい
ScMとして、メンバーのベロシティをあげることも1つの主務かと思います。ただ、メンバーの時間や他のタスクをやめて時間を割くのは、成果物が増えても時間を増やしただけで当たり前なので、ベロシティ向上には繋がりません。ですが！！！時間の使い方の見直しも1つの手段です。(もちろん定時内の話です)
じゃあどうするか。無駄な時間、MTGがないか、ルールはこれで良いのか、みたいなところを考えます。
ここで、他社も関わっていると、**他社の文化/風土なんかがあって、自社でのセオリーみたいなのが少なからず出てきます。そこを中和して改善するのが難しいポイントだと思ってます。**
あと**制約上動きづらかったりします**。「制約が多い」話でも出ましたが、コミュニケーションツールの統一化をしたくても制約上難しく、要求としての「コミュニケーションコストが少なくなる」手段をもう一度考えたりするので、制約...ってなります。

# まとめ
新卒3年目で、2つの対極的なPJにJoinしてみて、いろいろScMとして何ができるか/何をすべきなのかを考えることが多くなりました。
もちろん、**最終的な目的としてはScMが不必要になる環境作り (自己組織化)** があります。じゃあそのためにこのPJ内はどういうところが課題で、その課題がどこに紐付いていて、どうやって解決するかを考えることを1つずつやっています。
まだScM1年生にも満たないので、たくさんのInputとOutoutをしながら大きな壁を壊して行きたいと思います。
協業先や受注元の関わっているメンバーも一人ひとり自分と同じ人間なので、**ジブンゴト化を忘れず**に価値を生み出していきたいと思います。
これからもかんばるぞい！
RailsでDDDのバリューオブジェクトを実装してみる

## この記事は何
DDDを学んだ事がある方は「バリューオブジェクト」という名前を一度は聞いた事があるのではないでしょうか・
この記事ではRailsでバリューオブジェクトを実装するならどのような実装にすると良さそうかを紹介します。
なお、バリューオブジェクトの具体的な実装方針は千差万別だと思うので、この記事で紹介する実装はあくまで一例だと思っていただけるとありがたいです。

具体的なバリューオブジェクトの解説は↓の記事などが参考になると思います。

https://qiita.com/little_hand_s/items/f8c0d0858c895afed7e2

## バリューオブジェクトの条件
バリューオブジェクトは以下の条件を満たしている必要があります。
条件は以下の通りです。

- オブジェクトはイミュータブルである
    - 値の変化はインスタンスの再生成で実現する
- オブジェクトの同一生はバリューオブジェクトが持つattributeの一致で定義される

Railsで実装する際も、これらの条件を満たす必要があります。
そしてバリューオブジェクトとして実装する以上、バリデーションも行えるようにしたいです。
これらの要件を満たすインターフェースを実装してみます。

## 実装物

実装物はズバリ↓のようなクラスです。

```rb
class Value::Base
  include ActiveModel::Model

  def initialize
    fail ActiveRecord::RecordInvalid unless valid?
  end

  # @param other [::Value::Base]
  # @return [true, false]
  def ==(other)
    evaluate_attributes.all? { |variable| try(variable) == other.try(variable) }
  end

  private

  # @return [Array<String>] attributes used to equal evaluation
  def evaluate_attributes
    fail NotImplementedError
  end
end

```

このクラスは以下のように継承し、利用します。

```rb
class Value::Name < Value::Base
  attr_reader :first_name, :last_name

  validates :first_name, presence: true
  validates :last_name, presence: true

  def initialize(first_name:, last_name:)
    @first_name = first_name
    @last_name = last_name
    super()
  end

  def full_name
    "#{first_name} #{last_name}"
  end

  private

  # @note Override {::Value::Base#evaluate_attributes}
  def evaluate_attributes
    %i(first_name last_name)
  end
end
```

このクラスの機能について説明します。

### オブジェクトの不変性
このクラスでは、基本的にsetterを提供せずに、getterのみを公開します。
こうすることで、外部からインスタンスの変更を行うことはできません。


### オブジェクトの同一性
このクラスには`evaluate_attributes`というメソッドを実装しています。
また、`==`メソッドをオーバーライドし、各attributesの値の同一性を検証することでオブジェクト自体の同一性を判定するようにしています。
このようにすることで、`==`メソッドを用いた同一性検証はバリューオブジェクトが満たすべき条件と同じになります。

### 値のバリデーション
このクラスでは`ActiveModel::Model`モジュールを`include`しています。
また、`initialize`のタイミングで`valid?`が`false`を返すときにエラーを返すようになっています。
このように実装をし、子クラスで最後に`super()`を実行することで、インスタンス生成時に検証まで行えるようになっています。
関数の可変長引数


#タプルの可変長引数

```python:tuple.py
def tupleArgument(*arg):

tupleArgument('value1','value2','value3')
```
*ひとつでタプルの可変長引数であることを示す

#ディクショナリの可変長引数

```Python:dictionary.py
def dictionaryArgument(**kwargs)

dictionaryArgument(key1='value1',key2='value2',key3='value3')
```
*ふたつでディクショナリの可変長引数であることを示す
商社マンからエンジニアになってみて

# 前職の内容
- 前職は総合商社の海外営業を約6年担当していました。会社や資源権益のM&Aを担当したり、新規事業の立ち上げを担当していたりました。
- その後、2020年にポテパンに通い、エンジニアとして転職。現在SaaSの会社でRails、Reactを中心としたフルスタックエンジニアをやっています。

#エンジニアになろうと思ったきっかけ
- 商社に勤めていた最後の年に、海外でECサイトをゼロから立ち上げる担当になりました。現場責任者のような形で、ECサイトのレイアウト・コンテンツの設計、商品の仕入れ、在庫管理、PL&BSの管理など、事業全体を包括的に管理しつつ、サービスを立ち上げていく非常にチャレンジングな仕事を任せて頂きました。
- すごくやりがいのある仕事で充実していました。ただ、大企業の新規事業なので、システム会社やコンサルに発注をしながら、自分は取りまとめや関係者間のコミュニケーションを取り持つことが多く、**「これは本当に自分の力で事業を立ち上げているのだろうか」**という疑問を抱くようになりました。
- つまり、自分でサービスを作っている感覚よりも、多額の予算を使って、「スペシャリストの人たちにサービスを作ってもらっている」感覚の方が強く、その経験から、**「もっと自分の力で世の中に対して価値を与える仕事がしたい」**と思うようになりました。かなり自由にやらせて頂いていたので、さらにやりがいを感じる仕事をするためには、サラリーマンだと限界があると思い、起業を志すようになりました。
- 起業といっても色々あると思うのですが、私はWebプロダクトを自分で開発して、それをスケールさせることをやりたいと思っているので、エンジニアとして働きながら、並行してサービス開発をして起業する選択肢を選びました。それが長期的にみると再現性が高そうで、自分なりにしっくりきた道だったからです。
- 商社の経験から、**「自分がまったくわからないことを誰かに任せて、やってもらうだけだと、競争力のあるビジネスは作れない」**というのが私の持論です。Webプロダクトをスケールさせることがやりたいことなら、自分自身に開発ノウハウがないと、本当に価値あるものを作ることはできないと思っています。そのため、エンジニアにジョブチェンジしたことが、自分の将来の成功に繋がっていると自分では信じています。

#エンジニアとして働いてみた感想
- そこまで違和感は感じていないのですが、やはり慣れていない仕事をやっているので、サクサクできるようになるまでは時間がかかる、とは思います。ただ、商社のときも最初は全く仕事がうまくいかなかったですし、四苦八苦してる時の方が人間成長しているものなので、心地よいキツさを日々感じています。
- エンジニアは**「アウトプットをちゃんとだせば、自分のリソースを組織にフルコミットする必要がない」**という点で、日本の大企業の文系総合職とは異なるかと思います。文系総合職だと「組織に対してどれほど自分がコミットしているか」という点がどうしても評価の基準になりがちなので、エンジニアの方が圧倒的に自分の時間を確保しやすいです。スキルがあるので、副業とかも簡単にできますね。
- また、起業に向けたプロダクト開発も、誰かにお願いしたらお金がかかりますが、自分でできます。これがエンジニアになった一番のメリットです。自分で考えながら、自分の作りたいものを作れるので、小回りが効くというか、極めてアジャイルに開発できます。

#今後はどんなエンジニアを目指したいか
- エンジニアとしてなるべく自分のスキルを伸ばしていきたいです。10年、20年のキャリアがあるエンジニアの方と一緒に仕事をしたりすると、自分がまだまだ本当に未熟であることを痛感します。ただ、そういった方々と競い合って勝ちたいとはあまり思っておらず、ビジネスサイドの経験も生かしてうまくポジショニングしていければと思っています。
- また、私と同じような価値観を持っている方々とつながっていきたいです。そして同じ志を持つ仲間と一緒にプロダクト開発をやっていきたいですね。
VRChatプレイヤーによるParticle System解説 ～Triggers, Sub Emitters Module編～

:::note warn
この記事はUnity 2019.4.29f1の記事です
:::
[External Forces, Noise Module編](https://qiita.com/abcde_kind/items/f9702c960b3d25db7d35) <<  ここ  >> [Texture Sheet Animation Module編](https://qiita.com/abcde_kind/items/8676b0066c2b37a616e7)
# はじめに
この記事は**ちょっとParticle System触れるようになったけどまだまだ知らないパラメーターだらけで抵抗感がある人向け**にじゃあ全項目解説しようという記事です。

**パーティクル？シェーダー？憧れるけどよくわかんない…**という人は最近は[VRCUnity勉強会][link-1]などで初歩の初歩から解説してくれる講座などが解説されているのでそこに参加してみたりするといいでしょう。
[link-1]:https://discord.gg/mtvTTyM
その他にこの記事はアドベントカレンダーにしてParticle Systemの記事を増やしてパーティクルへの抵抗感を減らしてやろうという企みもあります。

##Triggers, Sub Emitters Moduleってどこ？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2386883/71ea2133-2662-d01b-3610-4e3222f0060f.png)
こここ
##Triggers
特定のコライダーにのみ関係してパーティクルを消したりTrigger[^1]を引いたりできるModule
###Colliders
**リストの形でどのコライダーに関係させるか指定するパラメーター**
###Inside
デフォルト Kill
**パーティクルがコライダーの<font color=red>内側にあるとき</font>にどうするか決めるパラメーター**
Kill(消滅), Ignore(何もしない), Callback(Triggerを送る)の3つ
###Outside
デフォルト Ignore
**パーティクルがコライダーの<font color=red>外側にあるとき</font>にどうするか決めるパラメーター**
###Enter
デフォルト Ignore
**パーティクルがコライダーに<font color=red>入るとき</font>にどうするか決めるパラメーター**
###Exit
デフォルト Ignore
**パーティクルがコライダーから<font color=red>出たとき</font>にどうするか決めるパラメーター**
###Radius Scale
デフォルト 1 (0.0001~3.402823e+38)
**パーティクルの当たり判定の大きさ**
###Visualize Bounds
デフォルト OFF
**パーティクルの当たり判定の可視化**
##Sub Emitters
パーティクルの動きをきっかけに他のパーティクルを出すためのModule
リストになっていてそれぞれ別のParticle Systemを設定できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2386883/00dd7f09-1250-9b2a-d5c2-df77c889ad65.png)
###モード
デフォルト Birth
**どういう条件で設定したParticle Systemが発動するか決めるパラメーター**
Birth: <font color=blue>パーティクル</font>が存在している間<font color=blue>1つ1つ</font>から<font color=green>設定したParticle SystemのパーティクルのRate over Time</font>で<font color=green>設定したパーティクルが出続ける</font>
Collision: **Collisionが有効のとき**<font color=blue>パーティクル</font>がコライダーに衝突した時に<font color=green>設定したParticle SystemがそのBurstsで一回だけ放出される</font>
Death: <font color=blue>パーティクル</font>が消滅した時に<font color=green>設定したParticle SystemがそのBurstsで一回だけ放出される</font>
Trigger: <font color=blue>パーティクル</font>がIs Triggerが有効のコライダーに侵入した時に<font color=green>設定したParticle SystemがそのBurstsで一回だけ放出される</font>
Manual: スクリプトで呼んだときだけ<font color=green>設定したParticle SystemがそのBurstsで一回だけ放出される</font>
###Inherit
デフォルト Nothing
**このParticle Systemからパラメーターをなにか引き継ぐか決めるパラメーター**
Everything, Color, Size, Rotation, Lifetime, Durationが他にある
あんま使わない
###Emit Probability
デフォルト 1 (0~1)
単位 割合
**設定したパーティクルが出てくる確率を決めるパラメーター**
##おわり
というわけでTriggers, Sub Emitters Module編でした
次はTexture Sheet Animation Module編です
[^1]: スクリプトとかアニメーションのイベントのきっかけにできるやつ、もしかしたらアバターでも使えるようになるかも
****
[External Forces, Noise Module編](https://qiita.com/abcde_kind/items/f9702c960b3d25db7d35) <<  ここ  >> [Texture Sheet Animation Module編](https://qiita.com/abcde_kind/items/8676b0066c2b37a616e7)
AfterEffects2022アップデート後に起動しない時の解決方法

# 状況

Mac Monterey OS
AE起動しようとすると、最初のタイトルビジュアルは出るけど強制終了されて起動できない。
下記After Effectsの警告が表示される。

（１）

``` <GPUManager> <2> Sniffer Result Code: 11 ```

![error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395383/2a4fa966-415b-f2a3-acb3-42d272eb603a.png)


（2）何回かやってたらこれも出た

``` <Scripting> <5> Executing startup/shutdown script at: --- ```

※ - 部分は旧バージョンでトライした時のなので2021になっている

![error2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395383/2b4c1359-038f-a823-e402-5b604f539616.png)

# 解決方法

> HD/Library/Application Support/Adobe/Common/Plugins/7.0/MediaCore　内にあるdummy.txt以外のファイルを別の場所に移動させる。

デスクトップに移動させて、AEを再起動したら解決しました。

## 参照元

https://community.adobe.com/t5/after-effects-discussions/last-log-message-was-lt-gt-lt-gpumanager-gt-lt-2-gt-sniffer-result-code-11/td-p/12483651

https://community.adobe.com/t5/after-effects-discussions/after-effects-is-not-working-with-monterey-os/td-p/12475922

アップデートとAEJuice入れてたのが原因かもと他の方のコメント見て思いました。
（再起動したり再インストールしたり他にも迷走したけど解決せずに、2時間くらいかかった；；）
テストケースを束ねしもの -とあるテスト管理ツール開発者の気づき-

本記事は [ベリサーブ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/veriserve) の24日目の記事です。
テスト管理におけるとある概念について、調べたり考察したりしました、というポエムです。クリスマスの夜の暇つぶしにでもなったら幸いです。もし何か誤り等ありましたら、コメントでその旨ご指摘いただければと思います。

## 突然ですが
読者の皆さま。

:::note info
複数のテストケースを束ねてできた情報、概念
:::

というと、何を想像しますか？

結論から言うと、ISTQB/JSTQB用語集上で定義されたものとしては、おそらく以下のものが該当しそうです。

- テスト手順
- テストスイート
    - 正確にはテストケースを束ねてできたテスト手順を、さらに束ねてできたもの、なのかな？

## テストケースのグルーピング
今更自己紹介ではありますが、私、株式会社ベリサーブで以下のツール群の開発マネージャーをしております、きんぢ、と申します。

- [QualityForard](https://www.veriserve.co.jp/qualityforward/)
- [GIHOZ](https://www.veriserve.co.jp/gihoz/)

上記のうちのひとつめのツール、QuailtyForwardはいわゆるテスト管理ツールに分類されるツールです。テスト管理ツールの最も基本的な機能はテスト実行の進捗や品質状況の可視化ですが、テストケースなどの成果物の資産管理も、テスト現場にとっては重要な機能かなと思います。

さて、テストの資産管理やテストの計画を立てる際、テストケースのグルーピングを考える局面が2つあります。

- 大量のテストケース自体をデータとして保持する際に、どうグルーピング・整理するのか？
- テスト計画時に、どの単位・順序でテストケースをまとめて、テスト実行者にアサイン・管理するか？

前述のテスト手順やテストスイートは、どうやら後者の文脈で作成される成果物を意味しており、逆に前者の資産管理の文脈で、テストケースを管理するカタマリ、に該当する概念はISTQB/JSTQBには定義されていないようです。

## スプレッドシートによるテスト管理

専用のテスト管理ツールではなく、Miscrosoft Excelに代表されるスプレッドシート系のツールでテスト管理をしているシステム開発プロジェクトはたくさんあると思います。スプレッドシートを用いてテストケースを管理する際、最も基本的なアプローチは、表の1行で1テストケースを表現し、それが縦に複数並ぶ形でテストケースが羅列され、そしていい感じの単位でシートやファイルを分けることでグルーピングされて管理されるやり方ではないでしょうか。

この場合、ファイル管理されている時点で、それがそのまま前述の資産管理の文脈でのグルーピング・整理になりますし、一方でテスト実行時にわざわざテストケースのかたまりを組み換えるのは非効率であるため、同時にテスト実行時に活用されるグルーピングでもあることが多いでしょう。

## QualityForwardによるテスト管理
次に、当社のQualityForwardの場合を見てみましょう。といっても、話は単純です。QualityForwardは開発コンセプトとして、スプレッドシートでテスト管理をしているプロジェクトが移行しやすいよう、スプレッドシートの1シートをそのまま1「テストスイート」という単位でインポートし、その後のテストケースの編集やレビュー、計画や実行もこの単位で実施していただく設計となっております。

つまりQualityForwardは、テストケースのグルーピングについて、スプレッドシート利用時と同様、2つの文脈を同時にテストスイートという単位で管理をします。

:::note warn
前述のとおり、ISTQB/JSTQBにおいては、テストスイートはテストケースではなく、テスト手順をグルーピングしたもののようなので、厳密にはQualityForwardが用いているテストスイートの定義とはズレがあります。
:::

## 他社製品によるテスト管理
では、他社のテスト管理ツールでは、これらはどのような形で管理されるのでしょうか？今回は例として、MICRO FOCUS社の[ALM/Quality Center](https://www.microfocus.com/ja-jp/products/alm-quality-center/overview)と、Gurock社の[TestRail](https://www.gurock.com/testrail/)について、チームメンバーに調査をしてもらい、結果として以下のようになっていました。

- どちらのツールも、テスト資産管理とテスト実行の文脈では、異なる概念でグルーピングをする設計となっている。
- Quality Centerの場合、後者は「TestSet」、前者は「Subject」というツリー構造のフォルダにケースを1件1件ファイル感覚で保持する。
- TestRailも同様、後者は「TestRun」、前者は「section」という名前で、やはりツリー構造のフォルダ管理。

## 以上からわかるQualityForwardの特長
以上から、QualityForwardと代表的な他社のテスト管理ツールとは、テストケース資産管理の考え方で明確な違いがあることがわかります。

QualityForwardはスプレッドシートの考え方を踏襲し、テストケースの資産管理とテスト実行時とで、同じグルーピングでテストケースを扱います。したがって、テスト実行ごとにテストケースの順序や組み合わせを柔軟に組み替えることは困難ですが、同じ単位で問題ないシーンにおいては、テスト計画時の効率がよいと考えられます。

一方、他社ツールは管理単位が異なるため、テスト計画時に都度テストケースを組み合わせてテスト手順を作成する必要があります。しかし、それによって、実行時のコンテキストにあわせた柔軟なテスト計画が実現可能です。

## まとめ

- テストケースのグルーピングを扱う際、2つの観点がありそう。
- ISTQB/JSTQBでは、テスト実行文脈の概念の定義はあるが、テスト資産管理の文脈での概念は特に定義されていなさそう。
- テスト管理ツールには、これら2つの文脈で、同じグルーピングでテストケースを管理するものと、文脈ごとに異なる仕組みでグルーピングするものがある。
- どういうシーンにおいて、どちらのアプローチがより適しているかは、今後もっと深く考察したいと思う。（力尽きた）

そんなところです。
Playgroundsを用いるApp開発において，パッケージを追加する

#概要
Playgrounds及びiOS, iPadOSのアップデートに伴い，Mac上のXcodeを用いずともAppの開発を行うことが可能となった。Playgroundsにおいて，外部ライブラリを使用したいと思った。XcodeであればcocoaPodsを使用するが，Playgroundsでは使えなさそうだった。そこで，Playgroundsにおいて，外部ライブラリ（パッケージ）を追加する方法を記載する。

#前提
今回は，アプリ内でグラフを描画したかったので，ChartsというSwiftのライブラリを導入しようと思った。基本ライブラリであれば，

```swift:import.swift
import SwiftUI
import Accelerate
```

のようにすれば簡単に導入できる。
ところが，外部ライブラリであるChartsはこのままimport文を記述しても"No such module 'Charts'"と，怒られる。

#方法
①Playgroundsのアプリ内で，ファイルを追加するボタンをタップする。
②最下部に「Swiftパッケージ」とあるので，これをタップする。
③パッケージURLを入れる欄があるので，ここにimportしたいライブラリのURLを入力する。

このパッケージURLがどのようにすれば発見できるのかが不明だった。ただ，ChartsはGitHubに上がっており，そのリポジトリのURLを入力すると適切なバージョンと導入されるものが自動で表示された。そのまま右上のプロジェクトに追加をタップすると，パッケージとしてChartsが追加された。
PowerAutomateの日時とExcelの日時の相互変換

今回はPowerAutomateの日時とExcelの日時の相互変換についてのお話です。
すでにそこら中で語られている内容ではあるのですが、私なりの観点と見解でまとめておきたいということで。

# Background

Power Automateは日時データをISO8601形式でフォーマットされた文字列として表現します。Power Automateにはデータ型としての日時型というものはなく、ただ「決められた形式にフォーマットされた」文字列型があるだけです。そしてこの日時データはタイムゾーンの情報を持ちます。

Excelは日時データをシリアル値という数値（正の実数）で表現します。こちらもデータ型としての日時型というものはなく、ただ「決められた方法で、日付を整数部分に、時刻を小数部分に、それぞれ変換した」数値型があるだけです。
日付（整数部分）は1900年1月1日を`1`としてそこからの経過日数を加えていく形で表現します。例えば1900年1月3日は`3`です。
ただし「1900年2月29日が存在したかのように数える」（グレゴリオ暦上は存在しない）Excelの仕様のため、日付計算の観点で言えば、実質的には1989年12月31日を`1`とみなすべし、さらにそこから1989年12月30日を`0`とみなすべし、こういうことになります。

一方、時刻は24時間を`1.0`として各時刻を`0.0`から`0.999...`の間の小数で表現します。例えば06:00は`0.25`です。
この日時データはタイムゾーンの情報を持ちません。

# Problem

Power AutomateとExcelの間で日時データをやり取り（Power AutomateからExcelに書き込んだり、Excelから読み込んだり）するとき、この日時の変換をどのように行うかが問題となります。

## Power Automate標準の機能で行う

以前 [PowerAutomateのISO8601とシリアル値の相互運用の条件](https://qiita.com/mizukyf/items/48a5bdad81abdb329467)でも言及している 「表内に存在する行を一覧表示」「表に行を追加」などのアクションの「DateTime形式」設定を活用することで、Power Automateの日時データとExcelの日時データの相互変換を実現できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/e220dd8a-4764-4b77-33a8-8027b242d94f.png)

### メリット

* __可読性が高い__。アクションやフローが「何をやっているか」がわかりやすい。難しい計算式を読み書きする必要はなく、アクションの設定項目を見れば「何をやっているか」は明白。
* __生産性・品質に優れる__。わかりやすければ結果としてフロー作成の生産性や品質が上がる。

### デメリット 

* __外的要因の影響を受ける__。この設定が正しく機能するかどうかは、Excelワークブック側の「表示形式」とテーブル内のレコードの状態に依存する（詳細は[前掲記事](https://qiita.com/mizukyf/items/48a5bdad81abdb329467)を参照のこと）。
* __タイムゾーンの扱いが曖昧になる__。Excelのシリアル値にはタイムゾーンを表現するすべがないので、Power Automateからその値を読み取るとすべてUTCの値として理解される。例えばシリアル値 `1.25` は `1900-01-01T06:00:00.000Z` とみなされる。

## 式関数で行う

これは「DateTime形式」設定の登場以前からあった方法です。
シリアル値の仕様を踏まえて、以下のように式関数を組み合わせることで、日時データの相互変換を実現します。

### Power Automate → Excel

Power Automateの日時データ（ISO8601形式文字列）をExcelの日時データ（シリアル値）に変換する：

```ts
div(sub(ticks( ISO8601形式文字列 ), ticks('1899-12-30T00:00:00')), 864000000000)
```
### Excel → Power Automate

Excelの日時データ（シリアル値）をPower Automateの日時データ（ISO8601形式文字列）に変換する：

```ts
addSeconds('1899/12/30T00:00:00', int(string(mul(float( Excelシリアル値 ), 86400.0))))
```

前述の通り Excelの仕様で（シリアル値は1900年1月1日起算、ただし開始値が`0`ではなく`1`、さらに1900年2月29日問題が存在）、日時データ変換の計算に用いる基準日は 1899年12月30日 となります。
なお、Excelから取得したシリアル値は文字列型となるので、計算の際に注意が必要です。

### コードサンプル

例えば 2021年12月24日12時58分00秒 を表す日時データの相互変換は次のようになります：

```ts
div(sub(ticks('2021-12-24T12:58:00'), ticks('1899-12-30T00:00:00')), 864000000000)
// => 44554.5402777778

addSeconds('1899/12/30T00:00:00', int(string(mul(float('44554.5402777778'), 86400.0))))
// => '2021-12-24T12:58:00'
```

### メリット

* __外的要因の影響を受けない__。変換処理の挙動がExcelワークブック側の「表示形式」やテーブル内のレコードの状態に依存しない。
* __タイムゾーンの扱いが明瞭になる__。`ticks()` 関数はタイムゾーン付きの日時表現を渡すと内部でUTCに変換した上で計算をしてくれる。タイムゾーンなしの日時表現や 末尾が `Z`で終わるUTCの日時表現を渡すとそのままUTCとして計算をしてくれる。タイムゾーンに関わる変換が関数使用を通じて明確になっている。

### デメリット 

* __可読性が低い__。アクションやフローが「何をやっているか」がわかりにくい（少なくともこの日時データ変換の部分はわかりにくくなる）。
* __生産性・品質が劣る__。わかりにくければ結果としてフロー作成の生産性や品質が上がる。

## 私の見解

私は総合点で言えば「式関数で行う」方式が優れていると感じています。

「標準の機能で行う」方式は可読性こそ優れるものの、処理結果が外的要因の影響を受けるために挙動を読みづらいものとなっています。
状況次第で起きたり起きなかったりする分かりづらいエラーに悩まされるリスクのある方式よりは、最初にきちんと正確な式を書いておけばいつでも正しく動く方式の方が優れていると考えています。
Jamf ProのSmart Computer Groups設定で事故った話

みなさんこんにちは。Jamf Heroesの[あおてつ](https://twitter.com/ao_Tetsu)です。
この記事は[情シスslack Advent Calendar 2021 #2](https://adventar.org/calendars/6179 "情シスslack Advent Calendar 2021 #2") 23日目の記事です。
（すでに1日過ぎて24日になってます。。。ごめんなさい）

# はじめに
先人の成功体験から得る学びは大きい。それと同様に失敗体験から得る学びもまた大きい。
と言うことで、今回は年忘れと禊を兼ねて **「Jamf ProのSmart Computer Groups設定で事故った話」** という失敗談をご紹介致します。

# 背景
弊社のJamf Pro環境では会社で所有している全コンピューターを対象にインストールしている構成プロファイルがいくつかあります。（無線LAN接続設定とか、業務で必要な証明書配布とか）
一方で、リースした機材の場合はこれらの構成プロファイルのインストールを除外するケースもあります。具体的にはJamf ProのSmart Computer Groupsで「LeaseComputers」というグループを作り、クライテリアでリース機材のシリアルナンバーを登録、
![スクリーンショット 2021-12-24 19.24.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140000/3bb77cd9-f265-82f5-5ddf-4ba76fb5b85d.png)
構成プロファイルの設定ではスコープのTargetsで「All Computers」を設定し、Exclusionsで「LeaseComputers」を設定することで、リース機材だけ構成プロファイルインストールを除外する、という運用を行っていました。
![スクリーンショット 2021-12-24 19.26.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140000/a9add1d1-7d3a-a525-876e-4009e1ebb858.png)

# リースが終了したのでやったこと
あるときリース期限が終わり機材は返却することになったので、それに関連するJamf Proの設定も削除することになりました。Smart Computer Groupsでシリアルナンバーを登録していたので、それを削除すればいいや。「LeaseComputers」のグループ自体はまたリース機材を使う時が来たら再利用するかもしれないから、箱としては残しておこう、ということでクライテリアからシリアルナンバーを削除しました。そして保存ポチ。![スクリーンショット 2021-12-24 19.35.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140000/7fcd31b9-c222-8b5e-79fe-dc525871ec4b.png)

# その瞬間悲劇が・・・
その瞬間です。いきなりネットワーク（無線LAN）が切れました。証明書が使えなくなりました。
　　あおてつ「あれ・・・？」
はじめ、何が起こったのかわかりませんでした。ネットワークトラブルかと思いました。
が、周り（ちょうどそのとき出社してた）でもMacの無線LANが繋がらなくなったという声がちらほら。。。

　　あおてつ「Oh,やっちまった・・・」

直前にやったJamf Proの設定変更が悪さしたのは直感的にわかりました。
Mac側のプロファイル設定見たら必要な構成プロファイルが消えてました。

　　あおてつ「あのSmart Computers Groups、クライテリア削除しちゃダメなのか！！」

そうなんです。
Smart Computers Groupsはクライテリアをすべて削除すると、すべてのComputerが対象になります。
あとでマニュアル見たらちゃんと書いてありました。。。
> 注: クライテリアが設定されていないスマートグループを作成すると、すべてのマネージドコンピュータ、モバイルデバイス、またはユーザがメンバーシップに含まれます。

[Jamf Pro ドキュメント スマートグループ](https://docs.jamf.com/ja/10.34.0/jamf-pro/documentation/Smart_Groups.html)

構成プロファイルのScopeとしてはTargetがAll Computersで、ExclusionsもAll Computersと同等。
この場合、Exclusionsが優勢で、すべてのコンピューターに対して構成プロファイルのアンインストールが走ります。

あぁ、悲しき勘違い。悲しき仕様確認漏れ。
経験上、動的グループ的なやつの動作は
　**条件指定しなければゼロ、条件に合致したものを抽出**
だと思い込んでいたのですが、Jamf ProのSmart　Computer Gropusは
　**条件指定しなければALL、合致したものに絞り込む**
だったのです。 
（いや、みんな「条件指定しなければゼロ」だと思うでしょ？？え？違う？）

# その後
と言うことで、構成プロファイルのインストールを戻すためにExclusionsから「LeaseComputers」を外したのと、忌まわしい思い出になってしまったので「LeaseComputers」も箱ごと削除して闇に葬りました。。。
コロナ禍で出社している人の数も少なく、かつ夕方で業務を終わらせている人が多く影響が少なかったのが不幸中の幸いでした。それにしてもこんなショボいミスをするなんて。。。

**Jamf Heroesとして不甲斐なし！穴があったら入りたい！！**
（泣きたくなってJamf Heroes返還しようかと思いました。。。返還できるのか知らんけど）

特にオチはないんですが、Jamf Proに限らず動的グループの類の設定変更の際は十分留意しましょう。
設定保存前にプレビューできる機能があるといいなぁ。。。
静的型付けと動的型付けを実務で扱った感想

**大事なこと🥺**
僕自身の感想であって、何かを押し付けるわけではなく、感想は人それぞれです。


# 自己紹介
経験で言うと

```
Rubyだけ (型なし)
 ↓
Ruby, Vue (型なし)
 ↓
Go, React　(型あり)
```

みたいなキャリアを歩んできました。
初めて型を書いた日はカルチャーショックが強くて、なんて無駄な時間なんだと小一時間悩みました。

動的型付けも静的型付けも、結局のとこ書き慣れてる方が楽に感じると思ってて
静的型付けじゃなきゃ嫌だって人は、好みに引っ張られまくりな気がする。

一方で、広い目線で見渡すと、Rubyもjavascriptも動的型付けだったのに、静的型付けっぽく書けるように`rbs`や`TypeScript`ができたり、**型を書き慣れてる人**がいっぱいいて、需要があるんだろうなと思っていて、結局は全エンジニアが型を書くことになるんだろうなとゆるく思ってます。

**注意時刻**
以下、デメリットは裏返しになるだけなので、書きません。
またパフォーマンス面での比較も重要な指標になりますが、表面的なメリットしか考えないことにします。
大概のwebサービスは静的型付けでも動的型付けでも、試行錯誤である程度のパフォーマンスは出せるはずです。

# メリットを考える
開発速度が速い/遅いについては議論しないです。あなたの実力次第だと思いました😈

## 静的型付けのメリット
### ソースがすぐ見つかる
ライブラリのソースを見つける速度が、本当に体感100倍ぐらい違います。
一方で`TypeScript`はライブラリのソースを読みたいのに、型定義書に飛ぶので、ムカつく(vscodeの設定で解決できそうだけど知らん)

### typoが存在しない
地味なんですが、開発効率上がってるはずです。コンパイルする前から、vscode側が判定して指摘してくれるので、railsみたいに、ローカルでは動くのに、デプロイした時だけ動かないみたいなこともないです

### どういうオブジェクトが渡されているのか、一目でわかる
当たり前なんですが、、威力のあるメリットだと思っていて、ソースが膨大になる程、良い影響がありそうです。

```go
// go
func Xxxx(u User) {
  fmt.Println(u.name)
}
```

## 動的型付けのメリット
### オブジェクトを気軽に生成できる
一時的にしか使わないオブジェクトとかは`Ruby`とか`js`っぽいなと思ってて、
`Rails`だと、`ActiveRecord`のレコードの集合をパースして、扱いやすいオブジェクトの配列に変換したりするコードって、動的型付けらしいなと思います

```ruby
# ruby
name_with_num_items = User.all.map do |user|
  {
    name: user.name,
    num: user.num
  }
end
```

### 静的型付けのメリットをデメリットだと思っていない
身も蓋もない話なのですが、地味にあるなと思ってて. 

**ソースを見つける速度**
`Rails`だと、クラスからソースの場所がわかるようになっていたり、何だかんだオブジェクトは`ActiveRecord`に集約されたり、動的型付け言語側がわかりやすい仕様にしているなと感じることが多いです（`js`は除く）

**typoが起きるかどうか**
静的型付けも動的型付けであっても、統合テストするので、結果的に気づくには気づくはずです

**引数のオブジェクトの型が何なのか**
動的型付けだと、変数名を変に省略せずにわかりやすくする傾向があることや、オブジェクトがファイル名になっていたり、見つけやすいことが多いとも思ってます. 
~~少しダックタイピングな感じで気持ち悪いと感じる人も多いかもしれないですが😇~~

```rb
# ruby
# app/models/user.rb
class User < ApplicationRecord
end

def xxx(user) # ActiveRecordのUserしか考えられない
  p user.name
end
```

# 勘違いしていたこと
動的型付け言語の現場から、静的型付け言語の現場に転職するときに、思っていたことの答え合わせを少しします。

### 静的型付け言語だとバグが少ないのでは？
そんなことありませんでした。
バグが少ないかどうかは、エンジニア側の実力とチームのテストやレビューの精度が影響するのであって、静的型付けは安全だと思ってる人は、滝に打たれるべき😵

### TypeScriptを一度経験したら、TypeScirpt信者になるのでは？
そんなことありませんでした。
むしろ、脳死で`TypeScript`って言ってる人はヤバいということがわかりました。
`TypeScript`にするかは、

- ソースコードの規模が大きい
- メンバーで`TypeScript`に慣れてる人がいる
- API側が静的型付け言語

辺りを考慮に入れて、最終的にはCTOがどうしたいのか、ぐらいの意思決定になりそうだなと思いました。  
特にAPIが`Rails`で、エンドポイントごとに返却するオブジェクトの型が様々ある場合は、意外と`TypeScript`だとしんどくなりそうだなと思いました🤲

逆に`Go`だと、構造体を丸ごと返却することが多いので、`TypeScript`と相性が良いなと思いました.

更に細かい話をすると、`Vue`は`TypeScript`が書きにくくて、`React`は`TypeScript`が書きやすい、みたいな宗教上の違いもあって、`TypeScript`を使いたいからフレームワークの選定が変わってきたりもすると思いました😤

### 初めて静的型付け言語を書くので、適応できなくて苦労しそう...
そんなことありませんでした。
`TypeScript`も`Go`も初日はビックリビックリすることが多かったのですが、何だかんだ半年もすればある程度は手に馴染みます。
~~もちろん、業務外でもいっぱい自習してる前提です😈~~
とはいえ、ライブラリのソースを読むときに、ジェネリクスがふんだんに使われたりしていて、読むのに少し時間かかったりもします。

まあ、両方やったことが自分にとって良い経験になっています。