OmniAICreator/Qiita-1.07M huggingface dataset:
ssh接続可能なDockerコンテナの作成方法

# ssh接続可能なDockerコンテナの作成方法

## 目次
1. [はじめに](#はじめに)
2. [ベースとなるDockerfileの作成](#ベースとなるdockerfileの作成)
3. [コンテナをbuild, runしてbashに入る](#コンテナをbuild-runしてbashに入る)
4. [bashでの作業とエラー確認](#bashでの作業とエラー確認)
5. [解決の手順](#解決の手順)
6. [Dockerfileの更新](#dockerfileの更新)
7. [最終的なDockerfileの動作確認](#最終的なdockerfileの動作確認)
8. [注意点とセキュリティ](#注意点とセキュリティ)
9. [付録: 完成したDockerfile](#付録-完成したdockerfile)

## はじめに
dockerコンテナを本番環境に見立ててデプロイのテストをするため今回準備した。

## ベースとなるDockerfileの作成
```markdown
FROM ubuntu:latest
```

## コンテナをbuild, runしてbashに入る
```bash
docker build -t my_ssh_container .
docker run -it my_ssh_container /bin/bash
```

## bashでの作業とエラー確認
1. `openssh-server`のインストール。
```bash
apt-get update && apt-get install -y openssh-server
```
2. `sshd`のディレクトリ作成と設定。
```bash
mkdir /var/run/sshd
echo 'root:YOUR_PASSWORD' | chpasswd
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/g' /etc/ssh/sshd_config
sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
```
3. SSHDサーバーを起動。
```bash
/usr/sbin/sshd -D
```

## 解決の手順
1. ssh接続を試みる
```bash
ssh root@localhost -p 2222
```
2. passwordを入力
3. permission denyエラーが発生。
4. sshdの出力ログを確認。
5. 確認事項:
   - passwordが正しいこと
   - `/etc/ssh/sshd_config`の設定が正しいこと

`/etc/ssh/sshd_config`の設定に誤りがあることを確認。
`#PermitRootLogin yes`がコメントアウトされているため、ssh接続が失敗した。

6. sshの設定を修正。
```bash
sed -i 's/#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config
```
7. SSHDサーバーを再度起動。
```bash
/usr/sbin/sshd -D
```

8. ssh接続を試みると成功。
```bash
ssh root@localhost -p 2222
=> passwordを入力
```

## Dockerfileの更新

## 最終的なDockerfileの動作確認
```bash
docker run -d -p 2222:22 my_ssh_container
ssh root@localhost -p 2222
```
パスワードを入力: `YOUR_PASSWORD`

## 注意点とセキュリティ
rootユーザーとしてのSSH接続はリスクがあります。鍵認証の導入など、適切なセキュリティ対策を行う必要があります。

## 付録: 完成したDockerfile
```Dockerfile
FROM ubuntu:latest

RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:YOUR_PASSWORD' | chpasswd
RUN sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/g' /etc/ssh/sshd_config
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
```
パワーシェル、ssh接続後管理者権限かどうか確認コマンド

Powershellが管理者として実行されているかどうかを確認する
https://techexpert.tips/ja/powershell-ja/powershell-%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89-%E3%83%A9%E3%82%A4%E3%83%B3%E3%81%8C%E7%AE%A1%E7%90%86%E8%80%85%E3%81%A8%E3%81%97%E3%81%A6%E5%AE%9F%E8%A1%8C%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84/

以下は上記URLのコマンドを実行


Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

新機能と改善のために最新の PowerShell をインストールしてください!https://aka.ms/PSWindows

PS （ユーザ名）@(コンピュータ名):C:\Users\（ユーザ名） - 2023-09-14 10:27:06 >
PS>ssh ゆう@（ゆうのIPアドレス）
ゆう@（ゆうのIPアドレス）'s password:
Microsoft Windows [Version 10.0.19045.3324]
(c) Microsoft Corporation. All rights reserved.
ゆう@（コンピュータ名） C:\Users\ゆう>powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

新しいクロスプラットフォームの PowerShell をお試しください https://aka.ms/pscore6

PS ゆう@（コンピュータ名）:C:\Users\ゆう - 2023-09-13 17:34:59 >
PS>([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Princip
al.WindowsBuiltInRole] "Administrator")
True
PS ゆう@（コンピュータ名）:C:\Users\ゆう - 2023-09-13 17:35:22 >
PS>


Trueなので僕の場合、sshでつないでpowershellを実行した後は、管理者権限で動いている
Vue3でinputイベントによるstate変更を遅延させるためのhookを作る

# はじめに
この記事の内容は、入力フォームと、入力の結果を閲覧できるプレビューの両方を持つ画面のような、入力フォームコンポーネントのmodelValueの値が他のコンポーネントの描写に影響する画面を作成したい場合を想定しています。

他のコンポーネントに入力値をリアルタイムに反映したい場合、inputイベントで変更を検知するしかありませんが、この場合、タイピングの最中の変更まで検知されてしまい、無駄なレンダリング処理が発生してしまいます。（主に英数字の場合）

これを回避する方法として、タイピング中はmodelValueに値が反映されない作りを検討した時の情報をまとめます。

# 概要

入力用のstateと、変更データ保持用のstateの２つのstateを用意し、key-eventが発生している最中は変更データ保持用のstateが更新されないようにします。

この処理をcomposableとしてまとめて再利用可能とします。

# hook

```typescript: composables/lazyChange.ts
import { Ref, computed, ref, shallowRef } from "vue"

const DERAY_TIME = 500

export const useLazyChange = <T>(
  state: Ref<T> | ReturnType<typeof computed<T>>,
) => {
  const timeoutId = ref<NodeJS.Timeout | string | number | undefined>()
  const value = shallowRef<T>(state.value)

  const changeState = () => {
    state.value = value.value
  }

  const setValue = (v: T) => {
    clearTimeout(timeoutId.value)
    value.value = v
    timeoutId.value = setTimeout(changeState, DERAY_TIME)
  }

  return {
    /** Value at which changes are reflected in real time */
    value,
    /** setter */
    setValue,
  }
}
```

# 使用側
```vuejs: components/.../Form.vue
<script setup lang="ts">
import { computed } from 'vue'
import { useLazyChange } from '~/composables/lazyChange'

type Props = {
  modelValue: {
    foo: string
    bar: {
      summary: string
      checked: boolean
    }
  }
}

type Emit = {
  (event: 'update:modelValue', value: Props['modelValue']): void
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: {
    foo: '',
    bar: {
      summary: '',
      checked: false,
    }
  }
})

const state = computed<Props['modelValue']>({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val),
})

const fooChangeHook = useLazyChange(
  computed({
    get: () => state.value.foo,
    set: (val) => {
      const orgState = state.value
      state.value = {
        ...orgState,
        foo: val,
      }
    },
  })
)

const barSummaryChangeHook = useLazyChange(
  computed({
    get: () => state.value.bar.summary,
    set: (val) => {
      const orgState = state.value
      state.value = {
        ...orgState,
        bar: {
          ...orgState.bar,
          summary: val,
        },
      }
	},
  })
)
</script>

<template>
  <form>
    <input
      name="foo"
      :value="fooChangeHook.value"
      @input="fooChangeHook.setValue"
    />
    <input
      name="barSummary"
      :value="barSummaryChangeHook.value"
      @input="barSummaryChangeHook.setValue"
    />
  </form>
</template>

```

# まとめ
useLazyChangeの使用箇所が冗長になってしまったので、input自体もコンポーネントにまとめて隠蔽したくなりました。

inputをラップした基本機能のatomコンポーネントを作成した上で、更にそのコンポーネントを利用した、inputイベントで"update:modelValue"をemitするコンポーネントを作成するのが現実的でしょうか。

時間があれば作ってみたいと思います。
filemakerで階乗を実装してみた（Letによる再帰式と再帰関数での実装）

# filemakerで階乗を実装してみた

下記サイト参考にさせていただきました。
https://fm-aid.com/bbs2/viewtopic.php?pid=86825

バージョンは17pro advancedなのでwhile関数はありません。
階乗する数はフィールドで入力されたものを使うのがいいんでしょうけど、今回は直接\\$n にいれてしまっています。

$n = 5　としていますので、
5! = 5 * 4 * 3 * 2 * 1 = 120 となればOKです。

1. 既にある関数を使った計算式
1. Letによる再帰式
1. 再帰関数

順番にコードを紹介します。

1\. 既にある関数を使った計算式
```
Factorial(5)
```

2\. Letによる再帰式
```
let(
    [
        $n = 5;
        $ans = 1;
        $saiki = "
        case(
            $n = 1;
            $ans ;

            $n > 1;
            let(
                [
                    $ans = $ans * $n;
                    $n = $n -1
                ];
                evaluate($saiki)
            )
        )
        "
    ];
    evaluate($saiki)
)
```

3\. 再帰関数
```
let(
    [
        $n = 5;
        $saiki = "case(
            $n = 1;
            1;

            $n > 1;
            let(
                [
                    $n = $n -1 
                ];
                ($n + 1) * evaluate($saiki)
            )
            
        )"
    ];
    evaluate($saiki)
)
```
~~$saiki = "case( )"
とするのが通例みたいですが、とりあえず動きました。~~
いれないと動かないみたいです。（なぜできていると錯覚したのでしょうか）


次はフィボナッチ数列をfilemakerで実装したいと思います。
dockerコマンド実行時、途中からフリーズしてしまう場合

●状況
コンテナ起動しようと思ってコマンドを打ってもずっと処理が進まない。
フリーズするのでググっても解決方法が出てこない。

PC再起動したらどうせ直るものだが、少し時間かかるので面倒
起動したまま直したかった。

ちなみに、WindowsでDocker Desktopを使っている。


## 解決方法
直感的に分かりそうだが、ググっても出てこない人向けに。。。

右下にこのように表示されていると思うが、Docker Desktopアイコンクリックしたら色々出てくるので、「Restart」をクリック。これで再起動され、再起動が終わるまで待つ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179803/52e70348-4af2-d2b1-63b8-811f6785157f.png)

その後、もう一度dockerのコマンド入力したら、いつも通りの動きをしてくれた。

解決方法はとてもシンプルだが、PC起動しっぱなしだとこういうことがたまに起こるので、これで解決！
Swiftのアクセス修飾子

## はじめに

Swiftプログラミング言語には、クラス、構造体、関数、プロパティなどのアクセスレベルを制御するためのアクセス修飾子があります。アクセス修飾子を使用することで、コードのカプセル化、隠蔽、保護などを行うことができます。この記事では、Swiftにおける各種アクセス修飾子とその使用例について詳しく解説します。

## アクセス修飾子の種類

Swiftには以下の5つのアクセス修飾子があります。

1. `open` - 別のモジュールでもサブクラス化やオーバーライドが可能。
2. `public` - 別のモジュールでもアクセス可能。
3. `internal` - 同一モジュール内でアクセス可能（デフォルト）。
4. `fileprivate` - 同一ファイル内でのみアクセス可能。
5. `private` - 同一スコープ内でのみアクセス可能。

---

## アクセス修飾子による呼び出し可能範囲の比較

以下の表は、各アクセス修飾子によって呼び出し可能な範囲を示しています。


| アクセス修飾子  | 同一スコープ | 同一ファイル | 同一モジュール | 別モジュール |
| -------------- | ----------- | ----------- | -------------- | ------------ |
| `open`         | ✅           | ✅          | ✅             | ✅ (サブクラス化、オーバーライド可能) |
| `public`       | ✅           | ✅          | ✅             | ✅           |
| `internal`     | ✅           | ✅          | ✅             | ❌           |
| `fileprivate`  | ✅           | ✅          | ❌             | ❌           |
| `private`      | ✅           | ❌          | ❌             | ❌           |


---

## 各アクセス修飾子の詳細と使用例

### open

`open` 修飾子は、クラスやクラスメンバー（メソッド、プロパティ、など）に使用できます。この修飾子を使うと、そのクラスやクラスメンバーは別のモジュールでサブクラス化やオーバーライドが可能になります。

```swift
// 別のモジュールでもサブクラス化やオーバーライドが可能
open class OpenClass {
    open func openMethod() {
        print("Open Method")
    }
}
```

### public

`public` 修飾子は、その要素がどこからでもアクセスできるようにしますが、別のモジュールでのサブクラス化やオーバーライドは不可です。

```swift
// 別のモジュールでもアクセス可能だが、サブクラス化やオーバーライドは不可
public class PublicClass {
    public func publicMethod() {
        print("Public Method")
    }
}
```

### internal

`internal` はデフォルトのアクセスレベルであり、同一モジュール内であればどこからでもアクセスできます。

```swift
// 同一モジュール内でアクセス可能
internal class InternalClass {
    internal func internalMethod() {
        print("Internal Method")
    }
}
```

### fileprivate

`fileprivate` は、同一ファイル内でしかアクセスできないように制限します。

```swift
// 同一ファイル内でのみアクセス可能
fileprivate class FilePrivateClass {
    fileprivate func filePrivateMethod() {
        print("FilePrivate Method")
    }
}
```

### private

`private` は、同一スコープ（ブロック、クラス、構造体、など）内でのみアクセスが可能です。

```swift
// 同一スコープ内でのみアクセス可能
private class PrivateClass {
    private func privateMethod() {
        print("Private Method")
    }
}
```

## まとめ

Swiftのアクセス修飾子は、コードの保守性や可読性を高める上で非常に有用です。適切なアクセス修飾子を使うことで、エラーを防ぎ、より安全なコードを書くことができます。この記事が、Swiftでのアクセス修飾子の理解に役立つことを願っています。
git fetch vs pull  fetchとpullの違い

## 背景
Git でfetchとpullのやりたきことが似ているのでどういう使い分けをしたらいいのか整理したいと思った

## 画像で整理
大まかに言うと、以下画像のような違いがある
![ブランチ整理.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/764409/a5234167-aa1c-30e0-8b19-1a1f1153976d.png)



## git fetchを使うケース
fetchだけをした状態だと、リモート追跡ブランチを最新の状態にする。
ローカルブランチにまでは影響が無いので、コンフリクトも発生しない。
ローカルリポジトリに反映させるには、``git merge``をする必要がある

コンフリクトが発生した時は``git fetch``だけして解消する


## git pullを使うケース
fetchとmergeを一気に行いたい時
DE環境


# 接続できない

+ [Unable to connect Dev Edition Org to Trailhead](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007RcTOE)

:::note alert
You're trying to log in to the wrong type of Salesforce org. You can only complete hands-on challenges with a Developer Edition org.

Try again with a Developer Edition org, like a Trailhead Playground. Make sure you’re not using a production or sandbox org, or an org with a namespace assigned to it.
:::

:::note
 I  followed what was shared in the article but it did not work as well. However, it started working today when I tried it again. Perhaps the answer to this issue was to wait 
:::
 

 # DE環境にはSandboxはない

+ [Salesforce Sandbox in Free Developer org](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V000077BtFf)

:::note
I don't think you can create sandboxes in Developer org.

If you are a partner of Salesforce and develop Apps for the App exchange - then you can sign up for a Partner Org which will have  Sandbox Instances. 

See the below links for more info,
http://wiki.developerforce.com/page/Partner_Development_%26_Test_Environments
http://www.salesforce.com/partners/overview/

https://developer.salesforce.com/forums/?id=906F00000008sZ0IAI
:::


# 組織にPlaygroundスターターアプリがありません

+ [Missing Playground Starter App from my org](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000EA0YU)
+ [Where is my Install Package link or Playground Starter?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000Jfqzi)


DE環境にインストールしたけど使えないです。
注意: このツールは Trailhead Playground 専用です。 本番組織では利用できません。
UnrealEngineのWebSocketsモジュールでパスがないURLを指定すると//が追加されて通信できなかった

UnrealEngineのWebSocketsモジュールを利用してAWSのAPI Gatewayのwebsocketとパスなしのカスタムドメインで通信できなくてはまったので内容を記録しておきます。

# 確認した環境

Windows 11
UE5.2.1

# WebSocketsモジュールについて

build.csにPrivateDependencyModuleNamesにWebSocketsを追加し、以下のようなコードでWebSocket通信ができます。

```c++
#include "WebSocketsModule.h"
#include "IWebSocket.h"

[略]

TSharedRef<IWebSocket> Socket = FWebSocketsModule::Get().CreateWebSocket(ServerURI, ServerProtocol, Headers);
Socket->OnConnected().AddUObject(this, &UWebSocketClient::OnConnected);
Socket->OnConnectionError().AddUObject(this, &UWebSocketClient::OnConnectError);
Socket->OnClosed().AddUObject(this, &UWebSocketClient::OnClosed);
Socket->OnMessage().AddUObject(this, &UWebSocketClient::OnMessage);
Socket->Connect();

[略]

```

# //が追加される現象について

wss://api.example.comのようなパスのないURLを指定してCreateWebSocketしてConnectすると以下のような結果になりました。

* エラーになって以下のようなログが記録される
```text
LogWebSockets: Warning: Lws(Warning): lws_client_handshake: got bad HTTP response '400' 
LogWebSockets: Verbose: FLwsWebSocket[1]::LwsCallback: Received LWS_CALLBACK_CLIENT_CONNECTION_ERROR, setting State=Error CloseReason=HS: ws upgrade response not 101 PreviousState=Connecting
```
* API Gatewayのアクセスログには何も記録されない
* fiddlerでは以下のような通信が記録されレスポンスとして400エラーになっている
```text
GET https://api.example.com// HTTP/1.1
[略]
Upgrade: websocket
Connection: Upgrade
[略]
```

# 原因

デバッグするとURLを解析するlibwebsocketsのlws_parse_uri関数の結果、パスの文字列が/になっておりそれと/がジョインされることで//になっていました。
https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Source/Runtime/Online/WebSockets/Private/Lws/LwsWebSocket.cpp#L709-L728
/hogeなどのパスが指定されている場合のlws_parse_uri関数で解析されるパスの文字列はhogeになっています。

libwebsocketsとしては仕様みたいです。
https://github.com/warmcat/libwebsockets/issues/414

# 対策

Engineの改造は嫌だったので、API Gatewayのカスタムドメインをパス付で提供するように変更しました。

# 所感

API Gatewayがデフォルトで提供するドメインはステージのパス付なので問題なく通信ができていたので、カスタムドメインに書き換えるだけと思っていたらできなくてはまりました。
ログを見ると400エラーが返って失敗しているようなのにAPI Gateway側にログが記録されていないというのでしばらく悩みました。
リモート追跡ブランチと上流ブランチ

## 背景
git pull とgit fetchの違いを理解する上でこれらの単語が出てきたので理解する

以下画像を見ながら整理する
![ブランチ整理.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/764409/0bf2cfc8-3435-b23a-5512-29eb4205d39b.png)



## 上流ブランチ
origin/developというリモートブランチをpullしてきた時にローカルにdevelopブランチができるが、
このpullしてくる元のブランチ(origin/develop)のこと



## リモート追跡ブランチ
上流ブランチと、ローカルブランチを関連付けるためのブランチ(DBで言う中間テーブル)
origin/developというリモート追跡ブランチはリモートのorigin/developブランチとローカルのdevelopブランチを接続(追跡)している。
[OCI] サービス制限の引上げをSRで依頼する

## やりたいこと
OracleCloudで、新しいRegionを追加したかったにもかかわらず
上限に達していたため追加できないことが判明。
上限の引き上げを依頼します。

今回は、Region数の引上げですが、Computeなど他のサービスも同様です。

前回の上限に達してエラーが出た記事はこちら
https://qiita.com/nisshii0/items/209572442f8d1118b263
　
## サービス制限の引上げリクエスト

### SRで引上げを依頼する手順

右上の「？」アイコンから、「製品の引上げのリクエスト」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/da786033-a90b-0211-f8b9-59dcb73224de.png)

上限を引き上げたいサービス（今回はRegions）と、希望の数を指定します。
また理由を入力して、「サポート・リクエストの作成」をクリックします。

上限は契約によって変わるようです（契約金額や契約形態AnnualFlexなど）
本環境はリージョンの上限が「4」でした。世界の各大陸とDataGuardをしたいので、最低7リージョンは欲しいところです。
日本の2つのリージョン（東京・大阪）は追加済みのため、少し余裕をもって依頼してみます。
現在の倍以上のリクエストになりますが、通るのでしょうか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/1f4bbb0b-b9cb-135e-0b5f-af349d9beac1.png)

リクエスト完了画面です。審査や対応に1－4日ぐらいかかるそうなので、少し待ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/6b45446a-7b5e-d569-f3b0-4e7af5ddc2af.png)

### 引上げ後の確認
ちょうど4日後、SRの画面が更新され、引き上げが行われたようです。
依頼完了はメールが届いたのですが、対応完了はメールが届きませんでしたので
たまにSR画面を確認したほうがよさそうです。SR画面へのリンクは依頼完了メールにありました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/64546c22-4582-9140-40ec-12baf741cc39.png)


制限が引き上げられたことを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/905f66e3-96c5-e4e0-00ec-30e2ebf08d3f.png)

以前は 4 でしたが、10 に変わっていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/6556182b-f3dd-fe39-1ba7-2e861e5f6162.png)

本当に制限が解除されていることを、リージョンを追加して確認してみます。
（リージョン追加は解除できないため、慎重に行います）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/8872353b-740f-657c-cde2-dd1f378dd575.png)

大好きな国スイスのリージョンを「サブスクライブ」します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/b2eb43c4-d1f6-a1a4-adc0-7e0ac1b60eb2.png)

