OmniAICreator/Qiita-1.07M huggingface dataset:
【Flutter】開発するよりもアプリリリースの準備が大変だった話




#はじめに
Flutterを初めて5ヶ月ほどになり、アプリ開発も考えることが多く試行錯誤して開発しましたが、AppleStore,GooglePlayに申請するまでの手順が大変だったので記事にしてみたいと思います。

想定購読者はこれから個人でモバイルアプリを開発し、リリースまでやってみたい「過去の自分に向けて」この記事を書いています。

文章を要約すると**「個人開発は難しくて楽しいが、開発した後もやることが多いぞ！」**です。

**アプリリリース前に知っておきたいこと**
アプリリリース前に以下のことが必要になってくるので、覚えておきましょう！

#アプリをリリースするのにお金がかかる
AppleStore,GooglePlayにアプリを公開しようとする場合、**GooglePlayの場合は25ドル、AppStoreの場合は99ドル/年間**がそれぞれ開発者登録の費用として必要になります。
決して安い金額とは思いませんが、個人でのアプリリリース経験が積めるので、価値は十分にある金額だと思います。

#睡眠時間が減り日常生活に支障をきたす
仕事とは別に開発をする以上どこかしらで時間を捻出する必要があります。結果として睡眠時間を削って作業するケースが多いと思います。
私自身も帰宅後に開発に夢中になっていて気がついたら日付が変わっていることがありました。
仕事と個人開発の両立は難しいです。本業に支障が出ない程度に頑張って、極力朝早起きしてコードを書いたり、休日を使って一気に開発するのが継続に繋がると感じました。

#恥じらいは捨てて一旦リリースしてみる
**「こんなダサいデザインで大丈夫だろうか」**
**「他のアプリと名前かぶっていないかな」**
**「こんな機能の少ないアプリダウンロードされるのかな」**
このような不安はあるかと思いますが、とにかくまずはアプリをリリースすることを目標にするのが良いと思います。
９割の人がプログラミングを挫折すると言われており、個人でアプリ開発して各ストアにリリースできるのはプログタミングに
挑戦して10人に1人の割合だと思います。
ですので、恥を捨てて一旦、リリースまで持っていきましょう！！
そうすることにより、コツを掴んで今後のアプリ開発を有利にするめることができるからです。

#各ストアに登録してから時間がかかる
AppleStore,GooglePlayに登録したから認証されるまでに１日〜２日の時間がかかります。

**Google Play Console**
https://developer.android.com/distribute/console?hl=ja

**Apple Developer Program**
https://developer.apple.com/jp/programs/
各ストア登録してから時間がかかるので、前もってこの情報を知っているとスムーズに作業を進めることが可能になります。
以下のメールが登録して２日後くらいに届きました。
![iOS の画像 (3).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740384/be3f313e-8f82-0df5-5b90-a7d43da625b2.jpeg)

#プライバシーポシリーなどが必要になってくる
アプリに関しての情報として、プライバシーポリシーが必要になってきます。
参考サイトとして、プライバシーポリシーの雛形（ひな型）を参考にしてHPに記載しました。（使用するかどうかは個人の判断になります）
https://kiyaku.jp/hinagata/privacy.html

**Wix.com**等でホームページを無料で作成できるので、こちらを参考にしてHPを簡単に作成することができます。
![スクリーンショット 2021-12-16 20.11.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740384/24de5d54-c17c-3e57-3f2b-f5da4125a363.png)

https://ja.wix.com/

#各画面のスクリーンショットが必要になる
アプリをリリースする際に各機能のスクリーンショットが必要になります。
↓iPhone画面サイズ、ピクセル数早見表を参考に作成しました。
https://qiita.com/GENZ_INC/items/4342ee29b087bc56b476
![ 2021-12-16 14.04.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740384/cd308308-c232-9995-3d79-83803e569dc9.png)

#おわりに
**個人開発を実際にやってみた所感として、難しいけどやってよかったです！**
何度も壁にぶつかって、調べてその繰り返しでしたが、プログラムを早く習得するには恐れずに続けることが大切だと学びました。
でも、もし少しでも個人開発が気になっていてまだ一歩踏み出していない方がいらっしゃいましたら是非、ご自身でアプリを一つ作成してリリースところまで体験してほしいと思っております。
最後までこの記事を読んでいただいた方に感謝します！
ありがとうございました！
Datadog Log Rehydrationの紹介

Datadog logsとても便利ですよね。ですがデータを長時間保持することはできず、古いデータは消えてしまいます。
そういうときに、S3などのクラウドストレージにログを保存する設定を入れておくと消えた後でも再度ログを持ってくることで検索可能にすることができます。

本当はまだ使ったことのないDatadogの新しい機能を使ってみて「使ってみた」記事を書こうと思ったのですが、最近この仕組みに助けられたためにLog Rehydrationの紹介をします。

## なにができるのか
Datadog logsの保存期間は一定（デフォルトでは2週間）でそれを超えると、Datadog logsからデータが消えます。
以下は2ヶ月間を指定して、直近一月以上前のデータが消えている状態です。（弊社は保存期間をひと月にしています）
![Log_Explorer___Datadog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17490/07a9d46e-77f9-dbd4-87b8-9c8897e9fac4.png)

課金すれば、さらに長い保持期間を設定できるのですが、いつまでもログを保存しておくと高額になります。そこで取り込んだログを別のストレージに保管しておくことで、必要になったときに検索可能にすることができます。

## 設定方法
まずDatadogにあるログをクラウドストレージに保存する設定をDatadogにする必要があります。Archives → New Archiveを押下すると、どのクラウドストレージに保存をするのかを設定できます（AWS、GCP、Azureが指定できます）

![スクリーンショット 2021-12-16 20.38.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17490/43be2e6d-7742-9461-c50e-4fa88f0ff9a6.png)

![Logs___Datadog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17490/f2237aae-ef63-b165-7959-e4a79225f2bc.png)

ここではAWS S3を選択します。画面ではDatadogで設定しているIAMの権限が選択可能になっていますが、そのロールにS3に書き込む権限が必要になるのが注意点です。
![Logs___Datadog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17490/88256bf4-8d56-df72-7399-d22d0605cfdc.png)
### S3への書き込み権限の設定例
![IAM_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17490/cf29e72a-7e63-207f-2781-b4f41fcbc2fd.png)

以上の設定をすると自動的に過去のログをS3に保存してくれます。
以下は保存されているS3の画面です。
![prd-loglass-system-logs_-_S3_bucket.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17490/e98b8edc-07f7-d809-9a98-dcb85f1d9e86.png)

## Log Rehydrationの手順
さてクラウドストレージへの保存が完了したので、そこからdatadogへログを再度流し込んでみましょう。
Rehydrate from Archives → New Historycal Viewを押下し、いつのログを戻したいのか選択します。
![スクリーンショット_2021_12_16_20_50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17490/e2523b40-64f3-d952-34f9-7638c28ed7cc.png)

![Logs___Datadog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17490/4649750d-078f-5b65-0b47-4cedb39f0fc0.png)

上の図は11/10-11/11の2日間のログを戻してくる設定。
クラウドストレージからDatadogにログを戻すのには少し時間がかかります。その推定時間は画面に表示されます。
またどれぐらいの量のログを戻すことになるのかは、同じ画面から推定することもできます。


## 検索してみる
![スクリーンショット_2021-12-16_21_03_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17490/0465b360-a01b-bd1f-3eb6-420967a9db21.png)

作成したIndexはdatadog logsのIndexでHistorycal Indexesとして選択することができるようになります。

以上です。
これで過去のデータも検索できてさらに調査が捗りますね。
C#の非同期処理 基礎編

## はじめに
この記事ではC#のTaskを用いた非同期処理の書き方を初心者向けに解説します。
家事の洗濯と料理を例にあげて感覚的に非同期処理と同期処理がわかるように紹介しています。

## 処理の前提
- 洗濯と料理は同時並行で進められるものとします（非同期処理）。   
    - 洗濯は一度洗濯機に衣類を入れてスイッチを押してしまえば自動で洗濯してくれます。
    - 料理は焼いている間は焼き上がるまで特にやることはありません。   
- それぞれの作業工程は一つ目の工程が終わってからでないと着手できません（同期処理）。
    - 洗濯は一度洗濯機に衣類を入れてスイッチを押してしまえば自動で洗濯してくれます。   
    - 料理は焼いている間は焼き上がるまで特にやることはありません。   
        
つまり、洗濯と料理を同時並行で家事をはじめて、終わった物からそれぞれの次の工程に進みます。


## 例

```C#:program.cs
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Sample
{
    class Program
    {
        static Task Main(string[] args)
        {
            // 洗濯と料理は非同期処理
            // 洗濯の作業
            Task<string> washing = wash();
            // 料理の作業
            Task<string> cooking = cook();

            // 結果を出力
            Console.WriteLine(washing.Result);
            Console.WriteLine(cooking.Result);

            return Task.CompletedTask;
        }

        // 洗濯と料理のそれぞれの工程は同期処理
        // 洗濯
        static async Task<string> wash()
        {
            Console.WriteLine("【洗濯①】洗濯開始");
            await Task.Delay(5000);
            Console.WriteLine("【洗濯①】洗濯　終了");
            Console.WriteLine("【洗濯②】乾燥　開始");
            await Task.Delay(2000);
            Console.WriteLine("【洗濯②】乾燥　終了");
            return "洗濯完了";
        }

        // 料理
        static async Task<string> cook()
        {
            Console.WriteLine("【料理①】味付け　開始");
            await Task.Delay(2000);
            Console.WriteLine("【料理①】味付け　終了");
            Console.WriteLine("【料理②】焼く　開始");
            await Task.Delay(4000);
            Console.WriteLine("【料理②】焼く　終了");
            return "料理完了";
        }
    }
}
```