前回は、この画面で「サブスクライブ」をクリックしたところでエラーがでましたが、、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/8e3e33b8-79b6-e72f-f404-22fd48491316.png)

無事に追加されました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/2736f5a2-5c34-b8d2-9e99-3706bc992958.png)
ChatGPTでより良い答えが返ってくる質問の仕方

## はじめに
ChatGPTを普段使っている中で、個人的により良い回答が返ってくる質問の仕方についてまとめてみました。
あくまで個人的にこうした方がいい答えが返ってくることが多いなーと感じたことを書いていきます。

## ChatGPTに聞いてみた
ChatGPTと上手く話すコツをChatGPTに聞いてみました。

**はっきりとした質問をする:**
はっきりとした質問をすることで、ChatGPTが適切な回答を提供しやすくなります。あいまいな質問では、予期しない回答や理解しにくい回答が返ってくる可能性が高まります。

**簡潔で具体的な言葉を使う:**
簡潔で具体的な言葉を使うことで、意思疎通がスムーズになります。長文や冗長な表現は避け、要点を明確に伝えるよう心がけましょう。

**対話を進める:**
ChatGPTはあなたの対話の文脈を理解しようと努力していますが、時には情報が不足していることがあります。そのため、対話を進める役割も持つことが大切です。前回の対話の内容や質問に関連する情報を提供し、対話を続けやすくしましょう。