## 実行結果
```
【洗濯①】洗濯開始
【料理①】味付け　開始
【料理①】味付け　終了
【料理②】焼く　開始
【洗濯①】洗濯　終了
【洗濯②】乾燥　開始
【料理②】焼く　終了
【洗濯②】乾燥　終了
洗濯完了
料理完了
``` 
## コード解説 
### static async Task

- Mainメソッドの中でasyncメソッドを使うおまじない

### async / await

- 非同期にしたい処理を含むメソッドは修飾子asyncをつける
- 非同期にしたい処理にはawaitをつけて実行する   
※awaitは戻り値がTask型のメソッドにしか付けられない
- awaitがついているメソッドが実行されると、そのメソッドを抜けて呼び出し元（Mainメソッド）に戻る

### Task

- taskの戻り値はTask型もしくはTask型のジェネリックにする     
- Delayプロパティは引数で指定した秒数を待ち、その実行状態をTask型で返す非同期メソッド
- Resultプロパティで戻り値を取得できる

## 参考
[多分わかりやすいC#の非同期処理その2 〜 asyncとawait 〜](https://tech-lab.sios.jp/archives/15711#asyncawait-2)
[Task.CompletedTask プロパティ](https://docs.microsoft.com/ja-jp/dotnet/api/system.threading.tasks.task.completedtask?view=net-6.0)
[C# 非同期、覚え書き。](https://qiita.com/hiki_neet_p/items/d6b3addda6c248e53ef0)
subprocessを使ってコンソール引数付のpythonファイルを外部から実行する

### コンソール引数付のファイルを外部から実行する

```subpro_qiita.py
import subprocess
from time import time

name_list = ["john","power","smith","jack"]

for i in name_list:
    print(i)
    # コンソール実行時の場合に空白で区切る部分を分割してリストに入れる"
    # python greeting.py --nickname XXXX の場合下記のようになる。
    command = ["python","greeting.py","--nickname", f"{i}"]
    proc = subprocess.Popen(command)
```

実行するファイル

```greeting.py
import argparse
import time

def arg_res():
    parser = argparse.ArgumentParser()
    parser.add_argument('--nickname',required=True)

    args = parser.parse_args()

    nickname = args.nickname

    greeting_sentence = f"僕のニックネームは{nickname}"

    return greeting_sentence

def test_main():

    greeting_sentence = arg_res()
    print(greeting_sentence)

if __name__=="__main__":
    test_main()
```
個人開発のメリット、デメリットについて

##### アジェンダ

    - 1.個人開発とは？
    - 2.個人開発のメリット、デメリット（一人の場合）
    - 3.個人開発のメリット、デメリット（チームの場合）
    - 4.まとめ
 
---

##### 1.個人開発とは？

私のイメージは以下の通りです。

    - 一人でサービス開発から運用まで行う
    - チームでサービス開発から運用まで行う

##### 個人”開発”でも、チームで開発する場合もある

---

##### 2.個人開発のメリット、デメリット(一人の場合)

- メリット
    - サービスの内容を自由に検討できる
    - 好きな技術を取り入れることができる

- デメリット
    - サービス内容がユーザにウケるか判断がつかない
    - 技術力がない場合は、行き詰まる
    - 進捗は自分自身ででマネジメントしないといけない

---

###### 2.個人開発のメリット、デメリット(一人の場合) ご参考

![goala.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141939/77ac3450-27bc-a1c6-57d4-9294657b0541.png)

---


##### 3.個人開発のメリット、デメリット（チームの場合）

- メリット
    - チーム開発の手法を学べる
    - チーム開発のスピード感を味わえる
    - チームメンバーが刺激となり、モチベーションが上がる
    - 分からないことを解決しないといけない状況に追い込める
    - マネジメントを受けれる
    - 純粋にチームで開発すると楽しい（笑）
    - アウトプットが癖付く

- デメリット
    - チーム開発が楽しくて、”個人”で行う個人開発が進まない（笑）

社会を回しているシステムは会社、チームで開発をしている。
個人開発（チーム）の経験はITに関わる人間にとっては、
大きなメリットである。

---

##### 4.まとめ

個人とチームで開発を行うメリットを享受しつつ、
個人開発を行うのが一番楽しく開発をできるのではないかと考えます。
TestCafe で待ち処理

株式会社カオナビでE2Eテストを推進している iamapen です。
現在はテスティングフレームワーク（TAF）に [TestCafe](https://testcafe.io/) を使用しています。

TypeScriptで書くことができ、セットアップが簡単なのが使いやすいところです。
Smart Assertionという仕組みがあり、待ち処理を書かなくてもよいとされています。

待ち処理はE2Eテストの安定性に深く関わるため、それを書かなくてよいのであれば助かります。
TestCafeにおける待ち処理の書きかた、を紹介します。


## Smart Assertion の例

たとえばこのように書くと、ボタンが表示されるまでクリックの試行を自動でリトライしてくれます。
表示待ちのコードを自前で書く必要がありません。

```typescript
const btn = Selector('button.save');
await t.click(btn);  // 表示されるまでリトライしてくれる
```

たとえば「ID・PWを入力してログインボタンを押す」のようなシンプルな画面であれば、
Smart Assertion の暗黙の待ち処理を頼るのみで、表示待ちのコードがゼロで、テストが実装できます。

Smart Assertionの詳細な仕様は公式ドキュメントへ。
https://testcafe.io/documentation/402837/guides/basic-guides/assert#smart-assertion-query-mechanism


## Smart Assertion を使って待ち処理を書く

しかし万能というわけではなく、よほどシンプルな画面でない限り、
現実的には「Smart Assertion を利用して待ち処理を簡潔に書く」ことになります。

とはいえ自前でループを書かなくて済むだけでも助かります。
多くの場合は簡潔に書くことができます。


たとえば、「編集」ボタンを押してから編集モーダルに文字を入力するような場合で、
画面は以下のような挙動をするとします。

```
1. 「編集」ボタンを押す
   1-1. 編集モーダルと タイトルtextbox が描画される
   1-2. タイトルtextbox に、現在の値が反映される
2. タイトルtextbox に新しい文字列を入力
3. 「保存」ボタンを押す
```
![2png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29639/843b9761-19a5-f947-365f-9c17ed02b2ca.png)


この場合、
Smart Assertion で 1-1 までは暗黙に解決できますが、1-2 の完了も待たないと、
テストで入力した文字が現在値で上書きされることがある、不安定なテストになってしまいます。

それを防ぐために、Smart Assertionを使って待ち処理を簡潔に書き、1-2 の完了を待たせます。

```typescript
const textbox = Selector('input[name=title][type=text]');

// 編集モーダルオープン開始
await t
    .click(Selector('btn.edit'))
    .expect(textbox.filterVisible().exists)
    .ok('textboxの表示待ち')
    .expect(textbox.value)
    .eql('変更前のタイトル', '現在値の反映待ち');
// ここまでして、編集モーダルオープン完了

await t.typeText(textbox, '変更後のタイトル');
await t.click(Selector('btn.save'));
```


## Smart Assertion が使えないケース

Smart Assertion に対応したアサーションメソッドが使えない場合、自前で書く必要があります。
TestCafeの機能に頼れないので、ループやPromiseを使って対応します。

たとえば、要素の非表示を「画面外の上部に配置する」など、特殊な実装で実現している画面で、要素が画面内に表示されるまで待つ場合など。

```typescript
export class FooPage {
  /**
   * 画面外の上部に配置して隠していた要素が画面内に表示されるまで待つ
   */
  async waitForXxx(
    selector: Selector,
    config = { timeoutMillis: 5000, checkIntervalMillis: 500 }
  ): Promise<void> {
    return new Promise((resolve, reject) => {
      let elapsed = 0;
      const interval = setInterval(async () => {
        if (await selector.filterVisible().exists) {
          const top = await selector.getBoundingClientRectProperty('top');
          if (top >= 0) {
            clearInterval(interval);
            return resolve();
          }
        }

        elapsed += config.checkIntervalMillis;
        if (elapsed >= config.timeoutMillis) {
          clearInterval(interval);
          return reject(new Error('timeout'));
        }
      }, config.checkIntervalMillis);
    });
  }
}
```

利用側

```typescript
const page = new FooPage();

const node = Selector('div.foo');
await page.waitForXxx(node);  // 表示まで待つ

await t.click(node);
```


TestCafe の各種タイムアウト設定をテストコードから取得できないので、タイムアウト値は selector timeout などとは別管理になってしまうのが残念...。







## まとめ

TestCafe で待ち処理を書く方法を紹介しました。

上記のサンプルコードもそうですが、[Page Model (Page Object)](https://testcafe.io/documentation/402826/guides/concepts/page-model) パターンを採用して、
画面の各操作に必要な複雑な待ち処理をカプセル化・ライブラリ化、
シナリオの実装の容易性・可読性・メンテナンス性を保つよう心掛けています。
【C#.NET】言語によって挙動が変わる

# はじめに
こちらは、Advent Calendar 2021 「ググって解決しづらかったこと」19日目の記事になります。

https://qiita.com/advent-calendar/2021/gseach

私が仕事の中で起きたググって解決しづらかったことについて書こうと思います。

よろしくお願いします。

# 環境
- Windows 10 
- Visual Studio 2022
- C# ( .NET 6.0 )

# ググって解決しづらかったこと
仕事の内容は、開発しているWebアプリで日本語や英語、韓国語、中国語などの各国の言語に対応させることです。
Webアプリ内でユーザーが言語を選択できる仕様で、この機能については問題なく追加することができました。

しかし、ここでおかしな現象が起きます。>< 
なんと、今までWebアプリ内で表示していたグラフなどのチャートの色が選択した言語によって、変わってしまうのです！（仕様ではどの言語も同じ色のチャートで表示します。）
言語を変えることでチャートの色が変わってしまうなんて、まったく想定できない問題でした。なにが原因なのか見当もつきません。
ただ明白なのは、各言語に対応させる機能を追加をしたので、言語機能周りが何か悪さしているということです。

ここから、ググってググってググってググってググって、やっと解決できました。本当にググって解決しづらかったな～と思います。やはり言語機能周りで問題は起こっていました。

# 原因
.NETでは、日付、数値、および通貨の書式設定など、言語に依存するとのことです...
自身で言語設定をしない場合は、デフォルトととしてWindowsで表示している言語が選択されるそうです。私の場合は日本語になります。
また、テキストの並べ替え順序、大文字と小文字の表記規則、文字列比較も言語に依存するそうです。

https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/localization?view=aspnetcore-6.0#supportedcultures-and-supporteduicultures

今回起きた問題では、四捨五入の計算で予期しない挙動をしていました。

```cs
double data = 0.25;

CultureInfo.CurrentCulture = new CultureInfo("ja-JP");
Console.WriteLine(Math.Round(data, 1, MidpointRounding.AwayFromZero)); // 0.3

CultureInfo.CurrentCulture = new CultureInfo("es-ES");
Console.WriteLine(Math.Round(data, 1, MidpointRounding.AwayFromZero)); // 0,3
```
上記のコードで、コメントアウトが出力結果です。

違いに気がつきましたか？？
なんと、日本語だと「0.3」、スペイン語だと「0,3」なんです。
「.」と「,」が違うんです！！！
色の透明度として関数に渡していた値でしたが、スペイン語だと「0,3」になり、引数の数がおかしいということでバグになってしまいました...。色はもちろん無効な色です...。

解決策として、カルチャに依存しない言語「InvariantCulture」というものを指定しました。これを使用することで、挙動を統一することができました。

https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.cultureinfo.invariantculture?view=net-6.0

# おわりに
ここまで読んでいただきありがとうございます。

起こった問題と原因がなかなか紐づかない内容だったので、最初はどのようにググったらいいのか、そこから難しかったです。
ここが悪さしているんじゃないか？と疑いながらコツコツと調べていくことで、最終的にはたどり着くことができたエピソードでした！
『わからない』を『使える』に変える言葉の理解の仕方

この記事は[リンクアンドモチベーションアドベントカレンダー2021](https://qiita.com/advent-calendar/2021/mcs)の21日目の記事です。

# 調べたけど、使えないをなくしたい

新卒一年目、エンジニア歴半年、新米エンジニアの坪井です。

早速ですが、新米エンジニアの方で、先輩の会話内に出てくる言葉がわからず
『ググってはみたけど、理解できたかわからない...』
『調べたけど、結局実務で使えるまで理解できていない...』
という経験をされている方はいませんか？

今回の記事はそんな方に向けた記事となっています。
記事を書くにあたっては、[知る、わかる、できる、教える（能力開発の４つのステップ）  | GLOBIS 知見録](https://globis.jp/article/5149)を参考にしています。

実際に、私はプロダクトチームに配属されてから、初めて聞く単語が多く、やみくもに、単語を調べているだけでした。
結果として、言葉の意味を「知る」だけで「業務で使える！」にはなっていませんでした。
この現象の裏には、表面上の理解で留まってしまっている事が原因にあると思います。

この記事では、言葉を「分からない→知る→分かる→使える」に変える方法を、4つのステップでお伝えします。



# Step1 日本語の意味をまずは、調べてみる
### 言葉の意味を知る。
そもそも、ITの分野で使われている言葉は、英語が多いです。
そのため、最初から言葉の意味を、理解することはそもそも難しいです。
なので、まずは言葉を和訳してみましょう！
慣れ親しんだ、日本語の意味から理解する事で、言葉そのものが持つ意味を理解する事ができます。

EX)デプロイ
日本語の意味：配備する・配置する

初めて聞いた時の私の脳内：デプロイ？？？？なんだそれ
和訳を知った私の脳内：何かを配備する事なんだなあ、

# Step2 実際に言葉の意味を調べてみる
###IT分野での言葉の意味がわかる
Step1で、言葉の根本的な意味を理解したので、
次は実際にITの分野でどの様な意味を持って使われている言葉なのか？
を調べてみます。

なぜその言葉が、ITの分野で調べた意味を持つ言葉なのか？が分かると思います。

ここまでのStepで、言葉を表面上で理解することができます！


# Step3 言葉を、視覚的に理解する
###言葉の概要を図示した物を活用する

ITの分野で使われる言葉は、システム上での働きを構造的に把握しないと、実務ではつかえません。
構造的な把握のために、効果的な手法は言葉の概要を視覚的に、理解することです。

構造的に理解するための手法としては、以下二つが挙げられます。
状況に応じて使い分けましょう！
1.自分で調べる場合は、単語を画像検索する
2.先輩から教えてもらう場合は、紙やホワイトボードを使って図示してもらう
　もしリモートでそんな機会を作れないよ...という場合はホワイトボードアプリを活用しましょう！ ex: ) [miro](https://aslead.nri.co.jp/whitepaper/lp/miro.html)


# Step4 自分の言葉で説明し、使えるに変える
###理解を、アウトプットする
最後に、ここまでで調べた内容をアウトプットします！

アウトプットにおいて重要なことは、以下三つです。
・場を決めておくこと
・自分の言葉で説明すること
・フィードバックを貰えること
　例)私の場合は、スラック上で先輩を含めた、学びを発信するチャンネルを作成し、そこでアウトプットしています。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337762/1d2acdf8-a440-57b5-be9f-13708f8f51d7.png)


アウトプットを実践することで、Step3までで理解した内容が自分の言葉で噛み砕くことに繋がり、結果として『言葉を使える』になると思います。



#最後に
記事を最後まで読んでいただき、ありがとうございました！！

色々書きましたが、私もまだまだ手探り状態で、毎日勉強中の新米エンジニアです。
もっといい方法あるよ！や、こっちの方法の方がいいんじゃない？
等あれば、どしどしコメントでフィードバックをお願いいたします！

一緒に、日々PDCAを回しながら成長していけたらと思います！
年末ラスト走り切りましょう！
新卒2年目から見た達人プログラマーの振る舞い

この記事は[Qiita Advent Calendar 2021](https://qiita.com/advent-calendar/2021/qiita)の 17 日目の記事です！
Qiita株式会社 CX 向上グループの花田（@ohakutsu）が担当します！

https://qiita.com/advent-calendar/2021/qiita

## はじめに

先日、社内のリードエンジニアの方から「達人プログラマー」という本を紹介してもらいました。

https://www.ohmsha.co.jp/book/9784274226298/

この本を読んで、実際に社内で活躍している **達人** たちが普段から行っていることがそのまま書かれている部分が多いなと感じました。
そこで、新卒 2 年目として実践すべきと感じたセクションについて紹介します。

## 達人プログラマーの振る舞い

本書では、ツールや設計に関することも書かれているが、この記事では **達人プログラマーとしての振る舞い** に絞って書きます。

達人プログラマーの振る舞いに関して以下のようなものが紹介されていました。

- Tip 1: 自らの技術に関心を持つこと
- Tip 2: あなたの仕事について考えること！
- Tip 3: あなたには現状を打破する力がある
- Tip 4: いい加減な言い訳よりも対策を用意すること
- Tip 5: 割れた窓を放置しておかないこと
- Tip 6: 変化の触媒たれ
- Tip 7: 大きな構想を忘れないようにすること
- Tip 8: 品質要求を明確にすること
- Tip 9: あなたの知識ポートフォリオに対して定期的な投資を行うこと
- Tip 10: 見聞きしたものごとを批判的な目で分析すること
- Tip 11: 日本語をもうひとつのプログラミング言語として考えること
- Tip 12: 伝えることがらと、伝える方法は車の両輪だと考えること
- Tip 13: ドキュメントは付け足すものではなく、作り上げるものである

## 振る舞いの中でも多くの達人に共通しているもの

達人プログラマーの振る舞いの中でも、以下の 5 つは特に社内で活躍している達人たちに共通していると感じました。

### Tip 1: 自らの技術に関心を持つこと

自分自身が使っている技術に対して関心を持っている。
このメソッドはどんな実装になっているのか？どうやって動いているのか？どんな考えの言語なのか？

社内の達人たちは **自分自身** を **自社** に置き換え、フロントエンド・バックエンド・インフラなどに縛られず関心を持っていると感じます。
自分の好きな分野に関心を持つことはそれほど難しくはありませんが、それを超えたものに関しても関心を持つことは難しいと思います。
ただ、それにとらわれることなく関心を持つことが達人であるのかもしれません。

### Tip 2: あなたの仕事について考えること！

常に考え続け、考えることをやめない。
自分は今何をやっているのか？なぜやるのか？どう改善するとよいのか？

社内の達人たちは、Qiita はどうなるべきなのか？それを達成するために自分は何をするべきなのか？を常に考えているように感じます。また、考えたことを実際に行動に移すこともしています。
考えることを諦めず、考えて考えて実践をし、また考え...を繰り返すことが達人であることなんだと思います。

### Tip 5: 割れた窓を放置しておかないこと

割れた窓（悪い設計、誤った意思決定、品質の低いコード）をそのままにせず、発見と同時に修復する。

社内の達人たちは、悪い設計やコードはコードレビューや周辺を実装する際に発見し、修復を行っているように感じます。もちろん、すぐに修復ができないものもあるとは思いますが、それを良い設計・コードへ近づけるような行動、実装は行なえます。また、悪い設計・コードに対してのセンサーが敏感です。
何が悪い設計・コードなのかを理解し、敏感になり、良い方向へ近づけることができることが達人なのだなと思います。

### Tip 10: 見聞きしたものごとを批判的な目で分析すること

なぜ？本当なのか？誰にメリットがあるのか？そもそも問題なのか？などと批判的な考え方をする。

> 常に考え続け、考えることをやめない。

と近いですが、なぜ？を繰り返し、表面ではなく核心の問題を見つけるよう考え続けています。
なぜそうなのか？この問題は本質的な問題なのか？核心はなんなのか？
達人たちは、日々関連書籍や情報などからインプットをし、自身の批判的な目を確立することによってなし得ているものなんだと思います。

### Tip 12: 伝えることがらと、伝える方法は車の両輪だと考えること

聞き手の能力・興味を理解し合ったタイミング・スタイルで伝える。また、相手の立場になって伝える・聞く。

自分が得意な技術、詳しく知っている情報を聞き手のレベル感にあった伝え方をしていると感じます。もちろん、いきなりそんなことはできないと思うので、聞き手のレベル感を理解しており、聞き手にあったスタイルを熟知していることによってできているのだと思います。
また、相手の立場になってどんなことを伝えたほうがいいのか？前提として必要なものは何か？を考え、伝えていると感じます。

## 最後に

社内の **達人** たちの多くに共通していることを言語化できました。（今回紹介していない Tip についても達人たちは日々当たり前のように行っています。）
僕はまだ新卒 2 年目ですが、達人になるための第一歩として上記の 5 つを意識して業務に励み続けます。

---

[Qiita Advent Calendar 2021](https://qiita.com/advent-calendar/2021/qiita)の 18 日目は、
Qiita株式会社 CX 向上グループ マネージャーの綿貫（@xrxoxcxox）が担当します！

ぜひ[Qiita Advent Calendar 2021](https://qiita.com/advent-calendar/2021/qiita)を購読設定して、明日の記事もご覧いただけると嬉しいです。
エラーハンドリングの心得

# 書くワケ
途中からアサインしたプロジェクトでのタスクで、外部ライブラリを使用した通信のエラーハンドリングで躓いたのがきっかけ。
これからエラーハンドリングを実装する際に必ず思い出したいがために書きます。

# エラーハンドリングとは
プログラムの実行中にエラーが発生した際に、すぐに実行を終了せず、あらかじめ用意しておいた処理を行うこと。

# 今回のエラーハンドリングの要件
ユーザーがこちらの意図しない特定の操作をした場合に、例外が発生し、通信が途切れ、それ以降は永久に繋がることはないのに何度も繋ぎ直そうとしてしまう。
↓
そのためその特定の操作が行われた際には、強制的に別の画面へ遷移させたい

#1 何を防ぎたいのか？を明確にする
エラーハンドリングを実装する際には、必ず明確に「〜を防ぎたい」「〜が起こらないようにしたい」といった目的があるはずです。
しかし、ここが曖昧、または広義になってしまっている場合には注意が必要です。

今回のエラーハンドリングの要件の場合、下記の様に実装してしまうのは危険です。

```typescript
// 省略
const connect = (): void => {
    // 色々省略
    
    //接続に成功していないのに通信しようとして例外が起きてるな...
　　　　　　　　//よしここに分岐入れて接続に成功していない場合は強制的に画面遷移させよう
    if (connectId) {
        //接続に成功した場合の処理
    } else {
        // 失敗した場合には画面遷移
        window.location.href = '/home'
    }
}
// 省略
```

上記は実際に僕がエラーハンドリングを実装する際にやってしまった手法です。

上記の防ぎ方の何が問題なのか？
先に申し上げておくと、問題ではないパターンもあるんです。
接続に成功している場合には、成功した処理、失敗した場合には、それに応じた処理を書くのは、おかしいことではないと言えます。

それを踏まえた上で、このエラーハンドリングが問題であると断定する前提条件は、__上記コードの分岐がその特定の操作が行われた場合にのみfalse判定されるわけではない__ということです。

####問題点その１ 上記で挙げた特定の処理意外にもここに引っかかる可能性があることを考慮できていない
そもそもこのエラーハンドリング実装の理由は、ユーザーに__特定の操作__をされた際に発生する、再接続の無限ループが起こらない様にするという要件です。
しかしこれでは、通信が、他の理由で失敗した際にも、elseに入ってしまい、想定していた正常なリトライも行えなくなる可能性があります。
上記の分岐は__ユーザーに特定の操作をされた際にのみfalseになるわけではない__判定だったのです。

####問題点その１ エラーの拾い方が広義すぎる場合、他のエラーを握りつぶしてしまう
上記とほぼ似たような内容ですが、特定の処理の際にのみelseになるわけではないので、他のエラーを握りつぶしてしまう可能性があります。
本来はキャッチすべきエラーも握りつぶされてしまい、問題が起きた時も直すべきところに当たりをつけるのが困難になる可能性があります。

##対策

__防ぎたい事象の時のみ通る場所を作ってあげる__

```typescript
// 省略
const connect = (): void => {
    // 条件を追加し、特定の事象は後続の処理へ行かない様に修正
    if (!connectId && isUnableConnect) window.location.href = '/home'

    //省略
}
// 省略
```
条件を追加し、ユーザーに特定の操作を行われた場合以外は、false判定されない様に修正しました。

# 2 外部ライブラリが絡むエラーハンドリングを実装する際には、無理矢理ロジックで解決しようとせず、ドキュメント等を読み特定のエラーをキャッチできるイベントがないかを探す

ライブラリ等を使用することにより、使い手は細かいことを気にすることなく、機能を「動かす」ことができます。
しかし、ライブラリを組み込んだ際のエラーハンドリングはきちんとできているのでしょうか？

僕が今回実感した外部ライブラリを使用する際のエラーハンドリングで一番大切なことは、__公式ドキュメントを読むこと__です。
当たり前です。当たり前なのですが、初心者ほど、誰かが噛み砕いてくれた記事を一生懸命探してしまおうとしませんか？僕もその1人です。

ログを追い、「ここで処理が止まっている！」と該当箇所を見つけた興奮さながらに、そのままそこにロジックを足して、「よし！動いた！」と安堵するのは安直すぎます。

まず、理解していないライブラリであれば、公式ドキュメントを読みましょう。

今回僕がエラーハンドリングを施そうと考えた処理に関わっていたライブラリは、SkyWay JavaScript SDKというものです。
https://webrtc.ecl.ntt.com/api-reference/javascript.html#events

上記のリファレンスを参照したところ

・エラーが発生した際に発火するイベント
・エラーの判別方法

までしっかりと明記されています。

これのおかげで「この処理で〜なるということは、こう！」とはっきりと断言できる実装となりました。

# 最後に
エラーハンドリングはアプリケーションには確実に必要なものだが、実装の仕方を誤ると、エラーを握りつぶしてしまったり、機能追加の際に、余計な手間がかかったりしてしまいます。
エラーハンドリングを実装する際には、今自分がキャッチしたい特定のエラーのみを拾う様にする。
取りこぼしなく広義のエラーハンドリングを実装したい場合には、その意図をコメント等に残しておけば、次に見た人が「エラーを広く拾っているな」と直感的に理解することができるため、上記のデメリットを克服できると考えます。
もう怖くないSpring × Junit5 ~後編~

[もう怖くないSpring × Junit5 ~中編~](https://qiita.com/sho-yamashita/items/ec763cbb1924552ad112)からの続き

## モックを使ったテスト
### Mock?モック？ハンモック？
モックとは、あるクラスのメソッドが呼ばれたときの返却値を予め決めておくことで、
そのメソッドの処理をいちいち再現せずに、テストしたいクラスのテストを可能にしてくれる仕組み

![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/bb195ff4-fe32-9aa4-a040-7fd7b4bcf91f.png)
引用）https://to-education.hateblo.jp/entry/2019/06/20/210558

### Mockito
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/b5903412-e637-ebaa-79f3-82d394d25a30.png)

### 実際モックのコードってどんな感じなの？
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/d6d1b31e-105d-0b36-2227-38b21e025486.png)

### mockitoって二種類あるよ
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/f123a858-12b2-0b6c-a88c-1122a3477f3f.png)

### モックをつかったクラスの使い分け
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/4c1310e2-60e5-db43-a730-01b182ca04a7.png)

### モックの振る舞いの変え方①(何も結果を返したくない場合）
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/1a158e0f-76e1-1f0e-3e37-1452905e95d0.png)

### モックの振る舞いの変え方②(引数に依らず何か結果を返したい場合）
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/2b6884db-c574-acfc-c88b-3f9bf4af260b.png)

### モックの振る舞いの変え方③(引数に応じて何か結果を返したい場合）
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/c60e6321-139f-8b43-d532-884e71a82406.png)

### オブジェクトの定義方法って三種類あるよ。
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/fa07d589-8fa9-c6b5-362f-800c1146dfe8.png)

## Springの起動が必要なテストの実行方法
springの起動が必要なテストの場合は、実行時のプロファイルを環境変数に
渡してあげる必要があります。
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/b2c4a02a-17da-1a2a-8e0e-3c643d35e3fa.png)
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/c2bbe1bd-0a6d-4442-04ec-88e441dea67d.png)
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/ac33e4fd-4788-43bb-4f4d-c1c0323fe7cd.png)

## 最後に
[もう怖くないSpring × Junit5 ~前編~](https://qiita.com/sho-yamashita/items/eb1dad4139b322ca722f)
[もう怖くないSpring × Junit5 ~中編~](https://qiita.com/sho-yamashita/items/ec763cbb1924552ad112)
[もう怖くないSpring × Junit5 ~後編~](https://qiita.com/sho-yamashita/items/c7e520c12f9113798275)
三部作でしたがいかがでしたでしょうか？

![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/cbc3ccf2-0680-1e96-9e69-5021659438f0.png)
git submoduleを使うときの私的メモ

git submoduleを使おうと調べたときに，古い情報が混ざっていて困ったので，備忘録的に整理．

[git submoduleの解説](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-%E3%82%B5%E3%83%96%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB)

他のgitリポジトリを参照する方法の一つ．自身のリポジトリで，サブディレクトリとして他のgitリポジトリを扱えるようにする．追加されたgitリポジトリをサブモジュールと呼ぶ．

リポジトリとは言っているが，特定のコミットを指している．大元のリポジトリが更新されても，自動的に追従はしてくれない．

# 他のgitリポジトリの追加

```
git submodule add 参照したいリポジトリのURL
```

# サブモジュールを含むリポジトリのクローン

```
git clone --recursive リポジトリのURL
```

# 更新の追従

サブモジュールを更新する．

```
git submodule update --remote 
```

更新時に変更をマージする場合には

```
git submodule update --remote --merge
```

を実行する．

このとき，サブモジュールは特定のコミットを指した状態のままなので，サブモジュールのディレクトリ（名前はサブモジュールと同じ）に移動してmainブランチに切り替える．

```
cd サブモジュール名
git switch main
```

リポジトリのルートに戻り，サブモジュールの変更をマージする．

```
cd ..
git add サブモジュール名
git commit -m "コミットメッセージ"
```

GitHubで管理している場合はpushする

```
git push origin main
```
yarn add cypress が失敗する




`yarn add -D cypress` が失敗するようになってしまいました。


```
yarn add -D cypress

中略

Installing Cypress (version: 9.1.1)

[STARTED] Task without title.
The Cypress App could not be downloaded.

Does your workplace require a proxy to be used to access the Internet? If so, you must configure the HTTP_PROXY environment variable before downloading Cypress. Read more: https://on.cypress.io/proxy-configuration

Otherwise, please check network connectivity and try again:

----------

URL: https://download.cypress.io/desktop/9.1.1?platform=darwin&arch=x64
Error: read ECONNRESET

----------

Platform: darwin-x64 (20.6.0)
Cypress Version: 9.1.1
[FAILED] The Cypress App could not be downloaded.
[FAILED] 
[FAILED] Does your workplace require a proxy to be used to access the Internet? If so, you must configure the HTTP_PROXY environment variable before downloading Cypress. Read more: https://on.cypress.io/proxy-configuration
[FAILED] 
[FAILED] Otherwise, please check network connectivity and try again:
[FAILED] 
[FAILED] ----------
[FAILED] 
[FAILED] URL: https://download.cypress.io/desktop/9.1.1?platform=darwin&arch=x64
[FAILED] Error: read ECONNRESET
[FAILED] 
[FAILED] ----------
[FAILED] 
```


調べたところ、同様の現象になってしまった人は他にもいるようでした


[The Cypress App could not be downloaded (Can't install via NPM I on WINDOWS 2012) · Issue #6315 · cypress-io/cypress](https://github.com/cypress-io/cypress/issues/6315)

[When downloading 2 versions of Cypress simultaneously, one clobbers the other resulting in nondescript error and exit · Issue #4595 · cypress-io/cypress](https://github.com/cypress-io/cypress/issues/4595)




## node_modulesの下

node_modulesの下にはcypressがいるので、add自体が失敗しているわけではなさそうでした。

![スクリーンショット 2021-12-16 20.08.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/8cf159de-3c5d-2089-b7ca-493ebed713ae.png "スクリーンショット 2021-12-16 20.08.21.png")


Cypress Runを行うと以下のようなメッセージが表示されました。

```
No version of Cypress is installed in: /Users/xxxx/Library/Caches/Cypress/9.1.1/Cypress.app

Please reinstall Cypress by running: cypress install

----------

Cypress executable not found at: /Users/xxxx/Library/Caches/Cypress/9.1.1/Cypress.app/Contents/MacOS/Cypress

----------

Platform: darwin-x64 (20.6.0)
Cypress Version: 9.1.1
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
```



もしかしたら、Cachesの下にバイナリを置くとうまくいくかもしれない


## バイナリ

以下からバイナリをダウンロードしました。

https://docs.cypress.io/guides/getting-started/installing-cypress#Direct-download


ダウンロードした`Cypress.app`を`Caches`の下に配置します。

```
mkdir ~/Library/Caches/Cypress/9.1.1
mv Cypress.app ~/Library/Caches/Cypress/9.1.1/.
```




### yarn

yarnしてみます。

```
# yarn
yarn install v1.22.17
[1/4] 🔍  Resolving packages...
success Already up-to-date.
✨  Done in 0.81s.
```

成功しました！！

### Cypress実行


```
yarn cy:run
yarn run v1.22.17
$ cypress run
It looks like this is your first time using Cypress: 9.1.1

✔  Verified Cypress! /Users/atsu/Library/Caches/Cypress/9.1.1/Cypress.app

Opening Cypress...
```

無事に起動しました！

なかなか罠でしたが、無事に稼働して一安心です。
なぜ、`Caches/Cypress/9.1.1/`が消えてしまっていたのかは謎なので、引き続き注視していきます。
Windows PCで添付ファイル付きのMBOXをPSTに変換する方法は？

最高のMBOXからPSTへのコンバーターをダウンロードして、ワンクリックでMBOXをPST形式にバッチ変換します。 添付ファイル付きでMBOXをPSTに簡単に変換し、MBOXをOutlook 2016、2013、2010、2007などにインポートできます。<b><a href="https://www.zooksoftware.com/ja/mbox-to-pst/">ZOOK MBOXからPSTへのコンバーター</a></b>をダウンロードし、データを失うことなくMBOXをPST形式にエクスポートするだけです。 これは、ユーザーが1つのプロセスで添付ファイルとともにMBOX電子メールをPST形式に抽出できるようにする最も愛らしいソリューションです。 このツールを使用すると、ユーザーは、Mozilla Thunderbird、Eudora、Entourage、および20以上のMBOXベースの電子メールクライアントなど、電子メールクライアントをサポートする任意のMBOXのMBOXファイルを変換できます。 さらに、このツールは、ユーザーが数回クリックするだけでMBOXをPST形式にバッチエクスポートできる高度な機能で構成されています。 全体として、これはユーザーがワンクリックで添付ファイルとともにMBOXをPSTに変換するための直接的で簡単なソリューションです。
<h2>MBOXからPSTへのコンバーターの最高の属性</h2>
1. 単一のプロセスでMBOXをPSTファイルに一括変換します。
2. 添付ファイルやその他のデータ項目を使用して、MBOXをPSTに完全に変換します。
3. 同じフォルダ構造を保持して、MBOX電子メールをPST形式で保持することができます。
4. ツールのユーザーフレンドリーなインターフェースは、技術者以外のユーザーに適しています。
5. MBOXメールのデータ整合性とRTF構造を維持します。
6. すべてのMBOXベースの電子メールクライアントのMBOXファイルを完全にサポートします。
7. MBOXファイルをPST形式に変換するための直接オプション
8. ツールの動作をテストするために、MBOXからPSTへのコンバーターの無料トライアルが利用可能です

<h2>MBOXをPSTファイルに変換する簡単な手順</h2>
1. MBOXからPSTへのコンバーターをダウンロードしてインストールします。
![zook-software.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188983/2e0b5eb8-972a-113c-d660-e5e0b343e60f.png)

2. システムからMBOXファイル/フォルダを選択します。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188983/a901f5a6-fd8a-dba2-d735-a02c80923bc6.png)

3. 目的地を参照して選択します。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188983/ed1ba334-398a-a4ea-e826-4eaebb552b5f.png)

4. 変換ボタンを押します。
![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188983/40f28788-4b44-7397-ceca-f13a39066220.png)
学生時代に死にそうになった話

体育大学で、野外活動のゼミに入り３回くらい死ぬかもしれないと思った出来事がありますので、記載します。

## １回目
雪山で、かまくらを作りそこで一晩寝るというゼミ活動がありました。
今日泊まる家を自分で作ったことってありますでしょうか？
作らなければ、寝る家がないのです。
そして、作ったとしても崩れないか心配で寝れるかも分からないのです。
<img width="300" alt=iOS の画像 (6).jpg src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2397810/0fed3de6-dd25-0915-9b0f-bb77d64573f4.jpeg> <img width="300" alt=iOS の画像 (6).jpg src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2397810/1b289525-2c71-2b56-263f-9ccafad1b0fa.jpeg> 


一応、無事翌朝を迎えました。

## ２回目
スキューバダイビングでリップカレントというのにあいました。
波が引く時に集中する場所があって、そこに巻き込まれ、上と下がどっちかわかんないくらい、クルクル体が回転しながら流され続けました。
全員で手を繋いでたので、余計に抵抗を強めているということで、
3人ずつに分かれる指示があったぽいけど
把握できてないままに…
隣の人に手を離されて、裏切られたーと思っているうちに、
集中ポイントから外れて助かりました。
<img width="300" alt=iOS の画像 (6).jpg src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2397810/74f54bba-66d1-2fda-04f9-1e58decca36c.jpeg>　<img width="300" alt=iOS の画像 (6).jpg src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2397810/325b0f6c-6503-284a-17e1-4e99ebc27ca2.jpeg>  


酸素も残りわずかで、本当に死ぬかと思いました。

## ３回目
乗鞍岳登山で水の計算間違えて、ジャンケンで負けた2名が山頂付近まで頑張って登り、雪解け水を取ってくる話になりました。
案の定、じゃんけんに負けて山頂付近まで行く途中、雷鳥もとんでてカミナリゴロゴロでカミナリが右から左に流れる瞬間を見てしまいました。
カミナリって上から下だけじゃないんだね！
<img width="300" alt=iOS の画像 (6).jpg src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2397810/7c0e3024-d6e5-cc6b-643c-b949099db6a6.jpeg> <img width="300" alt=iOS の画像 (6).jpg src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2397810/93c8bac2-0033-2361-0d9f-2255ed0dcbbf.jpeg> 






これは、ビックリしただけで、
死なないかもしれないけど、カミナリ直撃したら死ぬなと思った次第でした。


## 自然から学んだこと
日常は、当たり前ではないということ
例えば、蛇口をひねれば水が出るのは、とても幸せであるということ
少しでも自分の環境を良くしたいなら、自ら考え行動しなければ死ぬこと

## ゼミから学んだこと
ピンチの時は仲間と助け合わなければ死ぬこと。
人との出会いで人間は変われること。


## 番外編
キャンプや会社で使えるイニシアティブゲームをご紹介！

### イニシアティブゲームとは
>イニシアティブゲームは、小グループ（５～１０人）が、１人では解決できない精神的・身体的課題に対して、一人一人が持っている諸能力を出し合い「知恵」と「勇気」と「協力」のもとにその課題をグループで解決する活動です。望ましい社会性や問題解決能力、リーダー性を育てるのに有効なゲームです。
チームが協力しあわなければ達成できないゴールが設定されたゲームのことです。


人間知恵の輪
https://youtu.be/YqRXHgZ4WbA

ブラインドスクエア
https://youtu.be/oVfek6iQunI

ラインナップ等々その他色々
http://scout.o.oo7.jp/insiarugeimu.pdf

是非、チームワーク力を試してみてください！

最後に、大自然相手でチームワークが乱れると本気で死にます！！


井口でした。
もう怖くないSpring × Junit5 ~中編~

[もう怖くないSpring × Junit5 ~前編~](https://qiita.com/sho-yamashita/items/eb1dad4139b322ca722f)からの続き

## JUnitのいろんな機能
### 例外の検査
例外のチェックが簡単にできます
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/3ca43357-c0a6-813f-251d-67b566c8ba3a.png)
### 複数の値で同じテストする（パラメーター化テスト）
複数のテストを作らなくても一つのテストで境界値テストできます
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/9bcfeb20-15e1-3e89-7ede-2794f4b68f45.png)
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/bf426ac9-27b6-734b-e905-d5cb47a2192e.png)
### テスト結果の補足
テスト結果の表示を整形できます
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/8cb3e367-a773-0f42-23c5-85a2ce208d18.png)
### テスト構造化（ネスト化）
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/e3943cc2-fd1e-4c53-74f8-740b4c07076e.png)
### テストの前に初期化したいとき
テスト内に使う変数等を初期化する場合以下のようなアノテーションを使います。
それぞれの実行順は以下の通りです。
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/ea0f79ed-cd4a-0dd9-f783-1497f84bb6af.png)
引用）https://mike-neck.hatenadiary.com/entry/2017/01/01/230927