**ターゲットを絞る:**
広範なトピックに関する質問よりも、特定のトピックやテーマに絞った質問をすると、ChatGPTの回答がより適切になります。例えば、「料理のレシピを教えて」という具体的な質問は、一般的な「料理について教えて」という質問よりも明確です。

**フォローアップ質問をする:**
ChatGPTの回答に関連するフォローアップ質問をすることで、深い対話を楽しむことができます。回答に興味を持ち、詳細を尋ねたり、関連する質問を投げかけたりしましょう。

**丁寧にコミュニケーションを取る:**
ChatGPTは機械ですが、丁寧なコミュニケーションは良好な対話を促進します。挨拶や感謝の言葉を使うことで、対話の品質が向上することがあります。

**テストして試す:**
ChatGPTはモデルに基づくシステムであり、時には間違った情報を提供することがあります。情報を受け入れる前に、必要な場合は他の情報源で確認することを忘れないでください。

だそうです。

## 場面別の質問の仕方
開発などで、ChatGPTをよく使う場面別の聞き方を書いていきます。
### エラーを解決したい時
#### ・エラー文とエラーが起きているコードの両方を教える。
エラー文を教えるだけでも、それなりの回答が返ってくることが多いですが、エラーが起きているソースコードを一緒に教えると、そのソースコードのどこを直せばいいのかと、サンプルのソースコードを教えてくれます。


#### ・同じチャット欄で会話をする
これはどんな質問をする時にも言えることですが、ChatGPTは、同じチャット欄の会話をもとに、返答をしてきたりするので、同じ問題を解決したいときは、同じチャット欄で会話をするようにしたほうがいいと思います。

### サンプルのコードを教えてもらいたいとき
一からコードを書くのは、少し面倒くさいなーと感じる場面があると思います。
そんな時に、ChatGPTにサンプルコードを作ってもらって、それに手を加えていくという使い方をすることもあると思います。
例として、デザインなどを組み立てる場面のことを考えていきます。
こういう時は、自分がどんなイメージのコード画面にしたいのかを伝えたほうが、それに沿ったコードを教えてくれると思います。
例えば、「以下のコードをTailwindCSSを使って、色味は5色までかつ、かっこいいデザインにして」という質問とともに、デザインしてもらいたい画面のHTMLを貼り付けて質問するなど、具体的な要求をすることによって、いい回答が返ってくることが多いと思います。

#### コードを省略してほしくない時
ChatGPTに、コードの修正を頼んだ時に、そのコードが長かったりすると、ChatGPTは修正箇所以外のコードの一部を、省略したりします。なので、省略しないでほしい時は、質問する時に「省略しないで」という一文を追加しておけば、省略をしないで、修正したコードを教えてくれます。

他のパターンも追記していきます。

## 最後に
今回は、ChatGPTでより良い回答が返ってくる質問の仕方について書きました。
ChatGPTの全てを信じることは良くありませんが、上手く活用することで、仕事や学習の効率アップに繋げることができるので、積極的に活用していきましょう。

他にも記事を書いているので、ぜひ読んでいってください。

https://qiita.com/hukuryo/items/97797a91d7e2ee0bcabc

https://qiita.com/hukuryo/items/265c676d17fe21e75242

https://qiita.com/hukuryo/items/ebeb26823f944f143b11
Python: 2023東京大学・文科・第3問（シミュレータ）

# 2023東京大学・文科・第3問（シミュレータ）

Python を用いて上記のシミュレータをできるだけ単純に作成してみた。この問題については ↓

    黒玉3個、赤玉4個、白玉5個が入っている袋から玉を1個ずつ取り出し、取り出した玉を順に1列に12個並べる。
    ただし、袋から個々の玉が取り出される確率は等しいものとする。

    (1) どの赤玉も隣り合わない確率 p を求めよ。
    (2) どの赤玉も隣り合わないとき、どの黒玉も隣り合わない条件付確率 q を求めよ。

## 実装

玉を文字と見立ててシャッフルと `'rr'` が含まれるか、 `'bb'` が含まれるかを判定。(1) は `'rr'` が含まれる割合を計算すればよいので平均を取り、(2) は `'rr'` と `'bb'` 両方含まれる確率を計算し (1) の答えで割ればよい…はず

```python
import numpy as np
import random


class Sim(object):
    """2023東京大学・文科・第3問　シミュレーター
    黒玉3個、赤玉4個、白玉5個が入っている袋から玉を1個ずつ取り出し、取り出した玉を順に1列に12個並べる。
    ただし、袋から個々の玉が取り出される確率は等しいものとする。

    (1) どの赤玉も隣り合わない確率 p を求めよ。
    (2) どの赤玉も隣り合わないとき、どの黒玉も隣り合わない条件付確率 q を求めよ。
    """
    def __init__(self, x):
        self.x = x

    def __call__(self):
        # 玉をランダムシャッフル
        random.shuffle(self.x)
        # 文字列として処理できるよう結合
        y = ''.join(self.x)
        # 'rr' が y に含まれていない(True or False)
        a1 = 'rr' not in y
        # a1 & 'bb' が y に含まれていない(True or False)
        a2 = a1 & ('bb' not in y)
        return [a1, a2]


# 試行回数
N = 10000000
# 玉: 黒玉3個、赤玉4個、白玉5個
x = ['b'] * 3 + ['r'] * 4 + ['w'] * 5
# シミュレータ
sim = Sim(x)
# N 回シミュレート
result = np.array([sim() for i in range(N)])
# 平均確率を算出（numpy は True=1, False=0 として計算できる）
a1, a2 = np.mean(result, axis=0)
# 表示
print("(1)", a1)
print("(2)", a2 / a1)

>>> (1) 0.2543706
>>> (2) 0.613201761524327
```

## まとめ
多分できたはず。まぁ 15 分くらいでちゃちゃっと作った割には比較的わかりやすくシンプルに実装できたのではないでしょうか？ ちなみに計算すると…

(1) 25.45% 
(2) 61.31%

くらいになるよう。
Go言語を学んでみる #1

Go言語を使ってシステム開発してみたいと思ったので、まとめてみる。

参考: https://hnavi.co.jp/knowledge/blog/go/

# Go言語とは
- Googleが開発したサーバサイド言語
- シンプルかつ高速な処理が可能
- YouTubeやメルカリの開発で使用されていて、近年注目が集まっている言語のひとつ

# インストール方法
下記リンクからインストーラをダウンロードしてインストール
https://go.dev/dl/

# 学習方法
とりあえず基礎は公式サイトを見てみるのがいい感じ。
https://go.dev/learn/

「Tour of Go」から、ブラウザ上で学習ができる。日本語にも対応。大変便利。

ロードマップのリンクもメモ。英語ができる人はこのロードマップから勉強するのがいいかも。

https://github.com/Alikhll/golang-developer-roadmap/blob/master/i18n/ja-JP/ReadMe-ja-JP.md

ということで次回から実際に公式サイトで学習したことをいろいろメモしていく。
【 Vue.js 】FormData.append()メソッド

# FormData

`FormData`インターフェースは、インターフェールフィールドおよびそれらの値から表現されるキーと値のペアセットを簡単に構築します。

`fetch()`、`XMLHttpRequest.send()`、`navigator.sendBeacon()`メソッドを用いることで送信が可能です。

# メソッド

`FormData.append()`
`FormData`オブジェクト内のキーに新たな値を追加する。キーが存在しない場合はキーを追加する。

`FormData.delete()`
`FormData`オブジェクトからキーと値のペアを削除します。

`FormData.entries()`
`FormDara`ｎ含まれているすべてのキーと値のペアを走査するイテレーターを返します。

※イテレータープロトコル
配列のようばデータ構造の要素を準に走査していく繰り返し処理を簡潔に機銃できる構文やオブジェクト。

`FormData.get()`
`FormData`オブジェクトの中から、指定したキーに関連付けられた最初の値を返します。

`FormData.getAll()`
`FormData`の中から、指定したキーに関連付けられたすべての値の配列を返します。

`FormDatahas.has()`
`FormData`オブジェクトがあるキーと値のペアを持っているかを示す論理値を返します。

`FormDatahas.keys()`
オブジェクト内に存在するキーと値のペアから、すべてのキーを走査できるようにするためのイテレーターを返します。

`FormDatahas.set()`
FormDataオブジェクト内の既存のキーに新たな値を設定するか、キーが存在しない場合はキーと値のペアを追加します。

`FormDatahas.values()`
オブジェクト内に存在するキーと値のペアから、すべての値を走査できるようにするためのイテレーターを返します。

## FormData(コンストラクター

`FormData()`
新しい`FormData`オブジェクトを作成します。

### 構文
```js:
new FormData()
new FormData(form)
new FormData(form, submitter)
```

### 引数

〇form(省略可)
その各要素のnameプロパティをキーに、それらの送信される値を値としてるかい、フォームの現在のキーと値が設定さてます。

〇submitter(省略可)
submitterにname 属性があるか`<input type="image">`であった場合、このデータは FormData オブジェクトに含まれます。

### 空のFormDataの作成

```js:
const formData = new FormData();
```

キーと値のペアを追加
```js:
formData.append("username", "Chris");
```


# append()

`append()`はFormDataのインターフェースのメソッドです。FormDataオブジェクト内の既存のキーに新しい値を追加します。キーがまだ存在しない場合は追加します。

### 構文

```js:
append(name, value)
append(name, value, filename)
```

### 引数

〇name
value にあるデータのフィールド名です。

〇value
フィールドの値です。

〇filename
サーバーに報告されるファイル名（文字列）です。
Aiven for PostgreSQL®が論理レプリケーションスロットを自動的に再作成するようになりました。