具体的には以下のように使います
![もう怖くないspring×Junit5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/119c0b62-e7fa-e8af-d8a4-d9683e5d3bbd.png)

## 最後に
[もう怖くないSpring × Junit5 ~後編~](https://qiita.com/sho-yamashita/items/c7e520c12f9113798275)につづく
Mac を遅くしている ReportCrash を停止する方法 ～ Chrome が固まる原因かも！？

最近 Mac (macOS Big Sur) が妙に重くなっていて「アクティビティモニタ」（[ユーザーガイド](https://support.apple.com/ja-jp/guide/activity-monitor/welcome/mac)）を見たら ReportCrash が大量に CPU を消費していました。本当の原因（人によって原因は様々でしょう）は Chrome 関連のコンポーネント[^1]のようでしたが、**実害をもたらしている張本人は ReportCrash** なのでこれを停止しました。この方法は `man ReportCrash` （[参考](https://www.unix.com/man-page/osx/8/ReportCrash/)）に書いてあるので公式の方法と考えて良いでしょう。

## ReportCrash を停止させる方法

「ターミナル」アプリを起動（[詳細](https://support.apple.com/ja-jp/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)）して以下の二つのコマンドを実行するだけです。
（⏎ は enter キー。`sudo` ～ の行を実行するとログインパスワードを聞かれます。）

```sh
launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist ⏎

sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist ⏎
```

## ReportCrash を有効に戻す方法

元に戻したい場合は以下の二つのコマンドを実行します。

```sh
launchctl load -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist ⏎

sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist ⏎
```

[^1]: `/Library/Logs/DiagnosticReports/` にあるログを見てみると Google Drive だとか Google Chrome だとか Visual Studio Code（つまり Electron）とか Chrome (Chromium) 関連のコンポーネントを使っているアプリのログがありましたが、そんなこと言われても自分で修正できるわけもなく Chrome 関連のアプリは表面上は問題なく動いています。自分で開発したアプリのクラッシュする原因を調査したいのでないなら ReportCrash は必要ありません。
UIデザイナー１年目のお悩み別ハンドブック


この記事は、シアトルコンサルティング株式会社 Advent Calendar 2021の21日目の記事です。

## はじめに
こんにちは！
シアトルでUIデザイナーとして、ネイティブアプリの開発に携わっている藤原です！

本格的にUIデザイナーになって、１年が経ちました。

今回は、もともとWEBデザイナーだった私が、
この１年UIデザインに関わってきてインプットしたものや、
仕事で困ったときに参考にしたものを、逆引きでまとめてみました。


## アイデアに行き詰まった
デザインを作成していて、うまくアイデアをまとめられず手が止まる、、といったことありますよね。
そんな時は意識的にインプットとアウトプットの量を増やすようにしています。

###　1.参考サイトを漁る
SignUpなどユーザーのアクションから、Buttonなどのパーツ単位まで、
UIデザインが１５０以上にカテゴリ分けされているサイト。

機能は決まっているけど、どんなデザインにすればいいか悩むときに使っています。

https://collectui.com/designs

アクション別にいろんなアプリの導線がまとめられているサイト。
画面ごとのキャプチャがあり、いちいち携帯でアプリを見なくても、
導線を知ることができるので便利です。

オンボーディングとか、実際のアプリで何度も見ることができないものが、
こうしてまとめられていると使いやすいですね。

https://www.uxarchive.com/


###　2.とにかく紙に描き出す
調べたものをただ眺めるだけでなく、良いなと思ったパーツを紙に描き出すようにしています。
それを元に簡易的なラフを描いてみると、UX観点の抜け漏れが見つかることもよくあります。

## デザインの意図の説明がうまくできない
デザイナーは作ったものをディレクターやエンジニアに向けて説明することもありますが、
デザインの意図をうまく伝えるのって難しいですよね。
意図を説明するための根拠を、どこから引用するかが重要になってくると思います。

###　1.「UXデザインの法則」を読む
意図がうまく説明できないときは、デザインを論理的に理解できていないことが多いです。

「UXデザインの法則」は心理学に基づいた法則がまとめられており、
事例も多く載っているので、理解しやすい内容になっています。

実際のデザインの説明をする際にも、この事例を紹介しながら、
なぜこのデザインにしたのか？を説明しやすくなります。

https://www.amazon.co.jp/UX%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%81%AE%E6%B3%95%E5%89%87-%E2%80%95%E6%9C%80%E9%AB%98%E3%81%AE%E3%83%97%E3%83%AD%E3%83%80%E3%82%AF%E3%83%88%E3%81%A8%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E5%BF%83%E7%90%86%E5%AD%A6-Jon-Yablonski/dp/4873119499

###　２.ユーザビリティテストをしてみる
どうしてもプロダクトチームだけでアプリを作り上げてしまいがちですが、
実際のユーザーの声を聞くと、１つの判断軸が生まれます。

「ユーザビリティテストでこんな結果が出たので、
こちらのデザインの方がユーザーにとって良い体験を作れる」といった説明もできます。

また、実際ユーザビリティテストをしてみると
想定外のところでユーザーが操作につまづいたり、
こちらが考えていたフローで操作をしてくれなかったりするので、検証の重要性を感じます。

https://nijibox.jp/blog/usability_test1/


###　３.Google UX Designプロフェッショナル認定を受ける
GoogleがUXデザイン初学者向けに出している講座です。
カスタマージャーニーマップなどのフレームワークから、
Googleの考えるUXデザインまで、UXデザインのプロセスを学ぶことができます。

https://www.coursera.org/professional-certificates/google-ux-design

私は一人では続かないタイプなので、
知り合いのテックリードの方と一緒に朝活で勉強しています。

その場で講義の感想を共有できたり、
自分のプロジェクトの取り組みについて話ができるのでおすすめです！



## コンポーネントへの理解が浅い
大きなサービスのデザインになると、デザインシステムが導入され、
作ったパーツをコンポーネントでまとめておくことも必要になるかと思います。


###　１.Figmaを使いこなす
プロジェクトによってはXDでデザインを作っているところも多いと思いますが、
Figmaを１から触ってみるのはすごくおすすめです。

コンポーネント管理がしやすいということで
各企業もXDからFigmaに乗り換えることが多く、今が学びのチャンスともいえます。

こちらの講座では、Figmaの使用方法からファイルの整理の仕方まで、
丁寧に教えてくれるので、実際にものを作りながら理解することができます。
セールだと２０００円ほどなので、お得に勉強できます。

https://www.udemy.com/course/figma-app-design/

###　２.他社のデザインシステムを見まくる
最近、Figmaのコミュニティ上でデザインシステムを公開する企業が増えています。

これまでデザインシステムといえば、HIGやGoogle Materialデザインでしたが、
Figmaでは実際のデザインデータが見れるので、非常に勉強になります。

https://www.designsystemsforfigma.com/

## まとめ
いかがだったでしょうか？
少しでもUIデザイナーとして行き詰まった時の参考になると嬉しいです。

私自身もまだまだ課題が多くあり、プロジェクトをうまく進めることは難しいなと感じているので、
「こんな風に工夫しているよ！」というノウハウもお待ちしています。
デザイナーみんなで成長できる環境を作っていけたらいいなと思います！


## 参考
https://monstar-lab.com/dx/solution/uiuxdesign-reference/
https://note.com/fladdict/n/n97d74e754bc4
https://goodpatch.com/blog/i-love-design-systems
水匠５を macOS にインストールする

ちょっとインストールに手間取ったのでメモ。

まずは、たややんさんが公開されているファイルをダウンロードしてくる。

https://twitter.com/tayayan_ts/status/1463107309492531202

https://t.co/H2oVB14vqs

zip 形式なので、ダブルクリックで解凍されるはず。
次に、同梱されている `source.rar` を解凍するために unar を入れる。

```bash
brew install unar
```

unar で `source.rar` を解凍する。

```bash
cd ~/Downloads/水匠5
unar source.rar
cd source/source
```

`Makefile` をいじる。私のは Intel mac なので ZEN2 をコメントアウトして、AVX2 を有効化する。

```makefile
# --- Intel/AMD系 (x86/x64 Platform)
#TARGET_CPU = AVX512VNNI
#TARGET_CPU = AVX512
TARGET_CPU = AVX2
#TARGET_CPU = SSE42
#TARGET_CPU = SSE41
#TARGET_CPU = SSSE3
#TARGET_CPU = SSE2
#TARGET_CPU = NO_SSE
# --- AMD Ryzen
#TARGET_CPU = ZEN1
#TARGET_CPU = ZEN2
#TARGET_CPU = ZEN3
# -- ARMとか
#TARGET_CPU = OTHER
#TARGET_CPU = GRAVITON2
```

`libstdc++` だとコンパイルされないので `libc++` に変更する。

```makefile
# clang用にCPPFLAGSなどを変更
ifneq (,$(findstring clang++,$(COMPILER)))
	# stdlib
	CPPFLAGS += -stdlib=libc++

	# C++17のfilesystem
	# LDFLAGS += -libc++fs

	# 関数の引数が関数本体で使われていないときに警告出るのうざすぎるので抑制。
	CPPFLAGS += -Wno-unused-parameter

	# static リンクを行う際に __cxa_guard_acquire __cxa_guard_release の生成を抑止
	#   undefined reference to `__imp___cxa_guard_acquire'
	#   undefined reference to `__imp___cxa_guard_release'
	# static 変数を初期化したかを pthread_mutex_t でロックを取って確認し、
	# 最初の実行なら初期化するスレッドセーフなコードを生成するためのもの。
	# → 本当に消してしまっても大丈夫か？
	WCPPFLAGS += -fno-threadsafe-statics
```

このままだと clang を使っているのに、出来上がる実行ファイル名が `Yaneuraou-by-gcc` になってしまうので、好きな名前に変更する。

```makefile
TARGETDIR = .
ifeq ($(OS),Windows_NT)
	CPPFLAGS += $(WCPPFLAGS)
	LDFLAGS += -static -Wl,--stack,25000000
	TARGET = $(TARGETDIR)/YaneuraOu-by-clang-avx2.exe
else
	ifeq (${OS},wasm)
		TARGET = $(TARGETDIR)/yaneuraou.js
	else
		CPPFLAGS += -D_LINUX
		TARGET = $(TARGETDIR)/YaneuraOu-by-clang
	endif
endif
```

ビルドする。

```bash
make tournament
```

`make normal` と何が違うのかはよく知らない。
できあがった実行ファイルを起動すれば動く。

```bash
./Yaneuraou-by-clang
usi
isready
go infinite
stop
quit
```

評価関数だけをファイルとして入手したい場合は平岡さんのこれ https://github.com/HiraokaTakuya/get_suisho5_nn を参考にすると良い。
【React×Dexie】LiveQueryを利用した、リアクティブなIndexedDB

この記事は [N・S高等学校 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/n-s-highschool-1) の16日目です。

## はじめに
本日、12月16日の記事は私、N高横浜キャンパス5期生の渡邊智晴（Slack: ＠とも）が担当させていただきます。予定では、今年の成果的なのを書く予定だったのですが、諸事情がありボツになっていまいました。そのため予定を変えて、私が今イチオシしているライブラリをご紹介したいと思います。

## React×Dexie
みなさんは、Reactのグローバルな状態管理をどうされていますか。hooksのcontextで頑張る方法もあれば、reduxやrecoilなどのライブラリを利用する方法もあります。その中で、DexieのLiveQueryを利用するという新たな選択肢が出てきました。

### Dexie
そもそもDexieとは、IndexedDBをラップしたライブラリです。これを使うことで、Webフロントで非同期なRDB的なものを作成することができます。TypeScriptにもバッチリ対応しており、補完などを含めた使い勝手も上々です。

### LiveQuery
そして、Dexie v3.2.0 でLiveQueryという機能が追加されました！
これを使うことで、DBへの参照を**リアクティブ**にすることができます！

## DBを定義してみる
ここでは、Dexieのチュートリアルを改変したものを利用します。

```typescript:db.ts
import Dexie, { Table } from 'dexie'

export interface Friend {
  id?: number
  name: string
  age: number
}

export class MySubClassedDexie extends Dexie {
  // テーブルの型を定義
  friends!: Table<Friend>

  constructor() {
    // IndexDBでの名前を設定
    super('myDatabase')

    // DBの初期化
    this.version(1).stores({
      friends: '++id, name, age'
    })
  }
}

export const db = new MySubClassedDexie()
```

### 解説
typescriptでDexieを利用するには、classを継承してDBを作成するのが一般的です。これによって、型を継承しつつTable周りの型を定義できるため、DBを利用する際もほぼ完璧に型が当てられます。しかし、継承は型を引き継ぐという意味合いが強く、DBとの接続・初期化などのロジックは、普通にconstructorの中で手続き的に行われています。

## DBの内容を表示してみる
```tsx
import { useLiveQuery } from "dexie-react-hooks"
import { db } from "./db"

// DBで定義したFriendsを、一覧表示するコンポーネント。年齢での範囲絞り込み可。
export function FriendList({ minAge, maxAge }: { minAge: number, maxAge: number }) {
  const friends = useLiveQuery(
    async () => {
      //
      // DBをクエリする
      //
      return db.friends
        .where('age')
        .between(minAge, maxAge)
        .toArray()
    },
    // クエリ時に依存する値
    [minAge, maxAge]
  )

  return (
    <ul>
      {friends?.map(friend => (
        <li key={friend.id}>
          {friend.name}, {friend.age}
        </li>
      ))}
    </ul>
  )
}
```

### 解説
DBの取得では、新たに追加された**useLiveQuery**を利用しています。使い方としては、第1引数はdbをクエリする関数を、第2引数ではuseEffectのような依存値が入ります。そして、返却値はuseStateの1つ目のような形で、リアクティブな値としてコンポーネント内で使えます。クエリ時のDBのアクセスは、O/Rマッパーのように`db.[テーブル名].~`という形で行えます。

## DBを追加・更新・削除してみる
クエリ時と同じように、`db.[テーブル名].~`という形で行なっていきます。表示側でLiveQueryを利用している場合は表示更新を自動で行ってくれるため、本当に操作をするのみで問題ないです。ここでは、それぞれ簡単な例をご紹介します。

```typescript
/*** 追加 ***/
const id = await db.friends.add(
  { name: "new user", age: 16 }
) // idを自動設定する際は、返却値がidとなる。

/*** 更新 ***/
await db.friends.update(id, { age: 17 })

/*** 削除 ***/
await db.friends.delete(id)
```

## おわりに
React×Dexieによるグローバルな状態管理、いかがだったでしょうか。
LiveQueryがリリースされたことで、ReactとIndexedDBの連携が一気に現実的なものになりました。Dexieは使い勝手の良さからも、Reactのグローバルな状態管理の選択肢として、十分な機能を備えていると思います。
そして、Dexieにはまだまだ沢山の機能があります。個人的には、特にDexieのオンライン同期機能に注目をしています。こちらの記事は、また後日Qiitaに投稿する予定ですので、しばしお待ちください。
この記事が、Dexieに少しでも興味をもつきっかけになれば幸いです。最後まで読んでくださり、ありがとうございました。
【Python】turtleを使って☆星マークを記述

Pythonとturtleと使って星マークを記述するコード。

## 実装コード1

```python
from turtle import *

for i in range(10):
	forward(100)
	if i % 2 == 0: left(72)
	else: right(144)
done()
```

## 実行結果1
![スクリーンショット 2021-12-16 19.45.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522445/1896ae5a-69b3-2494-3e48-a03364ccec11.png)

＊クロスさせないタイプの星型の図形です。

## 実装コード2

```python
from turtle import *

for i in range(5):
	forward(100)
	right(144)
done()
```

## 実行結果2
![スクリーンショット 2021-12-16 19.50.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522445/8a7aa878-0d1e-2552-da2b-1ac8c695a50b.png)

＊クロスさせるタイプの星型の図形です。

## Pythonのお役立ち情報

https://wagtechblog.com/programing/python-school

https://wagtechblog.com/programing/ai-develop-school
AWSでrailsを使うときの環境設定

AWSのCloud9で環境設定をする方法についてまとめました。
手っ取り早く環境設定したい人向けなので、コマンドの意味などは省略してあります。

#コマンド
```
$echo "gem: --no-document" >> ~/.gemrc
```

```
$gem install rails -v 6.0.3
```

```
$gem install bundler -v 2.2.17
```

これだけです。Cloud9を利用しているのでとても簡単に環境構築ができますね。
あとは`rails new`を実行すればOKです。

```
$rails _6.0.3_ new app_name
```
Apacheのhttpclientを利用してServiceNow REST API（ Table API）をJavaでたたく方法

# 前記事
https://qiita.com/seino-ta/items/fe04d5cf71f126583774

ここではJavaのプレーンなものでGETを実行しました。

# Apacheのhttpclientを利用してGETを実行

```Java 
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;

public class App {

    public static void main(String[] args) throws ClientProtocolException, IOException {
        getMethodByApache();
    }

    private static void getMethodByApache() throws ClientProtocolException, IOException {
        // ユーザーIDやパスワードは適切なものに書き換えてください
        String user = "admin";
        String pass = "xxxx";
        // URLは適切なものに書き換えてください
        String url = "https://xxxxxxx.service-now.com/api/now/table/incident?sysparm_limit=1";

        HttpGet request = new HttpGet(url);
        request.addHeader("Content-Type", "application/json");
        request.addHeader("Accept", "application/json");
        request.addHeader("user", user
                + ":"
                + pass);
        String authString = getAuthorizationString(user, pass);
        request.addHeader("Authorization", "Basic "
                + authString);
        HttpClient client = HttpClientBuilder.create().build();
        HttpResponse response = client.execute(request);
        int httpStatusCode = response.getStatusLine().getStatusCode();
        if (httpStatusCode == 200) {
            BufferedReader br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
            String output;
            while ((output = br.readLine()) != null) {
                System.out.println(output);
            }
        }
    }

    private static String getAuthorizationString(String user, String password) {
        Charset charset = StandardCharsets.UTF_8;
        String userPassword = user
                + ":"
                + password;
        //byte[] authEncodedBytes = Base64.encodeBase64(userPassword.getBytes());
        byte[] authEncodedBytes = Base64.getEncoder().encode(userPassword.getBytes(charset));
        String authString = new String(authEncodedBytes);
        return authString;
    }

}
```


# pom.xmlについて
Mavenを使っていたのでライブラリはpom.xmlで既存のものに対して以下のように追記した。

``` xml
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.5.13</version>
		</dependency>
```
Git はなぜ空のディレクトリを無視するのか？

LAPRAS アドベントカレンダー2021 の 17 日目の記事です。

https://qiita.com/advent-calendar/2021/lapras

# 概要
Git では空のディレクトリをそのままリポジトリに追加することはできません。

この問題は`.gitkeep`等を作成することで解決しますが、そのやり方を知ったとき **「なぜ普通のファイルと同じように追加できないのだろう？」** と疑問に思った方も多いのではないでしょうか。

というわけで本記事では、空ディレクトリを追加できない仕様になっている理由について調査してみました。
 
# Gitが管理するのはファイルの内容

「空ディレクトリを`add`できないのは何故か？」という疑問への答えとして、
「そもそもどんなディレクトリも`add`はできないから」がまず挙げられるでしょう。

もちろん`git add directory/`とコマンドを打つこと自体は可能です。

しかしこのとき実際にインデックスに追加されるのは、その`directory`自身ではなく、それに含まれるファイル(の内容に対応する blob オブジェクト)群です。

インデックスにおいては、ディレクトリはそれらファイルのパス名としてのみ登場します。

よってディレクトリ内に追跡可能なファイルが一つもなければ`git add`しても何も起こらないのは当然ということになります。

##### 参考

https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88


しかし上述の「答え」は現状の仕様がそうだと言っているだけです。

**実際、空ディレクトリだけでも追加できる仕様に変えれば、大量の空ディレクトリがある場面などで便利なはずです。**
そのような機能が未だに実装されていないのは何故なのでしょうか？

この疑問の答えは、Git 開発者のメーリングリストにありました。

## ディレクトリを管理することの難しさ

「なぜ空ディレクトリを追加できる仕様にはできないのか？」という疑問に対しては、[2007年7月18日のスレッド](https://lore.kernel.org/git/85lkdezi08.fsf@lola.goethe.zz/)で Linus Torvalds 自身が様々な理由を挙げてくれていました。

その中でも、最も納得感のあった説明を以下で解説します。

### <空ディレクトリを管理すると起こる問題の例>
まずは空ディレクトリ内に適当なファイルを作成し、それを ignore したとします。
![GI!_01.001 2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/cff3681a-426f-cbc7-345f-702f51fbbe76.jpeg)
中のファイルを ignore しているため、扱いは空ディレクトリと依然同じになることに注意してください。

そして**この「空ディレクトリ」が Git 管理できると仮定し、コミットしたとします。**
![GI!_02.001 2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/35fd3e40-f9ed-851c-53db-d18ff74d52c9.jpeg)

さて、この「空ディレクトリ」がコミットされる以前のブランチへ移動するとどうなるでしょうか？

このディレクトリは Git 管理しているのだから、当然削除されることになるでしょう。
![GI!_03.001 2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/fec71ec1-266f-0133-549e-4f90f1a06cab.jpeg)

しかしその中のファイルは Git 管理から外しているのだから、**Git の状態に関わらず存在すべき**です！
![GI!_04.001 2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/d3a6f664-4232-cdad-5745-c32645ec4b5d.jpeg)
つまり**削除すべきディレクトリの中に、残しておくべきファイルがあることになり矛盾**します。

#### 問題が起こる原因

なぜこのようなことが起きてしまうのでしょうか？
Linus は[以下のように説明](https://lore.kernel.org/git/alpine.LFD.0.999.0707180925030.27353@woody.linux-foundation.org/)しています。

> 「ディレクトリを追跡すること」は「ファイルを追跡すること」と全く異なるのだと指摘しておきたい。
>
> セマンティクスが完全に異なっているんだ。突き詰めると、ファイルを追跡する場合は常に**その全て**の内容を扱うが、ディレクトリの場合はその部分集合を扱うことになるという事実に帰着する。

ディレクトリはその「内容」の一部だけが untracked になる場合があるため、ファイルでは起こらなかった問題が発生するということですね。

# まとめ
上の例以外にも、様々なケースで特別な考慮が必要になり、多くの改修が必要になりうることが指摘されています。

そして Linus 自身はあまりこの問題に関心がなく、空ディレクトリの管理が必要であれば自分でパッチを書くか、`.gitignore`の配置で解決せよと勧めています。

要するに空ディレクトリを無視し続けているのは、
- ファイルの内容を追跡する現行の Git のデザインと噛み合わず、様々な仕様上の問題が発生する
- `.gitkeep`や`.gitignore`で解決する問題のため、大規模な改修を行うモチベーションが低い

という理由からのようです。