<font color="Grey">*[Aiven for PostgreSQL® now recreates logical replication slots automatically](https://aiven.io/blog/aiven-for-pg-recreates-logical-replication-slots)の翻訳です。*</font>

2023年1月13日

# Aiven for PostgreSQL® が論理レプリケーションスロットを自動的に再作成するようになりました。

メンテナンス時やフェイルオーバー時に論理レプリケーションスロットを失う心配がなくなりました！詳しくはこちらをご覧ください。

## フェイルオーバーの痛み


PostgreSQL®クラスタのプライマリノードが故障し、新しいプライマリノードが計画通りにそれを置き換えます...しかし、レプリケーションスロットへの接続が切断され、他のシステムは新しいプライマリからデータを読み取ることができなくなります。例えば、PostgreSQL®が長期ストレージとして機能し、Apache Kafka®がデータを出し入れしている場合、新しいレプリケーションスロットをセットアップしないと、Kafkaは新しいプライマリからデータを読み取ることができません。


新しい論理レプリケーションスロットを作成して接続するには、しばらく時間がかかります。新しいエントリが書き込まれないようにシステムの他の場所からPostgreSQLへのアクセスをシャットダウンするか、エントリが削除されないようにクラスタ全体を再同期するかです。


そして、プライマリごとにこれを行う必要があります。


しかしAivenでは、この手間は過去のものとなりました。2022年12月、Aiven for PostgreSQLのフェイルオーバーや制御された切り替えの際に、論理レプリケーションスロットを自動的に再作成する新機能をリリースしました。


## 論理レプリケーションスロット


PostgreSQL®では、サーバの下流のサブスクライバに対して論理レプリケーションスロットを設定することができます。レプリケーションスロットを持つことで、サブスクライバはデータベースのデータの変更を受け取ることができます。


この設定の問題点は、レプリケーションスロットに依存していてプライマリノードがダウンした場合、データにギャップが発生するか、データベースの巨大な塊を再読み込みしなければならなくなることです。


フェイルオーバーやスイッチオーバーの後、スロットを再作成し、すべてのダウンストリーム・サブスクライバーを再接続する必要があるからだ。これを手作業で行った場合、サブスクライバはその処理中にデータベースに書き込まれたものをすべて失うことになる。データベースの完全な再同期でこれを軽減することはできますが、ユーザーにとってダウンタイムが発生します。


## もうギャップも完全な再同期もしない


Aiven for PostgreSQLはPGクラスタのレプリケーションスロットの自動再作成を実装しました。複数ノードクラスタのプライマリノードがダウンすると、計画外のフェイルオーバーであれ、制御された切り替えであれ、Aivenは自動的に古いプライマリサーバから新しいプライマリサーバにレプリケーションスロットを再作成します。シングルノードクラスターの場合、レプリケーションスロットは制御された切り替え時に再作成されます。


これは、スタンバイまたはプライマリとして昇格する新しいノードにプライマリからレプリケーション・スロットを作成し、それらの位置を継続的に同期することで実現されます。フェイルオーバーやスイッチオーバーが発生すると、スタンバイ・ノードにはすでに同じレプリケーション・スロットがあり、ポジションは最新（最大5秒の精度）になっている。


スロットは、プライマリに昇格してレプリカや他のシステムへの接続を開始する前に、ノード上で再作成されます。


## レプリケーション・スロットの自動再作成の適用


お客様のAiven for PostgreSQLデータベースは、次回メンテナンス時にサーバーが再利用された際にこの新機能の恩恵を受けることができます（お客様の環境での問題を避けるため、すでに稼働しているノードには手を付けません）。そのため、次回のメンテナンス更新でレプリケーションスロットを最後に失い、その後自動レプリケーションが機能し始めます。


もちろん、新しいサービスにはこの新機能が最初から備わっています！


## まとめ


Aiven for PostgreSQLクラスタの管理が簡単になりました。切り替えやフェイルオーバーの後、新しいプライマリが引き継いだ場合、そのプライマリは既に古いプライマリと同じレプリケーションスロットを持ち、他のシステムはシームレスにそのプライマリからの読み込みを再開することができます。


この新機能の詳細については、ドキュメントをご覧ください：[アップグレードとフェイルオーバーの手順](https://docs.aiven.io/docs/products/postgresql/concepts/upgrade-failover)をご参照ください。



Aivenと私たちのサービスに関する最新ニュースや、オープンソースに関するちょっとした情報を入手するには、[月刊ニュースレターを購読する](https://aiven.io/newsletter)！Aivenに関する日々のニュースは、[LinkedIn](https://www.linkedin.com/company/aiven/)と[Twitter](https://twitter.com/aiven_io)のフィードでご覧いただけます。


サービスのアップデート情報を知りたい方は、[変更履歴](https://aiven.io/changelog)をご覧ください。
モダンJavaScriptの基本あれこれ



# モダンJavaScriptとは？

## 主な特徴

- **React、Vue、Angular、Riotなどの仮想DOMを用いるライブラリやフレームワークを使用**

- **npmやyarnなどのパッケージマネージャーを使用**

- **主にES2015以降の記法を使用**

- **webpackなどのモジュールバンドラーを使用**

- **Babelなどのトランスパイラを使用**

- **SPA（Single Page Application）が基本**

## 仮想DOMとは？

### 従来のDOMと仮想DOM

- **従来のDOM**: DOM（Document Object Model）はHTMLなどを解釈し、ページの要素を木構造で表現する。従来のDOM操作は、バニラJavaScriptやjQueryを使用して直接操作をしていた。そのため、画面のレンダリングコストが高まり、パフォーマンスの問題が発生していた。

- **仮想DOM**: 仮想DOMは、JavaScript内でDOMの操作を行い、変更前と変更後の仮想DOMの差分を計算し、最小限のDOM更新を行う方法。これにより、UIの更新が効率的に行える。

## npm/yarnとは？

### パッケージ管理と依存関係解決

- npmとyarnは、パッケージ管理と読み込み順などの依存関係を解決のためのツール。外部ライブラリやモジュールの管理が容易になる。

- package.jsonは、設計書（いじってもいい）。
- package-lock.jsonは、依存関係やバージョンの解決。自動生成（基本的にいじらない）。
- node_modulesは、実際のモジュールファイルが格納。

## ECMAScriptとは？

### JavaScriptのルール

- ECMAScriptはJavaScriptの仕様を定めるルール。
- ES2015以降に主に追加されたものは以下
    - letやconstの変数宣言
    - アロー関数
    - クラス構文
    - 分割代入
    - テンプレート文字列
    - スプレッド構文
    - Promise
    - etc...

## モジュールバンドラーとは？

### JavaScriptファイルのバンドル

- モジュールバンドラーは、開発時に複数のJavaScriptファイルを一つにまとめるツール。これにより、開発効率が向上し、本番環境でのパフォーマンスも向上する。

## トランスパイラとは？

### JavaScript記法の変換

- トランスパイラは、新しいJavaScript記法を古いバージョンに変換するツール。これにより、新しい記法を使用しても、古いブラウザや環境でも動作するコードを生成できる。

## SPAとは？

### 単一ページアプリケーション

- SPA（Single Page Application）は、一つのHTMLページ内で画面遷移を行う方法。これにより、表示速度が高速化し、ユーザー体験が向上する。また、コンポーネントベースの開発が容易になる。
Next13のチュートリアルをしてたら「If you need interactivity, consider converting part of this to a Client Component.」というエラーにぶつかった話

# はじめに

- 初めてNext.jsの13のチュートリアルをしており、いい感じに実装してたのにボタンにonClickを実装しようとしたら、
    
![スクリーンショット 2023-09-14 4.08.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3504047/b793e520-a096-b0e9-3c5c-99793f2c582c.png)

```tsx
Event handlers cannot be passed to Client Component props.
  <button style={{...}} onClick={function} children=...>
                                ^^^^^^^^^^
If you need interactivity, consider converting part of this to a Client Component.
```

とかいうエラーが出た。

# 解決方法
https://stackoverflow.com/questions/74471642/nextjs-13-button-onclick-event-handlers-cannot-be-passed-to-client-componen

これより、「Next.js 13ではデフォルトで全ての関数がサーバーコンポーネントとなるためクライアントサイドのアクティビティを有効にするには、`’use client’;`をつけるだけでいいらしい。

例：

まじでコードの冒頭に入れるだけ。

注：Next 13以外で実行するとエラーが発生する可能性がある。

```tsx
'use client';

export default function Home() {

    const fetchCatImage = async () => {
      const res = await fetch('https://api.thecatapi.com/v1/images/search');
      const data = await res.json();
      console.log(data);
    };

  return (
    <div
      style={{
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        fontFamily: 'sans-serif',
        justifyContent: 'center',
        height: '100vh',
      }}>
        <h1>猫画像を取得</h1>
        <p>
          <img
            src="https://cdn2.thecatapi.com/images/4kc.gif"
            width={500}
            height="auto"
          />
        </p>
        <button style={{ marginTop:"18"}} onClick={fetchCatImage}>
          次の猫画像
        </button>
    </div>
  )
}
```

うん！いい感じ。
![スクリーンショット 2023-09-14 4.15.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3504047/5f839307-d263-7e99-f4e4-a5b845e3a419.png)
Macにnetdiscoverをインストールする

そんなに難しくない

https://github.com/alexxy/netdiscover/blob/master/INSTALL.mac.txt

↑ちゃんとMac用のインストール手順が書いてある

## インストール手順
```sh
brew install cmake libpcap libnet
git clone https://github.com/alexxy/netdiscover.git
cd netdiscover
cmake .
make
make install
```

次にパスを通してあげる。
```sh
# ~/.zshrc
export PATH="/usr/local/sbin:$PATH"
```

.zshrcを再読み込み
```sh
source ~/.zshrc
```

実行
```sh
sudo netdiscover
```

これでとりあえず実行できる
[積読]コードで「命名」は最重要課題

:::note info
どういうこと？
プログラミングにおいて、「命名」は最重要課題として認識し、慎重に取り組む。
「名前をつける行為」と「名前そのもの」、両方に重要な価値がある。
:::

### 名前をつける行為と名前そのものについて

##### 名前をつける行為
適切な名前を付けることができたら、その設計の大部分が完成したと言っても過言ではない。
| |  |
|:-|:-|
| 適切な名前を付けられた  |その要素が正しく理解されて、正しく設計されている   |
|ふさわしい名前が付けられない   |その要素が果たすべき役割について、プログラマ自身が十分理解できていない   |

##### 名前そのもの
名前は、コードを通じて、**プログラマ同士がコミュニケーションするための最大の場**になる。
コード書いた人と読む人が同時にその場にいて、「リアルタイムの会話」ができることは稀。このリアルタイムでないコミュニケーションを円滑にするため、名前には最大限の配慮が必要。

### コードを読む人へのUI
:::note info
名前はコードを読む人へのユーザーインターフェース。適切に名前を付けられたコードは、「何を」「どのように」やっているか明確に理解できる。
:::

コードを読み書きしている時、プログラマは、常に**脳への過負荷**と戦っています。プログラマがコードに対峙している時、「どう動いているか」という詳細で頭がいっぱいになってしまったら、考えがまとまらず先に進めなくなります。名前が悪いと、読むことに全てのリソースが奪われ、取り組むべき本来の作業（修正や機能追加など）を妨げられ、課題に取り付かなくなってしまう。

名前はこだわると結構な負担となります。しかし、不適切な命名は、コードに負債を与えることと同じです。その後コードが生き続ける限りずっと、コードを読む人、コードを使う人全てに、マイナスの影響が続いてしまいます。

### コードはまず名前を決める
:::note info
プログラミングはまず名前から入る。コードに現れる様々な要素に、意図が正確に伝わるような名前をつけるようにする。その際コードを書いていながらも、常に「使う側」「読む側」の視点に立って命名するようにしましょう。
:::


---

参考文献
*プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則*
https://www.amazon.co.jp/dp/4798046140?ref_=cm_sw_r_cp_ud_dp_0C637KV2ZJAP5TECFEK4_2
ubuntu(virtual box)を日本語環境にしてみた

# 設定画面を開く
右上のアイコン>setting
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/4f244280-eb59-073c-07ee-be1b857a48b3.png)

# Languageを開く
Region & Language > Languageを開く
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/606deb74-0083-3268-32c6-4c89e67f5d26.png)

# Japaneseを選ぶ
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/8a2d44ab-4025-4e2c-477a-e92d457292c2.png)

# Restartをクリックする
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/c8be857c-9406-d7ba-fdca-b7829406d887.png)

# ログインする

# ディレクトリ名変更確認が出る
好きな方を選ぶ
![41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/7fa9380c-bf9e-2e96-2c3b-dc044626ed07.png)



# Manage Installed Languageを開く
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/53fd6a00-0780-089e-5c7f-ef4ce3d3c7f8.png)

# 言語サポートインストール確認がでるので、インストールをクリックする
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/84cf6d14-5cd2-e3cc-9752-00757a225123.png)


![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/892b520c-b367-351d-5967-5f30b2b4909a.png)

# 言語サポートを閉じる
![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/48700b03-97a9-b08a-2942-b5b48c0d82a0.png)

# 入力ソースを開く
Keyboard > Input Sources > +
![21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/df77dc3e-3a7e-d3bc-58d4-ee5e46536317.png)


# 日本語を追加する
![22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/9537c345-2582-6136-b00d-f3abc7e0d267.png)


# ログアウト・ログインする

# 日本語キーボードを有効化する
あ > 日本語 > ja > 日本語(mozc)
![31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/b3bb7ba5-5341-faa6-8c42-0e24a0b591d2.png)

- この操作をしないとUSキーボードとして認識される
Google Cloud (GCP)資格受ける前に必読 :Professional Cloud Developer　編

皆さんこんにちは！iret Global Solutions 事業部の浜田です。今回はGoogle Cloudの中でも大人気資格であるProfessional Cloud Developerについて書いてみました。その名の通り Developer(開発者)向けの試験なので初学者の方はなかなかイメージしずらいと思いますが頑張っていきましょう。


<h1>試験概要</h1>
他の試験と同様、試験時間は2時間で問題数は50~60問です。

https://cloud.google.com/learn/certification/cloud-developer?hl=ja

https://cloud.google.com/learn/certification/guides/cloud-developer?hl=ja

<h1>絶対覚えておいた方がいいこと</h1>

<strong>IAM </strong>
Identity and Access Managementの略称で、Google Cloud Platform（GCP）内でのリソースへのアクセス権を管理するためのサービスです。IAMを使用することによって、ユーザーやサービスアカウントに対して特定の役割や権限を割り当てることができます。

<strong>Workload Identity</strong>
Workload Identityは、Google Kubernetes Engine（GKE）やCompute EngineなどのGoogle Cloudサービス内で、サービスアカウントを使った認証を簡略化する機能です。これにより、サービス間の安全な通信を行うことが可能です。


<strong>Network Policy / Authorization Policy</strong>
Network PolicyやAuthorization Policyは、Kubernetesにおけるネットワーキングやアクセス制御のルールを定義するためのリソースです。ポット単位の通信を制御することができます。


<strong>Compute Engine</strong>
Compute Engineは、仮想マシンを提供するGoogle Cloudのサービスです。Google Cloudの一番基本的な機能でありスケーラブルなコンピューティングリソースを提供しています。AWSを知っている方はEC2をイメージして頂ければわかりやすいと思います。

<strong>Google Kubernetes Engine (GKE)</strong>
Googleが提供するKubernetesクラスタのマネージドサービスです。Kubernetesはコンテナオーケストレーションシステムであり、GKEを使用することで、コンテナ化されたアプリケーションを効果的にデプロイ、管理することができます。


<strong>デプロイ戦略</strong>
デプロイ戦略は、アプリケーションの新しいバージョンをリリースする際の手法やアプローチのことを指します。例としては、CanaryリリースやBlue/Greenデプロイメントなどがあります。取引先の予算やアプリケーションの構成、Google独自の考えである<strong>SLO</strong>を考慮して適切なデプロイ戦略を選択することが重要になってきます。


<strong>Cloud Run</strong>
Cloud Runは、コンテナ化されたアプリケーションをサーバーレス環境で実行するためのGoogle Cloudのサービスです。面倒な設定を無しに手軽にマイクロサービスをオンデマンドで実行できるようになります。

<strong>Cloud Functions</strong>
Google Cloud Functionsは、サーバーレスのコンピュート サービスで、サーバーの管理なしでイベントに応じてコードを実行できます。小規模でイベント駆動型のスケーラブルなアプリケーションを構築するのに特に役立ちます。AWSのサービスに置き換えるとLambdaになります。

<strong>App Engine</strong>
AGoogleがインフラストラクチャの管理を行うPaaS（Platform as a Service）のサービスです。Googleがサーバーの管理をしてくれるので開発者がコーディングに集中できます。

<strong>Cloud Storage</strong>
Google Cloud Storageは、高度にスケーラブルで耐久性のあるセキュアな方法でデータを格納および取得できるGoogle Cloud のオブジェクト ストレージ サービスです。ファイル、画像、ビデオ、バックアップなど、さまざまな種類のデータを格納するのに適しています。


<strong>Firestore</strong>
Google Cloud が提供する NoSQLサービスの1つドキュメントデータベースです。でオンデマンドでスケーリングし、一貫性が高く、前述したSpannerと同様こちらも最大99.999%の可用性を提供します。eコマース、ゲーム、IoT、リアルタイムダッシュボードなど割と万能にこなせます。リアルタイムのアプリケーションやモバイルアプリにを作りたい時に好まれて使われます。













<h1>その他必須項目</h1>




<strong>ハンズオン</strong>
Cloud Developerの試験は開発メインの話が多く、他の試験と比較しても座学だけでは理解がしにくいものになっています。自分はGoogle Cloudの認定試験を受ける際にハンズオンは行いませんでしたが時間がある方は絶対にやっておいた方がいいです。

<strong>その他サービス</strong>
上記のサービス以外にも覚えるものは沢山あります。特に<strong>CloudSQLやBigtableなどのデータベース類</strong>や<strong>Google Cloudが推奨するセキュリティ項目</strong>は一通り覚えておきましょう。

<h1>試験対策</h1>
Google Cloudの模擬試験は必ず解いておきましょう。
足りない部分はUdemyを使うかWhizlabsをChromeのプラウザ翻訳して解くのがおすすめです。

https://docs.google.com/forms/d/e/1FAIpQLSc_67KaPnNwQrLZ7kuhw-aubz7gMAwY6DQwRJYcW0qlG-iajA/viewform?hl=ja


<h1>最後に</h1>

さて、今回の記事は以上になります。初学者の方は躓きやすい試験ですがGoogle Cloudで開発等を行なっている方、Google Cloudで開発を行ってみたい方達には実際の業務においても学べることが多くとてもメリットが大きい試験な気がします。

他のGoogle Cloud の試験に興味がある方は以下に難易度順のランキングを載せているので参考程度に是非。

https://qiita.com/sina-cloud/items/bbe1d263c6b69954867f

それでは皆さん、ご武運を。
【SQL】入社年度で学ぶ BETWEEN /SQLマスターへの道

## 導入
先日、Drupalにて「同期の一覧」をViewsで作成しました。

入社年が完全一致であるならば、MySQLの`WHERE`句で、`=`で指定すればいいだけですよね。
```sql
SELECT *
FROM `user`
WHERE `user`.`join_date` = `2021`;
```

ただ、今回は**入社年度**で絞り込みを行う必要がありました。
そこで、SQLの`WHERE`句で期間指定を行うことができる`BETWEEN`演算子を習得しましたので、備忘録として残させていただきます。

## コード例
```sql
SELECT *
FROM `user`
WHERE "user"."join_date" BETWEEN '2021-04-01' AND '2022-03-31';
```

## 解説
解説するまでもないかもですが一応...

`BETWEEN`は、特定の範囲内のデータを抽出するのに非常に便利です。
上記のクエリでは、'2021-04-01'から'2022-03-31'までの期間に入社したユーザーを選択しています。
この方法を使用することで、特定の期間に入社したユーザーを簡単に特定できます。
もちろん、ID等の単なる数字での範囲指定も可能です。

## まとめ
本記事ではSQLに限った解説をしましたが、Drupalでどう実装したかについても別で書こうと思います。
そちらも楽しみにしてください。
Laravel上でVueファイルが更新されない、画面上で反映されない問題について

# 発端
Laravel上で簡単なtodoサイトを作っている最中で生じたことを残そうと思う。

```cmd
npm install
```
ののち、
```cmd
npm run dev
```
を行っても反映されず
```cmd
npm run build
```
もダメ
```cmd
npm run watch
-> webpack compile successfully
```

ふむ、コンパイルは問題ないようだ。ならばほぼリアルタイムで更新してもらおう

```cmd
npm run watch-poll
-> webpack compile successfully
```
と表示され、少しの変更でも同様の言葉が送られている。

にもかかわらず書き換えた部分が反映されていないなんでだあああああああああああああ

# 結論
見苦しい茶番、すんません。結論言います。

原因はまさかの　**Chromeのキャッシュ**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688801/e30eacf0-4f91-ec9b-ad1e-1f876c010513.png)
2023年9月時点の方法だが、右上の点三つの所から

その他のツール　＞　閲覧履歴の消去　

でおそらく「設定 - プライバシーとセキュリティ」という新しいタブが開かれるので

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688801/b04dd98a-3ceb-9533-6cfe-d40a432b1661.png)

これにチェックをいれて削除するだけ。変更が反映されました。ちゃんちゃん


# 感想
プログラムやコードの問題だけかと思ったがフロント寄りの部分にはブラウザのことも考えなければならないと初体験。バックばっかやっていた人間なもんで。浅学ゆえにもっと精進しまさぁ
Oracle APEXアプリにユーザー名・パスワードの入力無しでアクセスする方法について

## はじめに

APEXアプリケーションにAPEXのワークスペース名やユーザー名、パスワード無しでアクセスする方法を調べたのでまとめます。

## 内容

認証を無くしたいアプリケーションの共有コンポーネントの画面を開き、セキュリティ項目の中の認証スキームをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/6fa3f8d2-f8f5-863b-2cd8-107e8dc7ee10.png)




作成をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/e4af261f-ad83-27a4-04bb-b51de0f03999.png)

次へをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/4998dafe-2b95-db9b-de42-20c66537c723.png)




任意の名前を設定し、フォームタイプは"認証なし"を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/fe239893-f1d3-6ae9-2cf3-d0ce85382aa2.png)


"認証なし"がカレントになっていることを確認出来ました。
以上で完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/944efee0-1d61-9d3e-2d11-8859face5c77.png)


## まとめ

都度ログインすることが面倒に感じる場合やそれほど重要な情報を持つアプリでない場合は認証無しで運用する方が良いケースがありますので、その時に少しでも参考になれば幸いです。



## おまけ　（アプリのトップページの設定方法について）

以下のホームURLを設定することでトップページを変更することが出来ます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/a2980c35-ed6a-bed6-9abf-50dea10ea9f4.png)
【Ruby】GemをGitHub Packagesに公開する方法

## パーソナルアクセストークンの設定
GitHub Packagesに公開などをするには認証が必要です。  
以下の手順でパーソナルアクセストークンの設定をします。  

GitHubのSettingsページを開きます。
![image220730_080233.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/14c246e6-70d9-7fd7-3d05-0155e24eeb20.png)

左サイドバー一番下の「Developer settings」を選択します。
![image220730_080909.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/4e5c8cff-a85e-98b6-c83b-d5e379ba535f.png)

左サイドバーの「Personal access tokens」を選択します。
![image220730_081141.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/066fa4c1-de28-efb4-857c-e306db42bc4d.png)


「Generate new token」を選択します。
![image220730_081329.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/a2978e2c-1fd3-5caa-381a-98748e3f5f3a.png)


「Note」にわかりやすい名称を入力します。
![image220730_081453.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/19690a42-56b8-d8e6-f337-c9f4a96dad66.png)


「Select scopes」で「repo」と「write:packages」を選択します。
![image220730_081711.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/ac65a36e-a0f2-f8bd-407d-b3a66e24f1bb.png)

「Generate token」をクリックします。
![image220730_081643.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/0ac81b28-5b93-9499-bbb2-96ce63a8f99f.png)

パーソナルアクセストークンが作成できました。

`~/.gem/credentials`を以下の内容で作成します。
```~/.gem/credentials
:github: Bearer 作成したトークン
```
```:ターミナル
$ chmod 0600 ~/.gem/credentials
```

## Gemを公開する
以下のコマンドを実行してGemをGitHub Packagesに公開します。
パッケージをビルドします。
```:ターミナル
$ gem build sample-gem.gemspec
```

GitHub Packagesに公開します。
```:ターミナル
$ gem push --key github \
--host https://rubygems.pkg.github.com/リポジトリを所有するユーザー名 \
sample-gem-0.0.1.gem
```
上記`sample-gem-0.0.1.gem`は実際の`.gem`ファイル名に置き換えてください。

公開されているかGitHubで確認します。

![image220730_084651.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/92f134f7-c7bd-e444-03f3-25fbb59cfb26.png)


## Gemをインストールする
上画像のパッケージ名をクリックするとインストール方法の記載されたページが表示されます。
![image220730_084831.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/d517264d-4b39-c26c-99ba-6dc0712e4508.png)


このページの説明に従いインストールします。
物体とデバイスの距離を測るSceneDepth（ARDepthData）からメートル単位の距離を取得する

# iPhone（iPad）と物体の距離を正確に測る
物体が何mデバイスから離れているか測りたい時ってありますよね。
ARKitの深度情報（奥行き情報）を使えば正確に測れます。
Lidar搭載デバイス必須です。

# 方法
### DepthDataの取得

```swift
let configuration = ARWorldTrackingConfiguration()
configuration.frameSemantics = .smoothedSceneDepth
sceneView.session.run(configuration)
```

```swift
func session(_ session: ARSession, didUpdate frame: ARFrame) {
    guard let sceneDepth = frame.smoothedSceneDepth ?? frame.sceneDepth else {
        print("Failed to acquire scene depth.")
        return
    }
    let depthPixelBuffer = sceneDepth.depthMap
```

これで、カメラ画像の**各ピクセルについてm単位の深度をとったマップ画像**が取得できます。

カメラで取得した画像（1920：1440）：
![スクリーンショット 2023-09-13 23.16.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/12cb5b27-07ba-0d8d-8a5e-782d6c40a6d2.png)

デプスマップ画像（256：192）：
![スクリーンショット 2023-09-13 23.16.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/3608f41d-06b0-1447-b3f6-7b431742c202.png)

黒いところほど近い（ピクセル値が低い）です。

アスペクトはカメラ画像と同じですが、256：192の小さなサイズになっています。
あと、カメラ画像は元は横向きになっているので、回転させて使おう。

### メートル単位で距離を取得する
さて、画像のピクセル値を物体への距離に変換します。
画像中央のピクセルで取ってみます。

```swift
let ciImage = CIImage(cvPixelBuffer: pixelBuffer).oriented(.right)
            
let width = CVPixelBufferGetWidth(pixelBuffer)
let height = CVPixelBufferGetHeight(pixelBuffer)
            
let centerX = width / 2
let centerY = height / 2

CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
let baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer)?.assumingMemoryBound(to: Float32.self)
            
let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
let pixelIndex = Int(centerY) * bytesPerRow / MemoryLayout<Float32>.stride + Int(centerX)
            
let depthValue = baseAddress?[pixelIndex]
            
CVPixelBufferUnlockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
            
if let depthValue = depthValue {
    let distanceInMeters = Double(depthValue)
    print(distanceInMeters)
}
```

>0.3746262788772583

**0.37mなので、37cm離れています。画面中央のうさぎまでの距離。**
後ろの壁は３〜４m離れていますが、測定できました。正確です。

### smoothSceneDepthとsceneDepth
sceneDepthはlidarのプリミティブな値、
smoothedSceneDepthは、
>時間の経過とともに深度データを平滑化し、フレーム間のデルタを軽減する

ということで、smoothedSceneDepthの方が安定して距離を測る方が良さそうです。

🐣
****
フリーランスエンジニアです。
AIについて色々記事を書いていますのでよかったらプロフィールを見てみてください。

もし以下のようなご要望をお持ちでしたらお気軽にご相談ください。
AIサービスを開発したい、ビジネスにAIを組み込んで効率化したい、AIを使ったスマホアプリを開発したい、
ARを使ったアプリケーションを作りたい、スマホアプリを作りたいけどどこに相談したらいいかわからない…

いずれも中間コストを省いたリーズナブルな価格でお請けできます。

お仕事のご相談はこちらまで
rockyshikoku@gmail.com

機械学習やAR技術を使ったアプリケーションを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
【csh】foreachでプロセス稼働確認・一括プロセスkillの実装

# cshってfor文ないんだって...
世の中色んなプログラミング言語がありますけど、
for文がない言語なんてあるのでしょうか？

それがあるんです。
ズバリ**csh**

cshはfor文がありませんが、
ループ構文が無いわけではありません。

代わりに用意されているのがforeachとなります。

## foreach

```shell:基本構文
foreach 変数 ( リスト )
    コマンド
end
```

foreachは()内でリストファイルの中身を一つずつ取り出し、
指定した変数に値を格納します。
リスト内からすべての値を取り出したらループ終了です。

### リストに変数の値を使用する
リストはスペース区切りで判定されます。
なので変数に以下のように値を定義することで、
foreachで扱えるリストが作成できます。

```shell
set lists = "test1 test2 test3"
```

この仕組みを利用して以下のような処理作成してみました。

## プロセス確認を行う

```shell:プロセス起動有無確認
set processes = "OneDrive firefox"

foreach pname(${processes})
	set pcount = `ps aux | grep "${pname}" | grep -v "grep" | wc -l`
	if ( 0 < $pcount ) then
		echo "${pname}：稼動状態"
	else if ( $pcount == 0 ) then
		echo "${pname}：停止状態"
	else
		echo "カウント値が不正です"
	endif		
end
```
**処理概要**
プロセス名は任意ですがここでは"OneDrive"と"firefox"とします。
- 変数"process"に起動有無を確認したいプロセス名をスペース区切りで定義します。
- 変数process内の値をforeachで取り出し、変数pnameに格納します。
- psコマンドの出力結果をgrepで絞ります。同名のプロセスが稼働していれば"wc -l"で行カウントされます。
- カウントの結果を変数pcoutに格納しif文で判定処理を行います。

```shell:実行結果
OneDrive：起動中
firefox：起動中
```

## リストから一括でプロセスkillを行う

```shell:一括kill
set processes = "OneDrive firefox"

foreach pname($processes)
    set pid = `ps aux | grep "${pname}" | grep -v "grep" | awk '{print $2}'`
    kill -15 $pid	
end
```
基本はプロセス確認と同じです。
awkでPIDを抜き出して、そのPIDに対してkillしています。

# 余談
Unix系のforは他のPG言語と異なり、
ちょっと変わった書き方をしますが、
その面cshの書き方はわかりやすいですね。

~~cshはC言語っぽい書き方を特徴としているため、
生粋の開発者からすると他のシェルよりも書きやすいのかもしれませんね(私は開発者ではないですが、、、)~~
追記：cshはシェルスクリプトには向かないそうです。詳細はコメント欄

自分が運用などで面倒を見たシステムなどはなぜかcshでスクリプトが記載されていることが多いですが(ログインシェルはcshではないのに...)ここら辺が起因しているのだろうか？
android-example-appの最新でビルドできない暫定対処方法(2023/09/13時点)


下記のコミットで大幅に環境に変化があったようです
https://github.com/elixir-desktop/android-example-app/commit/0e105ffd804ac695c89e55609e0cc31cdd3160e2

そのため、それより一つ前に戻します

```
$ git log
```

ログの結果
```
commit c297212d7264245c32989a08bc90ef770ffef452 (HEAD -> master, origin/master, origin/HEAD)
Author: Dominic Letz <dominic@diode.io>
Date:   Fri Jul 21 16:29:58 2023 +0800

    Added measurement

commit 0e105ffd804ac695c89e55609e0cc31cdd3160e2
Author: Dominic Letz <dominic@diode.io>
Date:   Fri Jul 21 12:29:32 2023 +0800

    Updated gradle

commit b6ea5317791cd52bdc0f6ced510558a976639719
Author: Dominic Letz <dominic@diode.io>
Date:   Fri Sep 2 14:25:14 2022 +0200

    Added note on branding

```

Updated gradleでうまくビルドできない為、 Added note on brandingに戻します

```
$ git reset --hard b6ea5317791cd52bdc0f6ced510558a976639719
```


この後は、Android Studioを起動してリビルドしてください
JSTQB Foundation Level受験記録

## JSTQB認定テスト技術者資格 Foundation Levelの試験に合格しました
ソフトウェアテストの認定資格である、JSTQB認定テスト技術者資格のFoundation Levelを受験して、無事合格しました。（受験料が22,000円とお高めだったのでひと安心）
情報が少なめの資格のように思えたので、これから受ける人の参考になればと思い、受験の記録を記載します。
JSTQBのテストについてはJSTQBの公式サイトをご覧ください。

https://jstqb.jp/attribute.html

## なぜ受けたか

[ソフトウェア品質を高める開発者テスト 改訂版 アジャイル時代の実践的・効率的でスムーズなテストのやり方](https://www.amazon.co.jp/gp/product/B09YTSXFW8/ref=ppx_yo_dt_b_d_asin_title_o07?ie=UTF8&psc=1) という本を読んでいたところ、テストに関する定義などをしている機関としてJSTQBが登場し、興味を持って調べ、試験を知りました。現職ではテストでのバグ発見率を褒めていただくことがあるものの、客観的に能力を測ることはできていないことと、場当たり的なテストをしてしまっているという思いがあったため、客観的な能力を知り、テストに関する体系的な知識を身に付けたいと思い受験してみることにしました。

## どのくらい勉強したか

３週間くらい仕事の前後や休日に少しずつ勉強をしました。そこまで勉強量は多くなかったと思います。

## どうやって勉強したか
JSTQBのサイトにある公式の[シラバス](https://jstqb.jp/dl/JSTQB-SyllabusFoundation_Overview__Version2018.J01.pdf)と、他の方のブログで知ったJSTQBの勉強用のアプリ([テス友](https://jstqb.jp/dl/JSTQB-SyllabusFoundation_Overview__Version2018.J01.pdf))を使って勉強しました。

私の場合は、仕事でテストも担当しておりある程度知識があったため、以下のような勉強をしました。
1週間目：テス友の問題を解いてみる。移動時間などに少しシラバスも読む。
2週間目：シラバスをノートにまとめる。時間がある時はテス友の問題も少し解く。
3週間目：前半でノートのまとめが終わったため、後半はまとめたノートを読み返しつつ、テス友の問題を1日20問くらい解く→知識の怪しい部分はシラバスやノートで復習。


電子ノートを試してみたくてiPadとApple Pencilを買ったことを除くと、コンビニでシラバスを印刷する数百円しかかかりませんでした。受験料は高いですが、勉強代は安かったです。（そして電子ノートはとてもよかったです。iPadを買ったかいがあった！）

## 予約
Foundation LevelはCBT形式で、実施日が決められているわけではなく、空いていれば好きな日を予約して受験することができます。
私は、勉強２週間目で、おそらく来週受けて大丈夫そうだなと思ってから予約したのですが、受験24時間前までキャンセルできるそうなので、早めに予約した方が安心だったなと思いました。

## 当日
新宿のテストセンターで受験しました。色々な種類のテストを受けている人がいる部屋に通され、PCで４択問題を解いていきます。結果は当日はわからず、公式では２週間くらいかかるとのことでしたが、私の場合は4日くらいでメールで結果が届き、２週間くらいで合格証も届きました。

## 特に勉強になったこと
・テストの種類と定義についてきちんと理解することができました。（例えばブラックボックステスト・ホワイトボックステストは言葉は知っていましたが、意味を間違えてとらえていました。）
・テストのプロセスについて知ることができました。（仕事では、テストケースを作成→実施くらいの認識しかありませんでしたが、テスト対象の分析やテスト完了後の分析や次回に向けたメンテナンスも必要であることがわかりました。）
・「テストの７原則」が、あるある〜と思うのものが多く、おもしろかったです。
・理想論ではなく、結構リアルな内容となっており、例えば「バグが発見されると開発者は責められたような気持ちになってしまうので、バグを産んだ開発者を責めてはいけない。良いプロダクトを作るという共通の目標に向かって客観的な態度でバグを報告するのがよい」や、「テストが完了基準に達していなくても、ステークホルダーがそのリスクを認めればテストが終了することもある」などの記載もありました。特にテストの心理学の部分は、チームとして働く上で、開発メンバーに配慮してテストや報告を行う必要がある、逆にテスト専任の担当者は情報共有がされない場合があるので早い段階からレビューなどに参加することでテストの効果を高めることができるなど、勉強になりました。
・レビューの際に、各担当者が、ステークホルダーの観点になりきってレビューをしつつ、本来の自分の役割で成果物を作成する「パースペクティブレビュー」が最も効果的とされているということで、機会があれば取り入れてみたいと思いました。

## これから
JSTQBの試験を知るきっかけとなった[ソフトウェア品質を高める開発者テスト 改訂版 アジャイル時代の実践的・効率的でスムーズなテストのやり方](https://www.amazon.co.jp/gp/product/B09YTSXFW8/ref=ppx_yo_dt_b_d_asin_title_o07?ie=UTF8&psc=1) を読むのを再開して、引き続きテストへの理解を深めたいと思います。
日本語に見る変数名を考えることの難しさ

プログラミングをしていると、「この変数の名前どうしようかなぁ。せや、いったん```temp```にしちゃえ！」とやってしまうことがあると思います。

もちろんよくありません。

ただ、個人的なコーディングの中でお試しで動かしたいときにまで、ちゃんとした変数名を考えるのは面倒くさいですよね。ただとはいっても、後日それを見返すと、その```temp```という変数が何を表した変数なのかわからなくなってしまうことがありますよね。あるいは他人が書いたコードをレビューしていたりする時にこの```temp```ってなんだっけ？となりがちです。

結局あとでコードを見返して```temp```の意味を改めて理解して、```temp```ではなくて意味のある変数名を考えて```temp```を使ってしまっていた部分のコードを書き替えて、、、ということをやっていると結局、最初からちゃんと考えて名付けた変数を使っていた方が効率的だった、ということになります。


ということがあった時に気づいたのが、**これと同じことが一部で起きてしまったのが日本語の文字なのではないかなぁという妄想です。**（文献などで調査したわけではないので、あくまで個人的にひらめいてしまったレベルのコトです。）


例えば、「漢字の『2を意味する二』と『カタカナのニ』」です。どっちも同じ見た目に見えます。（というか筆者はこれの違いを画面上では判別できないです。）カタカナを最初に考えていた人はもしかしたら、```temp```のように一時的に数字の「二」を「ニ」として書いていたらいつの間にかそれが定着してしまって後戻りできなくなってしまったのではないでしょうか？


漢数字の二とカタカナのニのようにすでに定着してしまったものはもうどうしようもないですが、プログラムを書くときは、未来の自分に向けてまたはコードを見てくれる他人のために、変数の名前はちゃんと考えたものにしたいですね（という自分への戒めです）。
LXDコンテナ内から対外に飛ばない場合の対処法

## 目的
lxdを構築した場合に、コンテナ内から対外へ接続できない場合がある。その対処法を備忘録を残しておく。

## ホスト側で実行
```bash
sudo iptables -P FORWARD ACCEPT
```

これだけでコンテナから対外(インターネット)へ疎通が通る。