OmniAICreator/Qiita-1.07M huggingface dataset:
Python開発をnpm風に始める最短ルート – PDM入門

# はじめに

Python開発の依存管理に「Poetry」や「pipenv」を使ったことがある人も多いはず。

しかし、Node.js の `npm` / `yarn` に慣れている人からすると、Poetry はカチッとしすぎるし、pipenv は普及力にかける...

そんな中、最近人気が出ているのが `PDM (Python Development Master)` です。

* `npm install` のような簡単なコマンド
* `npm run` のようなタスク定義
* `pyproject.toml` だけで完結
* モジュール化も自由

この記事では「PDM とは何か」から、「これぞ、Python の npm だと思った理由」まで簡潔に紹介します。

# PDM とは？

PDM (Python Development Master) は、PEP 582 / pyproject.toml 基盤の現代的パッケージ管理ツールで、

* Poetry ほどカチッとしておらず
* pipenv より深くモダン

な「続けられるツール」として人気を集めています。

https://pdm.fming.dev/latest/

**🌐 Node.js との対応関係**

| 機能                | npm / yarn             | PDM                   |
| ----------------- | ---------------------- | --------------------- |
| init              | `npm init`             | `pdm init`            |
| install package   | `npm install axios`    | `pdm add requests`    |
| uninstall package | `npm uninstall axios`  | `pdm remove requests` |
| run script        | `npm run start`        | `pdm run start`       |
| lock file         | `package-lock.json`    | `pdm.lock.toml`       |
| 使用環境              | global / node\_modules | ローカル環境 or PEP 582     |

#  PDM のセットアップ

**Windows**

```bash
powershell -ExecutionPolicy ByPass -c "irm https://pdm-project.org/install-pdm.py | py -"
```

**Mac**

```bash
curl -sSL https://pdm-project.org/install-pdm.py | python3 -
```

# プロジェクトのセットアップ

### 1. プロジェクト初期化

```bash
mkdir my-app && cd my-app
pdm init -n
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760374/15a60b07-5538-492f-87db-5737bc502b64.png)

### 2. 依存関係の追加

```bash
pdm add requests
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760374/d75415af-3b98-4017-ab68-cf847d28077d.png)

### 3. スクリプト実行

```py:main.py
import requests

def main():
    res = requests.get("https://httpbin.org/get")
    print(res.status_code)

if __name__ == "__main__":
    main()
```

```bash
# 実行
pdm run python main.py
```

# npm run 風にコマンド定義

```toml:pyproject.toml
# 下記を追加
[tool.pdm.scripts]
start = "python main.py"
```

```bash
# 実行
pdm run start
```

# まとめ

* やっと出てきた「本当の npm 風エンジニア向け」Pythonツール
* ライブラリよりアプリ開発者向け
* 試してみる価値あり

**🌟 PDM の良いところ**

* `npm run` 感覚の task runner
* パッケージにしなくてもOK
* Poetryよりライト
* pip / venv / pipfile からの移行も楽
* 開発者のアプリに最適

**🚫 PDM が合わない場合**

* 現時点では CI/CD のテンプレートが少なめ
* まだ少数派（Poetryの方が社会的デファクト）
* PyPI への公開ライブラリ開発なら Poetry が精密

補足：Poetryのご紹介はこちら：

https://qiita.com/oharu121/items/bb2ad2a89549db373af5
just-agentsでLM Studioのmistral-small3.2を使ってみた

## 概要

mistral-small3.2が出てたので、LM Studioでダウンロードして、just-agentsからローカルで使ってみた備忘録です。

なお、just-agentsはシンプルなAIエージェントのライブラリです。

* just-agents: https://github.com/longevity-genie/just-agents
* mistral-small3.2: https://lmstudio.ai/models/mistralai/mistral-small-3.2

## コード

```python
import base64
import urllib

from just_agents.base_agent import BaseAgent
from just_agents.data_classes import ImageContent as _ImageContent
from just_agents.data_classes import Message, Role, TextContent
from pydantic import AnyUrl


class ImageContent(_ImageContent):
    image_url: AnyUrl


def describe(url: str) -> str:
    llm_options = {
        "model": "lm_studio/mistralai/mistral-small-3.2",
        "api_base": "http://localhost:1234/v1",
        "api_key": "_",
    }
    agent = BaseAgent(llm_options=llm_options)
    with urllib.request.urlopen(url) as fp:
        b64 = base64.b64encode(fp.read()).decode("utf-8")
    message = Message(
        role=Role.user,
        content=[
            TextContent(text="画像の説明"),
            ImageContent(image_url=f"data:image/jpeg;base64,{b64}"),
        ],
    )
    return agent.query(message, remember_query=False)


print(describe("file:///path/to/some.jpg"))
print(describe("https://path/to/some.jpg"))
```

## 解説

just-agentsにはImageContentというのがあるので、これを使ってみましょう。
ローカルのLLMの場合は、画像をbase64で渡す必要があるようです。
実際に実行すると、下記のようなエラーになります。

```
pydantic_core._pydantic_core.ValidationError: 1 validation error for ImageContent
image_url
  URL should have at most 2083 characters [type=url_too_long, \
  input_value='data:image/jpeg;base64,/...', input_type=str]
    For further information visit https://errors.pydantic.dev/2.11/v/url_too_long
```

調べると、[ImageContent.image_urlの型がHttpUrl](https://github.com/longevity-genie/just-agents/blob/32d53f2e4e721c096ebf6f8555e05bf34bd6b44d/core/just_agents/data_classes.py#L60-L62)で、文字列の長さが長いためPydanticでバリデーションエラーになってようです。

今回は、下記のように無理やりAnyUrlに変えて回避しました。

```python
from just_agents.data_classes import ImageContent as _ImageContent
from pydantic import AnyUrl

class ImageContent(_ImageContent):
    image_url: AnyUrl
```

軽いモデルですが、わりと良さそうな印象でした

以上
【学生必見】試験勉強で生成AIに依存してはいけない理由

# はじめに
今回は学生の試験勉強において生成AIを多用しすぎることによるデメリットとその対応策（使い分け）についてまとめていきたいと思います。
かなり個人的な主観が強いので参考までに！

# 生成AIの危険性
みなさんは試験勉強で生成AIを使ったことはありますか？僕は課題の答え合わせや、過去問の解法が分からなかった時に使用しています。最近のAIの精度だと学生の課題レベルの問題ならほとんどあっていますしね。

しかし、生成AIの使用には大きなリスクが伴います。それは**インプットだけで満足してしまう**という点です。

よく僕もやってしまっていたのが、分からない問題の解法を出力させて写経だけして分かった気になっていることですね。ただ、「読んで理解できる」のと「試験でアウトプットできる」というのは別の話です。無論、試験では悲惨な点数が返ってきました。

勉強の本質は「**脳に負荷をかけること**」であるため、今まで生成AIなしでもできていたことを任せてしまうと学習になりません。

# 個人的な使い分け
基本的に生成AIには「今までできなかったこと」や「時間がかかっていたけど学びが少なかったもの」の処理を任せるといいでしょう。個人的には以下のように使い分けています。

### AIに任せているもの
- 解ききった課題の答え合わせ
- 過去問の模範解答の作成
- 過去問を学習させた類似問題の作成
- 考えても分からない、かつ解法の載っていない教科書問題の解説
- 1問1答の作成

### 自力で続けているもの
- 用語まとめ
- レポートの文章作成

# おわりに
今回の記事の使い分けはあくまで「学習のため」という目的を基準に考えているため、自身の目的に合わせてカスタマイズしてみてください！
JavaScriptのCustomEventでイベントを自作する


# CustomEvent の解説

## CustomEvent とは？

`CustomEvent` は **自分で名前をつけた独自のイベント** を作成するためのオブジェクトです。
ブラウザの標準イベント（例：`click`、`keydown`、`submit` など）とは別に、アプリの都合に合わせて「特別な合図」を送ることができます。

---

## 書き方の基本

```javascript
// CustomEvent の作成
const event = new CustomEvent('イベント名', {
  detail: データ // イベントと一緒に渡す追加情報（オプション）
})

// イベントを発火（dispatch）
window.dispatchEvent(event)
```

---

## 例：ファイルアップロード用イベント

```javascript
// CustomEvent の作成
const uploadEvent = new CustomEvent('trigger-file-upload', {
  detail: { fileType: 'image', maxSize: 10 }
})

// 発火
window.dispatchEvent(uploadEvent)
```

受け取る側のコード例：

```javascript
window.addEventListener('trigger-file-upload', (e) => {
  console.log('アップロードイベントを受け取りました！')
  console.log('詳細データ:', e.detail)
})
```

---

## CustomEvent の特徴

- イベントと一緒に **好きなデータ（`detail`）** を送れる。
- window だけでなく、任意の DOM 要素でも使える。
- 標準イベントと同様に `addEventListener` で監視できる。
- コンポーネント間の疎結合な連携に便利。

---

## 注意点

- イベントの名前は衝突しないようにユニークにする。
- 大規模アプリでは乱用を避け、整理して使う。
え、これって`true`なの！？ReactのJSXプロパティ、暗黙の了解にご用心！

# はじめに

Reactでコンポーネントにプロパティを渡すとき、「`true`」とか「`false`」ってちゃんと書いてますか？もしかして、

```jsx
<MyComponent myProp />
```

みたいに、プロパティ名だけ書いちゃってませんか？実はこれ、自動的に「**`true`**」ってことになっちゃってるんです！

これ、最初は省略できて，綺麗で便利だと思うんですけど、後々「あれ？この値ってどこから来たんだっけ…？」って迷子になる原因になりがちなんです。

# 歴史
## HTMLにもある「空気読んで`true`」文化

HTMLにも，一部の属性は値がなくても「ある」ってだけで`true`扱いになるんです。

例えば、チェックボックス。

```html
<input type="checkbox" checked>
```

これ、「`checked="checked"`」って書かなくても、`checked`って書いてあるだけでチェックが入りますよね？「`checked`属性がある＝チェック済み」って、HTMLが気を利かせてくれてるわけです。

https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Elements/input/checkbox

https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes

### JSXもHTMLに倣っちゃってる！

ReactのJSXも、このHTMLの「空気読んで`true`」文化を引き継いでるんですよ。JSXって、JavaScriptの中にHTMLっぽく書ける便利なやつですよね。結局はJavaScriptに変換されてReactがコンポーネントを組み立てるわけですが、その変換のときにHTMLの属性と同じように、JSXのプロパティも値が書いてないと\*\*`true`\*\*として扱われちゃうんです。

だから、

```jsx
<MyComponent myProp />
```

って書いた場合、Reactの裏側では

```jsx
<MyComponent myProp={true} />
```

って解釈されてるってことです。プロパティ名だけ書けば`true`をとして扱ってくれるってことなんですね。

https://legacy.reactjs.org/docs/jsx-in-depth.html#props-default-to-true


### 「明示的」が結局一番の近道！

この「値がないから`true`」って機能、コードをスッキリさせられるのは確かです。でも、個人的にはこれ、**後で自分が苦しむパターン**が多いなと感じてます。

`myProp`って書いてあるだけだと、この`myProp`が`true`なのか`false`なのか、それとも何か別の値が入る可能性があるのか、パッと見じゃ全然わからないじゃないです。特に、数ヶ月後に見返したり、チームの別の人がコードを読んだりするときには、かなりの「？」を生み出すことになります。

**僕が今回、この記事を書こうと思ったのも、この「値がないから`true`」のプロパティを探すのにめっちゃ時間かかったからなんです！**

だから、僕からの個人的な感想では，boolean値を渡すプロパティには、**`true`か`false`かをちゃんと明示的に書いてあげましょう！**

```jsx
// 断然こっちがオススメ！
<MyComponent myProp={true} />
<MyComponent anotherProp={false} />

// ちょっと待って！あとで後悔するかも…
<MyComponent myProp />
```

ちょっと手間に感じるかもしれませんが、ちゃんと`{true}`とか`{false}`って書くことで、**そのプロパティが何を意味しているのか、一目瞭然になります。**「あ、これはこういう時に`true`になるやつね！」って、未来の自分やチームメンバーが秒速で理解できるようになるはずです。

結果的に、デバッグの時間も減るし、コードの意図が伝わりやすくます！
より読みやすいコードを目指しましょう！
良いコード／悪いコードで学ぶ設計入門 第１６章

![猫と共にコードを書く開発者.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357904/b4f2f387-e0ee-4d23-8827-9c75e7bca832.png)

# 第16章 設計を妨げる開発プロセスとの戦い

この章では、開発現場で設計の品質を損なう要因として「開発プロセス」そのものがどう関わってくるかを多角的に掘り下げています。技術の話だけでなく、チームや組織、心理や文化にまで踏み込んだ内容は、読みながら自分自身の現場を何度も思い出すものでした。

---

## コミュニケーションと設計の密接な関係

**コンウェイの法則**と**逆コンウェイの法則**が紹介され、「チーム構造＝プロダクト構造」という現実から逃れられないことがよく分かります。コミュニケーションのしづらさが、コード構造の歪みに直結する——これは理屈ではわかっていても、実際の現場ではなかなか解決が難しいテーマです。

ここで強調されるのが「**心理的安全性**」の大切さ。声をあげられないチームに健全な議論は生まれません。何よりもまず「発言できる場」をつくる。これが最初の一歩であり、かつ一番難しい。

---

## 「早く終わらせたい」の罠と設計の本質

現場でしばしば見かける「スピード重視」の空気。動くコードが早く出てくると、なぜかチームの空気が和らぎ、評価もされがちです。でもそのコードは、果たして半年後も保守可能なものなのでしょうか？

TDDの導入が実装速度に良い影響を与えるという実験結果は、設計とスピードが対立しないことの示唆に富んでいます。個人的には「実装が早い＝設計が良い」の裏付けをもらったような気がしました。

また、「クラスを増やすとパフォーマンスが落ちる」という意見が、未だに根強いことにも驚かされます。ここでは「**早すぎる最適化**」というアンチパターンを避けるためにも、計測と根拠を大切にすべきだという教訓が提示されます。

---

## 設計ルールとチーム力の関係

設計ルールを「多数決」で決めることの危険性には思わず頷いてしまいました。経験の浅いメンバーの反対でルールが成立しない……そんな経験、ありませんか？

ルールづくりは**シニアエンジニアの責務**であり、意思をもって導くべきもの。そして、そのルールには「**意図**」や「**背景**」を明示することで初めて、形骸化せず意味あるものとして運用できます。設計とは「ルールを守ること」ではなく「ルールを育てること」でもあると感じました。

---

## 実装と品質の細やかな戦い

**割れ窓理論**と**ボーイスカウトの規則**は、すでに耳慣れた概念かもしれませんが、改めて実装に置き換えて読むと、現場での「ちょっとした気遣い」がコード全体の品質を左右することに気付かされます。

誰かが意図的に割った窓には、その理由を記しておく。そこには“壊した責任”を明確にする覚悟があります。また、「なぜこの実装なのか」という説明がコミットメッセージにあると、未来の仲間たちがきっと救われます。

既存コードに潜む**アンカリング効果**や**ジョシュアツリーの法則**の話も興味深く、「目にしているのに気付けていない」ことの恐ろしさにハッとさせられました。

---

## コードレビューという文化を育てる

レビューが単なるチェックリストではなく、**チームの設計力を育てる場**であるという意識は、とても大切な視点です。

特に印象的だったのは、「レビューにおける敬意と礼儀」についてのパート。**Google Chromiumのレビュー指針**は、レビューを文化として根付かせる上で非常に参考になります。

> 「能力と善意を想定する」

この一文だけで、レビューの空気はがらりと変わるはずです。褒めるコメント、感謝のコメントがあるだけで、レビューが「指摘」から「対話」に変わります。

---

## チームの設計力を育てるためにできること

設計力の底上げには、「**仲間集め**」と「**小さな実感**」がキーワードです。クープマン目標値という現実的な指標も登場し、ボトムアップの活動にも希望が持てます。チーム20人なら2人が旗を振ればいい。そう考えると、やれそうな気がしてきます。

そして「実感」の大切さ。改善前と改善後を**自分の手で比べる**こと、そしてその変化を**共有する**こと。この体験が、設計力の芽を育てていきます。

---

## 設計活動を浸透させる仕組み

**勉強会**の活用方法として、単なる読み合わせでなく、手を動かし、改善を共有する形式が推奨されているのは非常に実践的です。参加者それぞれが普段触れているコードを使うことで、自分事として捉えられるのも良い工夫です。

また、**リーダーやマネージャーへの説明**の重要性にも触れられています。変更容易性の価値を伝えるには、一人で戦うのではなく、仲間と共に向かう。これは心強い言葉でした。

最後には「**設計責任者**」という役割の明確化の話も出てきます。全員が設計に強くなくても、誰かが意識しているだけで、チームの設計意識は段違いに変わるはずです。

---

## おわりに

この章は、「設計とは単なるコードの話ではない」というメッセージに溢れています。チームの空気、レビューの文化、組織との関係性、学びの共有。それらすべてが設計を良くする土台となる。

設計品質を高めるには、設計だけに注目していてはダメなんだ。そう気付かされる、まさに「設計と戦う」ための実践知が詰まった章でした。
Entra Connect バージョンアップ

・アップグレードの推奨事項
本番環境での直接アップグレードは非推奨。

推奨手順：ステージングサーバーを利用した「スイング移行」。

新サーバーで構成して切り替えることでダウンタイムを最小化。

・ステージングモードとは？
Entra Connect の同期機能を停止した待機モード。

スケジューラーやエクスポート処理を無効化した状態で、他設定（インポート/同期）は通常通り実行。

主に以下の目的で使用：

障害時の代替同期サーバー

バージョンアップや構成変更の事前検証

ゼロダウンタイムでのサーバー移行

・ステージングサーバー活用の具体例
サーバー移行・バージョンアップ
新サーバーに最新バージョンをインストールし、ステージングモードで構成。

旧サーバーの同期停止 → 新サーバーを本番へ切替（スムーズな移行）

障害対策（冗長構成）
本番と同じ構成のサーバーをあらかじめ待機させておき、障害時に即時切り替え可能。

テスト用途
フィルター変更やルール調整の影響を本番に影響させず検証可能。

・ステージングモードの注意点
同時にアクティブな Azure AD Connect サーバーは1台のみ	
複数台が同時にエクスポート処理を行うと 競合が発生
ステージング解除はGUIまたは PowerShellで可能	Set-ADSyncScheduler -SyncCycleEnabled $true など
ステージングモードでも同期ルールの適用状況や差異は確認可能

・主なポイント
1. バージョンアップの重要性
古いバージョンはサポート終了・脆弱性の対象。

Microsoft は最新バージョンの使用を推奨。

・アップグレード方法の選択
方法①：インプレースアップグレード（同一サーバー）
手軽だが、失敗時にロールバックが難しい。

メリット：構築の手間が少ない。

デメリット：同期が止まるリスクがある。

方法②：新サーバーへの移行（推奨）
ステージングモードでの構築 → 切り替え。

ゼロダウンタイムでの移行が可能。

安定性・保守性に優れる。

・新サーバー移行手順（ステージングモード使用）
ステップ	内容
①	新サーバー準備（OS要件と前提条件を確認）
②	最新版の Entra Connect をインストール
③	既存構成に基づいてセットアップ（同期対象OU・フィルタなど）
④	ステージングモードでインストール
⑤	同期差異の検証（「CSExportAnalyzer」等で比較）
⑥	旧サーバーの同期停止、ステージング解除して切替
⑦	新サーバーで運用開始、旧サーバーはアンインストール or 待機用に保持

・検証と確認方法
同期差異は「同期サービスマネージャー」または Get-ADSyncConnectorRunStatus コマンドなどで確認。

イベントビューアーのログや「Microsoft Entra 管理センター」で同期エラーを確認。

・バージョンアップの注意点
構成が複雑な場合は事前に PowerShell で設定のバックアップを取ること。

同期ルールのエクスポートを忘れずに。

グローバル管理者権限のアカウント使用。

ステージングモード切替時は慎重に。

同期ルールやカスタム構成は事前にエクスポートしておく。

SQL Server 使用時：バージョン互換性も確認。

TLS/証明書/ファイアウォール要件も考慮。
令和7年度春期ネットワークスペシャリスト受験体験記

## はじめに
この度、令和7年度春季に行われたネットワークスペシャリストを受験してきましたので、受験までの勉強方法や受験までに重視していた点についてご紹介しようと思います。

## 自分の情報
- 令和4年度の秋期に行われた応用情報技術者試験に合格
- 大学では情報工学を専攻し、2023年3月に大学院の修士課程を修了
- 令和6年度の秋期に行われたデータベーススペシャリスト試験を受験（残念ながら不合格、、）

## 受験のきっかけ
- ネットワークのプロトコルについて知っておくと、今後のプロジェクトで設計を行う際の基盤にできると考えたこと

## 勉強を通じて得られたこと
- ネットワークプロトコルで何をしているか
- ネットワーク構築の知識（DNSレコードの書き方や通信経路の冗長化の方法など）

## 学習方法
### 午前I対策
今回は試験免除が切れてしまったので、午前I試験を受験する必要がありました。
試験内容は応用情報技術者試験の午前問題のような問題が抜粋されて出題されているようです。
当初は過去に受験した応用情報技術者試験の勉強貯金で勉強無しで合格できると思ったのですが、
試しに1年分の過去問を受験したところ、割合としては66点で危なかったため、安全を取るため本格的に対策を行いました。
結果的には、過去問5年分と[応用情報技術者試験ドットコム様の過去問道場](https://www.ap-siken.com/apkakomon.php)で140問ほど解答しました。

### 午前II対策
午前II試験は本格的にネットワークに関する問題が選択式で出題されます。
1. [ネットワークスペシャリスト 合格教本](https://gihyo.jp/book/2023/978-4-297-13703-8)を一通り読んでネットワーク周りの知識をつける
2. [ネットワークスペシャリストドットコム様の過去問道場](https://www.nw-siken.com/nwkakomon.php)を使用して選択式の問題に慣れる
の順序で対策を進めました。
2.については問題の解説が見られるようになるのでプレミアムメンバーシップ（月額490円）に入会しました。
結果的には間違えた問題の解き直しも含め、400問近く解いて本番に挑みました。

### 午後I、午後II対策
合格教本を読むだけではどの分野が勉強不足なのか判断を付けられなかったため、過去問を解くことに集中しました。
5年分にあたる午後I試験(15問)、午後II試験(10問)の過去問を解き、勉強が足りない分野が分かるようにしました。
この結果、問題ごとにも傾向があるように感じました。例えば、
1. 問1の(1)の問題は穴埋め式であり、傾向的に出やすく、以下は2、3回問題内で問われることがあった。
    1. DHCPリレーエージェント
    1. フラッディング
    1. SNMP Trap
1. 各大問単位のうち、出やすい分野が顕著にあり、以下は2、3回問われることがあった。
    1. BGP
    1. OSPF
    1. VRRP

午後Iは3問中2問、午後IIは2問中1問解ければよいため、本試験ではよく出題される分野を抑えておくことが重要だと感じました。

また、文章を記述する問題にも傾向があるように感じました。
個人的に感じた傾向は以下となります。
1. 約80~85%は問題の中にヒントがあるので、この内容に基づいて回答する
1. 約15~20%は問題の中には無く、自分で新規に回答する（例えば「対処法の例を述べよ」といった問題など）

問題の問いを読み前者と後者の問題のうちのどちらに当てはまるかを肌感覚として識別できれば回答スピードは速くなると思いました。

## 結果
結果発表は2025年7月3日のため、少々お待ちを、、、
llama-cpp-pythonインストール時に発生したビルドエラーの解消法

```
pip install -U llama-cpp-python
```
上記コマンドを実行し、
```
ERROR: Failed building wheel for llama-cpp-python
Failed to build llama-cpp-python
ERROR: Failed to build installable wheels for some pyproject.toml based projects (llama-cpp-python)   
```
このようなビルドエラーが起きた場合の対策を記します。

ビルドエラーが起きる原因は、
Visual Studio の C/C++ ビルド環境（nmake / cl.exe）と CMake が入っていないからです。
なので、入れてあげましょう。

以下URLを開く
https://visualstudio.microsoft.com/ja/downloads/

無料ダウンロードボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3983698/c3688020-f7ee-48f4-90a4-383bfc352d62.png)

ダウンロードしたexeファイルを起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3983698/50e9ce3f-2fbd-492e-a985-e23d27f685a6.png)

続行ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3983698/17a5464f-0b56-4bb4-9ba8-0101910cbfd0.png)

インストールするものを選択画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3983698/5885c7c4-0a9c-491a-ae64-d2785418c99b.png)

ワークロードの「C++によるデスクトップ開発」と
個別コンポーネントの「Windows用 C++ CMakeツール」を選択し、
インストールしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3983698/e5af8df7-6139-443e-bc01-824aced81904.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3983698/5a3666cb-c587-4ea4-b1cd-da46158d33fc.png)

以上です。
インストール後は再起動する必要があるのでお気をつけて！
50 個記事を書いてみてわかったこと

# はじめに

１年ほど毎週記事を投稿してみたので、ポエムでも書こうと思います。

たくさん記事を書くのは苦労の割に、得られたものは少なかった印象で、ここらが潮時だと感じました。

## コーディングのアドバイス系の記事は書くのはとても大変

自分の原点とも言えるのが [Effective C#](https://www.amazon.co.jp/Effective-6-0-7-0-Bill-Wagner/dp/4798153869?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=2KRIX6IZ4Q5S0&dib=eyJ2IjoiMSJ9.BxleMjT-ravoJ--H7Vsnctdpj1u2mxDMyolW_XwyQczVyB8FfpAv_Di39JSxGEJWf9PJi2k0WmZr0bppk-VDAjN8jNltgywny3jhFZmIh0nRXBuT1ijPbcumPLA_ViKEwmImiRA9KUfiLww9Cdx20WFX2Gj4zmCnEH2lO8R1pO3MwenGrBXMnEhw9ALXUUUn8o9fagJDWQLME_WqKzN1zvwRRiMmRF6d0uC8ZbFbYVxh2d-o0OEwVVm8NTO7f-xcWpP91C3JuAmRUKV8y0o1hA69sACgiB9Al4b7fhDH6YE.d5lMaXobMzp6u_gDNgeXo5bYBxpKYLHVxgWAjST9kBA&dib_tag=se&keywords=Effective+C%23&qid=1750592102&sprefix=effective+c+%2Caps%2C167&sr=8-1) で、これはコーディングに役立つ考え方や専門知識が５０程度のアドバイスとして列挙されています。自分もこんな内容を書けたらいいなあと漠然と思っていました。しかしこれはとても大変です。

- 書籍になるレベルの知見と経験が必要
- コードやアドバイスに間違いは許されない

そもそも専門書としてお金を取るべき内容を個人ブログに書くのは無理筋です。

以前[記事には新規性がなければならないか？](https://qiita.com/abetakahiro123/items/d1e4b476058de3d20f71) と疑問に感じたのですが、これは記事として新規性はなくても面白ければいいんじゃないかという結論でした。アドバイス系の記事は新規性がなければいけません。

そこで自分はニッチなパフォーマンス関係に記事を見出したわけですが、これも一般的には答えが示されています。**時期尚早な最適化は避けよ**。

当初は記事を書き溜めて技術系の同人誌を出してみたいと考えていたのですが、いざ溜まったものを振り返ると本にするには微妙なものばかりです。やるなら内容を計画立てる必要がありました。しかしながらそうすると記事の投稿が続かなかった可能性もあるわけで、いずれにせよ難しいです。

## 記事のコメントがストレス

記事にコメントをいただくとメールでお知らせが来るのですが、これが非常にストレスでした。ポジティブな内容もネガティブな内容も同様にストレスでした。

- バグ報告はとてもありがたかった
- 「こうしたらいいんじゃないか」的な意見の中には、サンプルコードに書いてある内容の指摘もあった
- メール通知をオフにしても結局コメントは確認するため同じ

素性の知れない相手とコメント欄でやり取りするのは避けたい主義なので、基本的にコメ返しはしませんでした。放置するのは忍びないと思いつつ、反応する義務もないため自分が長続きする方針を優先しました。コメントは別のコメントを誘発するためここの見極めは難しいところです。

自分はそういう性格の人間なんだという知見は得られました。

## 自分のプロジェクトは進まなかった

自分が趣味で進めているプロジェクトで進捗が出ないのをなんとかしたい、という期待を込めて記事を書き始めました。実際はまったく進捗は出なかったです。

- 書きやすい記事（.NET 新機能の紹介等）を優先しがち
- 締切に追われて`重い記事` `書いたことのない分野の記事`を敬遠する
- いざ記事にしようとするとスクショを貼る以外に思いつかない

結局ひとつも記事に起こすことはありませんでした。今思えば発想が逆で、記事の題材としてプロジェクトを取り上げるのではなく、プロジェクトの広報として記事を書くべきだったのです。

記事を書いて得られる能力は**記事を書く能力**であると痛感しました。プロジェクトを進めたいのなら、プロジェクトを進める練習が必要です。

## おわりに

今回はネガティブな内容が主体になってしまいました。それだけ記事を書き続けるのは大変で、期待していた何かを自分は見つけられませんでした。  

よく耳にする**アウトプットは重要**という言葉は間違いないのですが、記事を書くならせいぜい５個も書けば十分と思いました。個人的にこの言葉は０を１にする重要性を説いていて、１を１０にするかは必要に応じてやるべきと感じます。

[2025 年の目標である毎週記事を更新して 50 記事を達成する](https://qiita.com/abetakahiro123/items/d06e1a1b838c03ecbd39#2025-%E5%B9%B4%E3%81%AB%E3%82%84%E3%82%8B%E3%81%93%E3%81%A8)はなんとかなったため、そこは良かったと思います。
【DATASaber】Tableau初心者が知っておきたい"一つの技"

DATASaberに挑戦中のいぐちです！
今回は2ヶ月強Tableauを使ってきてもっと初めに知っていたかったショートカットを紹介していきます！
1. ピルの複製
[windows] Ctrl + 左クリック + ドラッグ
[Mac]Command (⌘) + 左クリック + ドラッグ
上記のショートカットで以下のようにピルを複製できます。
![ピルのコピペ紹介1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4120283/84b399b8-9652-46fe-a517-243ffd514513.png)
![ピルのコピペ紹介2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4120283/3fd0845f-b2dd-4eb2-b5d4-08c19e8cdb84.png)
![ピルのコピペ紹介3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4120283/f64ff930-7a66-4488-912c-571b6929c50f.png)

　DATASaberのOrdの課題をクリアするため、DATASaberを目指している方は皆KTさんの動画を見ながら勉強をしていくと思います。この動画の中でKTさんがピルの複製を簡単に行われていました。私はCtrl + Cでピルをコピーし、Ctrl + vでコピペが出来ると思っていましたが、Tableauではコピペはこの方法では出来ません。
そのため、私は恥ずかしながら最近まで複製したいビューを1から再現して利用していました。しかし、Ordが進むにつれてビューの構成も複雑になっていき、1から再現するのが面倒になってきました。。。
そこで、やっとビューを複製するショートカットを調べたところCtrl + 左クリック + ドラッグでコピペ出来ることを知りました。このショートカットが個人的には１番使っており、もっと早く知っておけばよかったと思ったので紹介しました！
参照透過性ってなんだっけ

# 参照透過性ってなんだっけ？
ふと「参照透過性」てなんだっけ？と気になったので、色々考えたことをまとめてみる。

参照透過性を調べると「式をその値に置き換えてもプログラムの意味が変わらないこと」と出てくる。
参照透過性がある例はこんな感じ。
```kotlin
fun add(x: Int, y: Int): Int {
    return x + y
}

val sum = add(2, 3)
// これはadd(2, 3)の戻り値5に置き換えても意味は同じ
val sum = 5
```

そんなに特別なことじゃなくない？と思ったけど、参照透過性を満たさない例は普通にある。
例えば標準出力。

```kotlin
val x = println("Hello")
```
Kotlinの`println`の戻り値は`Unit`だけど、
```kotlin
val x = Unit
```
とは明らかに意味が異なる。

他にも、内部の状態を変更するような関数は参照透過性を持たない。
```kotlin
class Counter() {
    var i = 0
    
    fun increment() {
        i++
        return i
    }
}
```
この `increment()` という関数は
```kotlin
val counter = Counter()
val x = counter.increment() // x = 1
val y = counter.increment() // y = 2
```
だが、
```kotlin
val counter = Counter()
val x = 1 // 右辺を値に置き換えると
val y = counter.increment() // yの値が1に変わった！
```
明らかに意味が変わってしまう。

# 「副作用」が関係するらしい
関数の戻り値を返す以外の、状態を変化させるような操作を言う。
例えば、グローバル変数の値を書き換える、DBやファイルへの永続化、標準出力などが挙げられる。
また、関数の外部の状態を受け取ることも副作用と呼ぶようで、DBやファイルの読み取りも副作用である。また、乱数や現在時刻など、実行結果が都度変わってしまうようなものも副作用に含まれる。

副作用を持つような関数は参照透過にはならない。
参照透過性と副作用の概念は微妙に異なるはずだが、よくわからない。

# 冪等性とは違うんだっけ？
冪等性とは、同じ処理を何度繰り返しても結果や状態が変化しないこと。
HTTPメソッドの`PUT`と`PATCH`の違いとかで有名。

参照透過性を持つ関数は当然冪等性を持つ。
```kotlin
val x = someFunction()
val y = someFunction()
//もし x!=y ならば sumFunctionは副作用を持っている。
```

ただし、冪等性を持つ関数が参照透過性を持つとは限らない。
```kotlin
hoge.setValue(42)
hoge.setValue(42)
hoge.saeValue(42)
... //　何度繰り返しても hoge.value == 42
```
だが、`hoge`の内部の状態を変更しており、参照透過性はない。

# そもそも戻り値がUnitの関数は参照透過性を持ち得ない
`println()`もsetterも、戻り値がUnitである。
このような(実質)何も返さない関数は、何かしらの副作用を持つ処理を行っているはずで、そうなると参照透過性は持たない。
厳密には
```kotlin
fun doNothing() {}
```
という関数は参照透過性を持つが、何もしない関数を呼び出すことに通常意味はないので、戻り値がUnitの関数は参照透過性を持たないと考えてよい。

# オブジェクト指向のメソッドは?
ところで、Kotlinはオブジェクト指向の言語である。クラスに紐づくメソッドの扱いはどうなるんだろうか？
例えば、単純なgetterを見てみると
```kotlin
hoge.getValue() // 仮に111になるとする
hoge.setValue(222) 
hoge.getValue() // ここでは222
```

`hoge.getValue()`の値が変わっているので、参照透過性を持たないということになるのだろうか...？

さらに、クラスを引数に持つ場合はどうなるか？
```kotlin
class Point(val x, val y)
```
こういうクラスを引数に持つような関数
```kotlin
distanceFromOrigin(p)
```
を考える。これはどうなるか？
`Point`というクラスをValue Objectとして設計しておけば、参照透過性を持つと言っていいきがす。

そもそも、オブジェクト指向は「(隠蔽された)内部状態を持つクラスの振る舞い」を基に記述するし、対して関数型プログラミングは「（数学の関数のように)同じ引数に対して常に同じ戻り値を返す関数」を中心とするというような違いがある。
思想が異なるものを無理に当てはめようとしているので、わかりづらくなっている面がありそう。

# まとめ

「参照透過性」として「式が値に置き換えられる」と言う意味は大きく分けて2つありそう。
1つ目が、「戻り値の値以外、関数が意味のある処理を行なっていない」こと。
2つ目が、「同じ引数に対して、必ず（外部の状態などに依存せず）同じ値を返す」こと。

副作用とか純関数などの概念と関わりがあるので、きちんと改めて関数型プログラミングを勉強してみようと思った。
【Winston + Docker】バックエンド・フロントエンド・DBの実行ログを1日ごとにローテーションして保存する方法

# はじめに

開発中のプロジェクトで、以下のような構成でログを一元管理したくなりました。

- **バックエンド**：Node.js (Express)
- **フロントエンド**：Next.js (React)
- **DB**：PostgreSQL

そこで、Winston と logrotate 対応の `winston-daily-rotate-file` を使って、**ログを1日ごとに分割・保存**する仕組みを構築したのでメモします。

【ファイル構成】
```
project-root/
├── backend/
│   ├── log/
│   │   ├── backend-%DATE%.log
│   │   ├── db-%DATE%.log
│   └── ...
├── frontend/
│   ├── ...
├── docker-compose.yml
```


# Winston ログ設定（バックエンド）

バックエンドのログ設定は `backend/logger.ts` にまとめておくと便利です。

### インストール

```bash
npm install winston winston-daily-rotate-file
```

## logger.ts

```ts
import winston from 'winston'
import 'winston-daily-rotate-file'
import path from 'path'

const logDir = path.join(__dirname, 'log')

// 日ごとにファイルを分割
const createTransport = (filename: string) => new winston.transports.DailyRotateFile({
  filename: path.join(logDir, `${filename}-%DATE%.log`),
  datePattern: 'YYYY-MM-DD',
  zippedArchive: false,
  maxSize: '20m',
  maxFiles: '14d',
})

export const backendLogger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    createTransport('backend')
  ],
})

export const dbLogger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.simple()
  ),
  transports: [
    createTransport('db')
  ],
})
```


# Knex.js の SQL ログを出力する

Knex インスタンスにログ関数を渡せばOK。

```ts
import knex from 'knex'
import { dbLogger } from './logger'

const db = knex({
  client: 'pg',
  connection: {
    host: 'db',
    port: [ポート],
    user: '[ユーザー名]',
    password: '[パスワード]',
    database: '[DB名称]'
  },
  log: {
    debug(message) {
      dbLogger.info(`[SQL DEBUG] ${message}`)
    },
    warn(message) {
      dbLogger.warn(`[SQL WARN] ${message}`)
    },
    error(message) {
      dbLogger.error(`[SQL ERROR] ${message}`)
    },
  }
})
```

# フロントエンドのログをサーバーに転送

フロントエンド側でもエラーログやユーザー操作ログを収集したい場合、API 経由でバックエンドに送信→Winstonで記録できます。

## Next.js のエラーハンドラ例

```ts
// frontend/pages/api/log.ts
import type { NextApiRequest, NextApiResponse } from 'next'

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === 'POST') {
    const log = req.body
    // バックエンド側の logger を使って保存（プロキシや中継あり）
    console.log(`[ClientLog] ${JSON.stringify(log)}`)
    res.status(200).json({ message: 'Logged' })
  } else {
    res.status(405).end()
  }
}
```

クライアント側では `fetch('/api/log', { method: 'POST', body: JSON.stringify(...) })` で投げればOKです。


# Docker構成

Dockerコンテナ間でログファイルを永続化するため、`backend/log` はボリュームにしておきます。

```yaml
# docker-compose.yml
services:
  backend:
    volumes:
      - ./backend/log:/app/log
```

# おわりに

複数コンテナの環境でも、**ログの出力先・ローテーションポリシーを一貫して管理**することで、後々の運用がかなり楽になります。

バックエンド、DB、フロントエンドでそれぞれ必要なログを、**Winston + daily rotate**で安全に保存していきましょう。
何かしらの役に立ったら嬉しいです。
[Linux] システムログ設定_systemd-journald, /var/log/journal, /run/log/journal

# systemd-journald

| 項目                     | 内容                                                                     |
| ---------------------- | ---------------------------------------------------------------------- |
| **役割**                 | `systemd-journald` は systemd 環境における **ログの一元管理** を担うデーモン                |
| **ログの対象**              | - systemd によって起動されたプロセスの **標準出力 / 標準エラー出力**<br>- `syslog` メッセージなども受信可能 |
| **ログの形式**              | **バイナリ形式**（テキストではない）で保存され、`journalctl` コマンドで閲覧                         |
| **ファシリティ / プライオリティ対応** | syslog と同様に、**ファシリティ（送信元分類）** や **プライオリティ（重要度）** に対応                   |

# ログの保存先と永続化の設定

| 保存先                | 特徴                                                         |
| ------------------ | ---------------------------------------------------------- |
| `/var/log/journal` | - 永続ログ保存先<br>- 永続化には設定ファイルでの指定が必要            |
| `/run/log/journal` | - 一時ログ保存先（**デフォルト**）<br>- RAM上の tmpfs に配置され、**再起動で消去される** |



# 永続化設定手順（再起動後もログを保持したい場合）

1. `/var/log/journal` ディレクトリを作成（root権限）

    ```bash
    sudo mkdir -p /var/log/journal
    sudo systemd-tmpfiles --create --prefix /var/log/journal
    ```

2. `/etc/systemd/journald.conf` を編集し、以下を設定：

    ```ini
    Storage=persistent
    ```

3. `systemd-journald` を再起動：

    ```bash
    sudo systemctl restart systemd-journald
    ```

# Ping-t
- []()
PythonでCloudWatchエラーログを集計・分析する方法

私は現場でAWS CloudWatch に出力されるエラーログの定期的な確認と集計を担当しています。
手動でのログ確認は手間がかかるので、作業を効率化するためにCloudWatch Logs InsightsでエクスポートしたJSONを元に、エラー内容と発生箇所（path）ごとにログをグループ化し、件数を集計する Pythonスクリプトを作成しました。
ログ分析を効率化したい方の参考になれば幸いです！

## 準備
まずは CloudWatch Logs Insights を使って、必要なログを検索します。

ロググループを選択し、クエリを実行した後に、右上の 「結果をエクスポート」ボタンをクリック → 「テーブルをダウンロード(JSON)」を選択 すると、検索結果を JSON 形式でエクスポートできます。
保存されたファイルは通常 logs-insights-results.json というファイル名になります。

## 目的
今回はAWS CloudWatch Logs Insights からエクスポートしたログファイル（JSON形式）を対象に、以下の3つの処理を行うPythonスクリプトを紹介します。
・エラーメッセージとpathの組み合わせでグルーピング

・各グループごとに件数をカウント

・不正な（不完全な）ログはスキップして内容を確認

## Pythonスクリプト
```python:group_logs.py
import json
from collections import defaultdict

# JSONファイルを開く
with open("logs-insights-results.json", "r", encoding="utf-8") as f:
    data = json.load(f)

# data はリスト形式
results = data

# エラーの種類と path でグループ化
group_counts = defaultdict(int)

for entry in results:
    try:
        message = entry["@message"]
        context = message.get("context", {})
        detail = context.get("detail", {})

        error_message = detail.get("message")
        error_path_raw = detail.get("path")

        # message や path が無効の場合はスキップ
        if not error_message or not isinstance(error_path_raw, list):
            raise ValueError("message または path が無効")

        error_path = tuple(error_path_raw)
        group_key = (error_message, error_path)
        group_counts[group_key] += 1

    except Exception as e:
        # timestamp 付きでスキップログを出力
        timestamp_str = entry.get("@timestamp", None)
        if timestamp_str:
            formatted_timestamp = timestamp_str
        else:
            formatted_timestamp = "timestampなし"

        print(f"スキップされたログ（理由: {e} / timestamp: {formatted_timestamp}）")
        continue

# 件数の多い順にソートして出力
sorted_group_counts = sorted(group_counts.items(), key=lambda x: x[1], reverse=True)

for (msg, path), count in sorted_group_counts:
    print(f"[{count}件] {msg} | path: {path}")
```

## スクリプトの実行方法（初心者向け）
Pythonの初心者でも実行できるように、手順を簡単にまとめました。

1.Pythonのインストール
　公式サイトからPythonをインストールしてください
→ https://www.python.org/
　インストール時に 「Add Python to PATH」 にチェックを入れてください！

:::note warn
「Add Python to PATH」にチェックを入れずにPythonをインストールすると、コマンドライン（ターミナルやPowerShell）から python が使えなくなります。
:::

2.スクリプトとJSONファイルを準備
　上記のPythonコードを group_logs.py という名前で保存します。
　logs-insights-results.json を同じフォルダに置きます。

3.コマンドラインで実行
```
cd スクリプトのあるフォルダ
python group_logs.py
```
結果がコンソールに表示されます。
## 実行結果
```
スキップされたログ（理由: message または path が無効 / timestamp: 2025-06-21 03:38:48.707）
[15件] User not found | path: ('user', 'profile')
[8件] Invalid token | path: ('auth', 'validate')
[3件] Database timeout | path: ('orders', 'submit')
```
:::note warn
不完全なログは「スキップされたログ」として表示され、内容とタイムスタンプが記録されます。
スキップされてしまったログはタイムスタンプをもとに、あとから手動で確認できます。
:::
## おわりに
CloudWatch のエラーログを手動で確認・集計するのは、件数が多くなるととても大変です。
しかし、このような簡易集計スクリプトを作っておくと、エラーの発生件数や新規エラーの検出が格段に楽になります。

小さな改善ですが、日々の運用を効率化したい方の参考になれば幸いです！
非同期処理の中に同期処理を入れてない？

## いきなりですが、次のコードの実行結果はどうなると思いますか？

```python
import asyncio
import time

async def process_save_queue():
    while True:
        print("Task1: Starting blocking operation")
        time.sleep(2)
        print("Task1: Finished blocking operation")

async def startup_process_event_queue():
    while True:
        print("Task2: I'm running!")
        await asyncio.sleep(1)

async def main():
    task1 = asyncio.create_task(process_save_queue())
    task2 = asyncio.create_task(startup_process_event_queue())

    await asyncio.gather(task1, task2)

if __name__ == "__main__":
    asyncio.run(main())
```
実行結果は以下のようになります：

```makefile
Task1: Starting blocking operation
Task1: Finished blocking operation
Task1: Starting blocking operation
Task1: Finished blocking operation
...
```
Task2の出力がまったく表示されません。

## なぜTask2が実行されないのか？
原因は、process_save_queue() 内で 同期処理の time.sleep(2) を使っていることにあります。

async def で定義された非同期関数では、本来 await を使って「他の処理に譲る」ことを期待されています。非同期処理はマルチスレッドやマルチプロセスとは異なり、ひとつのスレッド内でタスク同士が await を使って協調しながら動作するのが基本です。

ところが time.sleep(2) は処理をブロックする同期関数のため、実行中は他のタスクに制御が渡りません。その結果、Task1が動いている間、Task2はずっと待たされたまま実行されないという状況になります。

## よくある落とし穴
今回の例のようにすべて同期的に止まってしまえば問題にすぐ気づけますが、もしタスク1の中に非同期処理と同期処理が混ざっていたらどうでしょうか？

この場合、Task2も一応動いてはいるように見えますが、処理効率は非常に悪くなります。
気づかないうちにアプリケーションのパフォーマンスを大きく損なってしまう危険があります。

## 正しい書き方
非同期関数内で同期処理を行いたい場合は、次のように書き換える必要があります：

方法1：非同期版のsleepを使う
```python
await asyncio.sleep(2)
```
方法2：同期処理を別スレッドで実行する
```python
await asyncio.to_thread(time.sleep, 2)
```
どちらも、他のタスクに制御を渡すための手段です。

## 結論
非同期関数の中で 同期処理を直接呼び出すのはNG です。
必ず await を使って、他のタスクにも処理を譲るように設計しましょう。
ハードウェア,  IoT

# ハードウェア
## CPU
4bit, 8bit, 16bit, 32bit, 64bitおよびGPU中心処理などの種類がある。
4bit CPUでは、ハードウェア設計がほとんどで、ソフトウェアは論理的な制御部分を担当する。

### 4bit 
CPU リモコンで、各国語対応（処理・表示）したり、各国時間に調整したり、温度・気圧対応、文化依存設定などを担当するかもしれない。各国語対応、各国時間対応、温度・気圧対応、文化依存設定は、ハードウェアで実現することもあり、すべてがソフトウェアで行うとは限らない。

### 8bit CPU
では、POSIX OSは普及しておあらず、ベアメタル処理、BASIC処理、CP/MなどのOS対応になる。
8bit CPUのC言語は、16bit Registerを持つCPUでは容易に実現し、Subsetも存在する。

BDS C
https://www.bdsoft.com/resources/bdsc.html

### 16bit CPU
当初C言語、UNIXの開発を行っており、ほとんどの16bit CPUで、C言語またはUNIXなどのPOSIX系OSが動作する。

WATCOM C Compilerは、1990年頃には、C言語標準に最も準拠した16bit CPU Cコンパイラとして、C言語のアプリの互換性確認に用いることがあった。
https://winworldpc.com/product/watcom-c-c/70

その後、Open WATCOM C Compilerとして16bit CPUでの挙動確認のために幅広く利用している。
https://github.com/open-watcom/open-watcom-v2

### 32bit CPU
GNU C Compiler/Gnu Compiler Collection(GCC)は、オープンソースのCコンパイラとして、32bit Intel CPUでの最適化が商用コンパイラと並ぶようになり、急速に用いるようになり、Open Sourceの活動の拠点となった。
https://gcc.gnu.org

### 64bit CPU
C言語仕様が、64bit CPUへの拡張を実現しておらず、Cの精神に基づいた拡張は続けている。
一つの解決策として、32bit C言語、64bit C言語という2つのC言語仕様に分けるという考え方がある。
32bit C言語は、16bit C言語をひきずっており、そのまま再規定するか、ARMのように16bit CPUがないシリーズを想定した32bit 限定の仕様にするかでの合意が取れるかどうかがわかっていない。

GPU拡張を64bit C言語にだけ適用するという方針で合意できれば、可能性がないわけではないかもしれない。

### GPU
GPUの処理は、並列FORTRANのライブラリを利用した並列Cコンパイラなどを利用したり、GPUに適したライブラリを用意した言語をもhc位いることがある。

### Ethernet/Wi-Fi
Ethernet/Wi-Fiは、IEEE802委員会で標準化しており、継ぎ目ない(seamless)接続が可能である。
RPC(remote procedure call)のようなAUTOSARでも指向している仕組みなど、POSIX OS以外でも幅広く適用している。

### USB
USB-Cは、逆挿がなく、とても便利。
操作の際の無駄時間が省略できるだけで十分嬉しい。

### bluetooth
IEEE 802.15は、一時的な仕様。
原則BlueToothSIGで仕様を決めている感じ。

### GPS
博論はPHSで実験した。柏村審査会の前日から大学に泊まり込み、GPSでの測定を行った。
PHSと同じように、測定プログラムを下記、遅延差が測定できた。
「PHSでしか成り立たない現象ですか？」
という質問に対して、
「GPSでも同様です。」
って答えられるようにしておいた。
「PHSでは時代遅れで、最新の通信プロトコルではどうですか？」
という質問への回答としても準備。

前日、徹夜でプログラム書いてて寝ていない状態での発表が、プログラマらしい迫力があったのか、該当する質問はなかった。
教授会では最高得票だったらしい。主席卒業？

### HDMI
画面を表示するのに、Display Portの種類がいろいろ提唱された。
Raspberry PIが対応しているHDMIが圧倒的なシェアをとっているかもしれない。

### Raspberry PI
Raspberry PIは、各種ハードウェアの基本機能を試すのによい基盤である。
標準でPythonを同梱したOSを提供していることも特筆できるかもしれない。

Raspberry PI 再出発 5でっていう
https://qiita.com/kaizen_nagoya/items/70c2e3da6c8c815dc3ac

## FPGA
自動車業界でBMWがいち早く商用車にFPGAを搭載したらしい。
日本の部品メーカが、Watchdogの試作をVerilog HDLで行おうとした。
コンパイルエラーをとることと、STARC RTL 設計スタイルガイドにもとづいた警告への対応を指導した。

RTL設計スタイルガイド Verilog HDL編(System Verilog対応版）coding(73)
https://qiita.com/kaizen_nagoya/items/4c02f1575db1f28310a7

# IoT(Internet of Things)
IoTには、ハードウェア側面と、ソフトウェア側面がある。

ハードウェア側面には、Raspberry PIのようなPOSIX互換OSであるLinuxを搭載するシステムと、
C言語のFreeStanding環境のみのベアメタル、POSIX非互換のRealTime OSを搭載するシステムがある。

Ethernet/Wi-Fi, USB, Bluetoothは、Raspberry PIについては、前章で紹介している。

## .net micro framework
Microsoftとの歴史　Basicに始まり、Cコンパイラ、Windows95、Git(9)hubまで
https://qiita.com/kaizen_nagoya/items/d7c0cc257e99de0573cf

## 各種無線
Wi-Fi, bluetooth以外の各種無線はいくつかは試用した。
両方を凌駕する無線にはまだ出会っていない。


## 関連資料
職業訓練（IT)　オープンソースとユーザビリティ教育。構造化とUMLを使って。
https://qiita.com/kaizen_nagoya/items/c41988c2f8ce1b61a08a

セキュリティ記事まとめ
https://qiita.com/kaizen_nagoya/items/f8fa4228c45a04c74fc2

サービス、アプリケーション
https://qiita.com/kaizen_nagoya/items/3acf38aaf744e73677e1

ライブラリ・フレームワークの創り方
https://qiita.com/kaizen_nagoya/items/459cb3f499f9faf71e55
JavaSilver取得までの学習方法

# 最初の挨拶
初めまして、Qiita初投稿となります
学習のアウトプットを主目的に投稿していこうと思っています
ベテランの皆さんには生暖かく見ていただけると嬉しいです
また私と同じ未経験の方には、少しでも今後の学習のヒントになれば幸いです


# 本記事の概要と目次
**概要** 
JavaSilverを取得するまでの学習で効果を実感できた方法を記載します 
<br>

**目次**
1. 学習のポイント
1. 学習手順
   - 学習項目と概要を把握する
   - 問題集のコードをchatGPTに解説してもらいながら、問題を解いていく


# 学習のポイント
- **参考書は電子書籍を買う**
電子書籍をおすすめする理由
  1. 通勤時間も学習できる（仮に通勤時間が片道1時間なら、1週間で10時間も学習時間が増えます）
  1. kindleで購入した場合web版とアプリ版で２画面表示出来るので、演習問題と解説を同時に表示するのに便利
  1. 問題文のスクショを撮ってchatGPTに質問すれば、質問文を打ち込む手間もない
<br>

- **JavaSilver黒本の演習問題を6周する**
脳筋的な発想ですが、極論演習問題を100%正答できるまで解けば試験には合格できます
<br>

- **問題を丸暗記しないよう注意する**
繰り返し解いていると正解を暗記してしまいますが、本質を理解せず暗記だけしても試験は突破できませんので私は以下の点を注意していました
  1. この問題はどういった意図で出題されたのか、なんの知識があれば解けるのか意識する
  1. 不正解の選択肢について、なぜ不正解か説明できるようにする
  1. 問題文のコードについて、行ごとの意味を説明できるようにする
上記を意識して学習を進めていました

# 学習手順


#### 学習項目と概要を把握する
- Oracle公式サイトから、出題範囲の項目を抽出
- 各項目の概要をChatGPTに解説してもらう
- 要約で分からない単語をchatGPTに解説してもらう
全体の学習内容を大まかに把握してから細部を深掘りすると理解しやすいかなと思います

【oracleサイト記載の出題範囲】
![スクリーンショット 2025-06-22 20.52.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922524/2e51be60-3439-4702-b9a2-8016a7daa393.png)

【chatGPTの解説例】
![スクリーンショット 2025-06-22 20.56.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922524/bbf97518-2301-4ed3-97fe-e27322251a7e.png)


#### 問題集のコードをchatGPTに解説してもらいながら、問題を解いていく
- 問題集のコードについて、コード全体の解説をして貰う
- 行ごとの意味を解説してもらう
- 単語ごとの意味を解説してもらう

【問題の解説例】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922524/29c7715f-ac97-476f-a9c9-128c92e6883f.png)


# まとめ
流れとしては概要を把握し、分からない単語やポイントをchatGPTに聞くだけです。
上記を意識してjavasilver黒本の演習問題を5周した結果、試験に合格できました。
ただこのやり方だと、実際にjavaでコーディング出来るようにはなりませんでした。
試験合格に必要な知識を覚えるだけですので、スキルとして身につけたい！という方は実際にコードを実行して理解を深めるといいのではないかと思います。
ここまで有り難うございました。
【Python】DataFrameからデータを抽出する方法

DataFrameからデータを抽出する方法は、「直接、loc、iloc」の3つです。

主なルールは以下となります。

【1】 直接
◾️ df[列名]
指定した列が返ります。
インデックス（数字）で指定することはできません。
行名を指定することはできません。

◾️ df[数字:数字]
スライスで指定した行（全列）が返ります。
指定する数字はインデックスです。
df[:数字]やdf[数字:]のように、始点と終点だけを指定することも可能です（Python標準と同じで終点の行は含みません）。
df[数字, 数字]のように、カンマを使って行と列を両方指定することはできません。


【2】 loc（名前で指定）
◾️ df.loc[:, 列名]
全行、指定列が返ります。
カンマで区切った左が行、右が列の指定です。
df.loc[:, :]は全行全列が返ります。
df.loc[:, :列名]のように列名をスライスで指定することも可能です（locのスライスはインデックスと異なり終行・終列を含みます）。
df.loc[:, ['A列', 'B列']]のように複数の列を指定することも可能です。

◾️ df.loc[行名, :]
指定行、全列が返ります。
df.loc[:行名, :]のように行名をスライスで指定することも可能です。
df.loc[['1行目', '2行目'], :]のように複数の行を指定することも可能です。

◾️ df.loc[行名, 列名]
指定位置の値が返ります。


【3】 iloc（インデックスで指定）
使用方法は基本的にlocと同じです。
インデックスによるスライスは終行・終列を含みません。


これらのルールを覚えておけば概ね対応できます。

locとilocは紛らわしいですが、iはindexの「i」と覚えると分かりやすいです。
Growiセットアップにて docker-compose up ができない   

# はじめに
個人wikiを探していたところ、いつも参考にさせていただいているXアカウントがGrowiをローカルに立ててナレッジを貯めていくことをお勧めしていた。

Growi公式
https://docs.growi.org/ja/admin-guide/

当方の環境は、MacBook Pro(2023,M3)
```
Darwin Kernel Version 23.6.0: Fri Jul  5 17:56:39 PDT 2024; root:xnu-10063.141.1~2/RELEASE_ARM64_T8122 arm64
```
# いざインストール
公式ページのdocker-composeのチュートリアルを手順通りに行なっていくと、以下エラーが出た。
```
docker-compose up
WARN[0000] /Users/xxxx/Project/growi/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
[+] Running 2/2
 ✘ pdf-converter Error manifest for growilabs/pdf-converter:1 not found: manifest unknown: manifest unknown                                                                      2.6s 
 ✔ mongo Pulled                                                                                                                                                                  2.1s 
Error response from daemon: manifest for growilabs/pdf-converter:1 not found: manifest unknown: manifest unknown
```
どうやらdocker-compose.ymlの
```
  pdf-converter:
    image: growilabs/pdf-converter:1.0
```
の書き方がまずいらしい。
以下リンクを見ると、
https://hub.docker.com/r/growilabs/pdf-converter/tags
OMG! tagの名前が1.0ではなく1.0.0じゃないか！
とりあえず:latestにしてみる
```
  pdf-converter:
    image: growilabs/pdf-converter:latest
```


# 結果
無事docker-compose upが成功しアクセスできた。デフォルトのportは3000番のよう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4067743/3c187599-c0fd-464a-9b6a-1632e4c13da3.png)
ビギナーにも発信をしてほしいと思うワケ

「ある程度理解してから発信しよう」と思っていないだろうか？
それも決して間違いではないが、ビギナーの発信にも大きな価値がある。

## 「ビギナーがどこで躓くのか」という情報には価値がある
新しいプロジェクトや技術に取り組むとき、最初から要点を掴める人はそう多くない。 「チームのチャネルが多くてどこを見ればいいのかわからない」 「エラーメッセージのどこに注目すればいいのかわからない」など、こうした悩みは多少慣れた人には自然と処理できるものかもしれないが、ビギナーにとっては大きな壁になり得る。

こうした「どこで躓くのか」という情報は、**仕組みの不備の改善や教育方法の見直しにつながる重要なヒントになる。**

「ビギナーがどこで躓くのか」はビギナー本人が一番よくわかるし、経験を積むにつれてビギナーの頃の感覚は忘れがちになっていく。だからこそ、「ビギナーのうちに発信をしてほしい」と伝えたい。

## 「自力で解決できたこと」でも発信してほしい
「躓いたけれど、自力で解決できたから言わなくてもいい」と思うこともあるかもしれない。確かに対話型AIの台頭により調べればわかる範囲というのは大きく広がっている。
だが、同じようなことを多くの人が調べているということがわかれば、有識者にあらかじめ説明してもらったり、躓きがちなところをまとめた記事を書いてもらったりもできる。

ビギナーの頃は特に、躓きと解決の繰り返しなのではないだろうか。**「どこで躓いて、どう調べて、どう解決したか」**、その思考の流れや試行錯誤の跡は、同じ問題にぶつかった他のビギナーにとってもビギナーを導く立場にあるベテランにとっても非常に参考になるはずだ。

## 「躓いた」は恥じゃないので、小さな発信から初めてみよう
「こんな初歩的なことで躓いたのを発信するなんて……」と思うかもしれないが、あなたが躓いたということは、他の誰かも躓くかもしれない。あなたの発信は、たぶん誰かの助けになるはずだ。
Qiita Tech Festa 2025もまだ始まったばかり。これまで「まだまだビギナーだから…」と発信を躊躇してきた人も、これを機に投稿を初めてみるのも良いかもしれない。

## 参考記事
https://qiita.com/Sicut_study/items/4e4f49aefb5a1b134582
【Python】NumPyのsin関数、cos関数、tan関数

sin関数、cos関数、tan関数の引数は角度ではなくラジアンで指定します。

ラジアンは、角度360°を2π（2×3.14...）、180°をπ（3.14...）として扱う単位です。

例えばsin180°の三角比を求める場合は、「np.sin(np.pi)」とします。結果は「1.2246467991473532e-16」が返ります。最後の「e-16」の「e」はネイピア数ではなく、大きな数や小さな数を表すときに使われる記号です。

■ eの右側に正の整数がある場合
eの左側の小数に、eの右側の回数だけ10を掛けます。
例えば「1.1e2」であれば、1.1に10を2回掛ける、つまり100を掛けるため、「110」を表します。

■ eの右側に負の整数がある場合
eの左側の小数に、eの右側の回数だけ10で割ります。
例えば「1.1e-2」であれば、1.1を10で2回割る、つまり100で割るため、「0.011」を表します。

先ほどの三角比の「1.2246467991473532e-16」は、eの左側の数を10で16回割ります。小数点を左側に16回移動することになるため、ほとんど0に近い数字になります。sin180°の三角比は「0」ですが、円周率のように無限に続く数をコンピュータで計算すると誤差が出るため、このような結果になります。
AWSのEC2/Linuxインスタンスで同一サブネットに2つのNICを差しそれぞれにElasticIPを設定する時のカーネルパラメーター

# AWSのEC2/Linuxインスタンスで同一サブネットに2つのNICを差し、それぞれにElasticIPを設定

異なる経路で応答しないようにひと工夫必要。大昔にロードバランサーを組んだときのおぼろげな記憶とgeminiさんによる支援で設定。

## 構成
下記のような構成。

```
EIP-1 -> ENI-1 (172.16.0.1/24)
                   \
              EC2インスタンス
                   /
EIP-2 -> ENI-2 (172.16.0.2/24)
```

先々EIP-1,EIP-2は同一サブネットの異なるEC2インスタンスに割り当てる予定。  
送信先によるアクセスフィルタリングをしているような接続元からの疎通確認用にEC2インスタンスを仮設。  
LinuxではIPアドレスは特定のインターフェースに割り当てるというよりシステム全体に割り当てられる。  
よって柔軟なままのデフォルト設定ではEIPがばらけてしまう模様。

## カーネルパラメーター

結果として設定したのは以下のパラメーター。

```
cat /etc/sysctl.d/50-rp_filter
net.ipv4.conf.all.arp_ignore=1
net.ipv4.all.arp_announce=2
net.ipv4.conf.all.rp_filter=2
net.ipv4.conf.default.rp_filter=2
```

前提として、`ip route`でポリシーベースのルーティングができてしまうような柔軟な設計になっています。
一方で、IP割当をインターフェースに縛りたいロードバランスや仮想IP割当の場合には逆に厄介で今回のような設定が必要。

まず、`arp_ignore`でARPリクエスト受信の際にリクエストされたIPアドレスが設定されているインターフェースのみに応答を限定。
さらに`arp_anounce`でARPリクエストを送信する際に自身のIPアドレスのみに限定。

そうした上で`rp_filter`でインターフェースとIPの不一致をフィルターして捨てることで整合を保つ。

## やってみて

素直にEC2を2つ立てたほうが速かった説
【Python】NumPyのarange関数

Numpyのarange関数は、Python標準のrange関数と同様に、始点を指定しなかった場合は0から始まり、終点は含みません。

引数が1つの場合は「要素数」、2つの場合は「始点と終点」、3つの場合は「始点・終点・ステップ」を指定します。
AIを用いた高精度な英語辞書ツールを開発しました

# はじめに

突然ですが、みなさんは「Mouse Dictionary」というChrome拡張機能をご存知でしょうか？  
https://qiita.com/wtetsu/items/c43232c6c44918e977c9

英語のニュース記事や論文を読む際に、マウスオーバーするだけで単語の意味が表示されるという非常に便利なツールです。

ただし、使っているうちに次のような課題点も見えてきました：

- 一部の辞書の精度が低い  
- 調べた単語が自動で単語帳に保存されない  
- 音声再生（TTS）が対応していない  

こうした課題を解決するために、高精度なAI辞書ツール「AI Dictionary」を開発しました。  
Chrome拡張として動作し、**自動で単語帳を作成**したり、**高品質な音声再生**にも対応しています。

---

## 実際の使い方

1.調べたい単語を選択して、拡張機能のアイコンをクリック

![en_dictionary_output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4100003/4f1bf9a6-f224-40ce-90da-0a5456816a8f.gif)

  
2.サイドバーを開いた状態で、アイコンをクリック

![en_dictionary_sidebar_output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4100003/e8024503-7062-47eb-82c3-4cd952283062.gif)


---

## 主な特徴

- **Geminiを使用**しているため、人名やアプリ名など特殊な単語にも対応可能  
- **文脈を考慮した辞書表示**で、その文章に合った意味が表示される  
- **調べた単語は自動的に単語帳へ保存**され、学習にも活用しやすい  
- **GoogleのTTSサービス**により、自然で高品質な音声再生が可能

---

## インストール

Chromeに追加ボタンから使用できます。

https://chromewebstore.google.com/detail/cgojmhjlocnlmdbbacfaeijmeaojlnpc?utm_source=item-share-cb

英語学習をさらに効率化したい方、専門的な英文を読む機会が多い方に、ぜひ使ってみていただきたい拡張機能です。  
今後もアップデートを重ねて、より快適な英語リーディング体験を提供していきます。
ディスク逼迫調査・ボリューム拡張手順

## はじめに
いつもEC2の容量が足りなくなった際、どのような手順でやっていたか毎回調べている事に気づきました。

Qiitaの記事のを執筆する際、開発や検証はCloud9で行っていますがそれの容量が逼迫したのを機に備忘録として残します。

今回の手順に出てくる重要な単語なども纏めていきます。
日頃クラウド関連の学習ばかり好きでやってしまいこのようなインフラの基礎的な部分が疎かになりがちなのでこのような内容の記事も今後増やしていきます。

## ボリュームとは
論理的なディスクの領域、区切りの事を指しています。
パーティションにファイルシステムを適用しOSから認識できる状態になった論理的なディスクの領域の事。(AWSだとEBSでAzureだとAzure Managed Disks)

## パーティションとは
物理的なディスクの区切りを指しています。ディスクがパーティションされただけではまだOSは認識できない状態。

## ファイルシステム
パーティション上に構築されるファイルとフォルダの管理構造。
ファイルの位置やサイズ、メタデータが保存されるルールそのものを指している。(ext4 or XFSなど)

## それぞれの関係性、イメージ
以下、ChatGPTさんが作成してくれました。

```
         ┌───────────────────────────────┐
         │    アプリケーション              │
         │  (例: ls, cat, mkdir など)       │
         └─────┬─────────────────────────┘
               │ (システムコール：open/read/write)
               ▼
┌──────────────────────────────────────────────┐
│        → OS カーネル（VFS / ドライバ）←      │
│                                              │
│   ┌──────────────────────────────────────┐   │
│   │   ファイルシステム (ext4, XFS など)     │   │
│   │   └─ OS はここを通じてファイル操作    │   │
│   └─────────────┬────────────────────────┘   │
│                 │                              
│                 ▼                              
│   ┌──────────────────────────────────────┐   │
│   │   パーティション (/dev/nvme0n1p1)     │   │
│   │   └─ OS はここをブロック単位で扱う   │   │
│   └─────────────┬────────────────────────┘   │
│                 │                              
│                 ▼                              
│   ┌──────────────────────────────────────┐   │
│   │   ボリューム (EBS / Managed Disk)     │   │
│   │   └─ OS からは /dev/nvme0n1 として見える │
│   └──────────────────────────────────────┘   │
└──────────────────────────────────────────────┘
```

では、以下ボリューム拡張手順です。Linux想定です。
※AWSコンソールでの作業は省略します。

## １：エラーメッセージの確認
ディスクの空き容量がなくなると大体以下のようなエラーメッセージが出てきます。
```
Error while installing hashicorp/aws v5.100.0: 
write ... no space left on device
```

terraform initのコマンドを実行した際の例です。

## ２：空き容量の確認
```
df -h
```

## ３：ディレクトリ・ファイルの調査、不要ファイルの削除
```
du -sh ./* | sort -h
```

上の階層のディレクトリに移動して実行していき、逼迫の原因となっている箇所を突き止めましょう。

原因を突き止めたら不要であれば削除→他のディレクトリも調査を繰り返していく。
↓
手順2に戻って容量に空きができたか確認する。

エラーとなった際の作業を再度実行し解決できない場合は、手順４へ進む

## ４：ボリューム拡張

1,現在のディスク構成の確認
```
lsblk
```

出力例：
```
nvme0n1       20G disk
└─ nvme0n1p1(←※ここがパーティション領域)  10G part /
└─ nvme0n1p3  10M part /boot/efi
```

2,パーティション領域の拡張
```
sudo growpart /dev/nvme0n1 1
```
nvme0n1の部分はパーティション名ごとに書き換えてください。

3,ファイルシステムの種類を確認、拡張
```
# ファイルシステム種類を確認
df -hT /

出力例：
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/nvme0n1p1 xfs(←ここを確認)    10G   10G   10G  100% /

# ext4 の場合
sudo resize2fs /dev/nvme0n1p1

# xfs の場合
sudo xfs_growfs -d /
```

最後に手順２のコマンドを実行しボリュームが拡張されたことを確認して終了です。

## 最後に
ずっとAWSコンソールでEBSを拡張しても再度サーバで作業が必要部分についてうまくイメージできていませんでした。

コンソールの作業だけではディスクのサイズを大きくしているだけでOSは認識できない状態だということでした。

そこからディスクを大きくした分パーティションに割り当てる→さらにそれをファイルシステムに割り当ている事によってOSが認識できる状態になる。
k8sでのCI/CDの流れを図解してみた【GitOps vs CIOps】

### はじめに
- GitOpsって？
    - Gitを用いたCI/CDの手法の一つ
    - Dockerイメージの変更のようなクラスタの操作を、Gitリポジトリを介して行うこと
    - 手動で「kubectl」コマンドを実行する必要がなくなる


### クラスタ上にデプロイするアプリケーションを開発する際のフロー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3326131/799468b7-c043-4e4d-88ba-d0fd56f2a57f.png)


- クラスタ上にデプロイするアプリケーションを開発する時、一般に下記のフローを踏みます
    1. アプリケーションのソースコードを変更
        - xxx.javaなど
    1. アプリケーションのテスト
    1. コンテナイメージのビルド
    1. コンテナイメージをコンテナレジストリにプッシュ
        - openshift-image-registryなど
    1. Deploymentなどのマニフェストに記載されたイメージのタグを修正
    1. 「kubectl apply」相当の処理を実行してクラスタに反映
        - OpenShiftの場合「oc apply」

### GitOpsで必要なリポジトリ
- Gitリポジトリとして、「アプリケーション」と「マニフェスト」用のリポジトリを用意
- マニフェスト用リポジトリ
    - クラスタにデプロイする全てのマニフェストを保管
    - 保存されたマニフェストが自動的にクラスタに適用される
    - **マニフェスト用リポジトリの状態＝クラスタの状態**
- アプリケーション用リポジトリ
    - アプリケーションのソースコードを保管
    - ソースコードに変更があると、CIによって以下が行われる
        - テスト
        - コンテナイメージのビルド
        - 新しいタグの付与
        - コンテナレジストリへのpush

### GitOpsの流れ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3326131/15dcda9e-0848-48eb-ad64-901521d68783.png)

1. 開発者がアプリケーション用リポジトリに変更をコミット
1. アプリケーション用リポジトリは、自動的にCI(継続的インテグレーション)実行
1. アプリケーション用リポジトリは、マニフェスト用リポジトリに対してイメージタグを変更するPR(Pull Request)を自動で送信
1. 開発者がPRをapproveすると、マニフェスト用リポジトリにてマニフェストの変更がマージされる
1. OpenShift上で動作しているDeploy Agent(Argo CDなど)が、マニフェスト用リポジトリに保管されたマニフェストを取得
1. 取得したマニフェストを適用

### コンテナイメージのビルドにおけるTips
- 「コンテナイメージのビルド」とは、「アプリケーションのビルド」を実行し必要なパッケージなどを内包したコンテナイメージを作成すること
- このときビルドした実行ファイルをコンテナイメージにCOPYやADDするのではなく、「アプリケーションのビルド」自体もDockerfile内に記述するべき
- **実行環境に依存した影響を受けづらくなる**

### CIOps
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3326131/7c878171-3421-4ba0-a238-df357130e032.png)

- GitOpsに類似した概念としてCIOpsがある
- GitOpsと同じところ
    - 「アプリケーション」と「マニフェスト」用のリポジトリを用意して、それぞれでCIを実施すること
- GitOpsと違うところ
    - 「マニフェスト」用リポジトリに保管されているマニフェストをクラスタにデプロイする部分
    - CIOpsの場合
        - クラスタ外にあるJenkinsなどのCIツールでデプロイ実行
        - 具体的には「マニフェスト」用リポジトリに対してマージされたタイミングでCIジョブをトリガーし、マニフェストをフェッチしたあと、それらのファイルをクラスタに適用
    - GitOpsの場合
        - クラスタ上にDeploy Agentを配置し、「マニフェスト」用リポジトリからのマニフェストの取得とクラスタに対する適用を実行


### CIOpsよりGitOpsが推奨されている理由
- CIOpsの提唱元「Weaveworks」はCIOpsをアンチパターンとし、GitOpsが推奨されている
- 理由は**ツールに与えるクラスタ操作権限の範囲を狭められるから**
    - CIOpsの場合
        - クラスタへのデプロイを行う際に、CIツールがkubectlコマンドなどを利用して外部からクラスタに対してマニフェストの適用をする
        - そのため、CIツールにクラスタに対する強い権限の認証情報を持たせる必要があり、セキュリティ上の欠陥になる恐れがある
    - GitOpsの場合
        - クラスタに対してDeploy Agentを起動し、「マニフェスト」用リポジトリからマニフェストをPullして適用する
        - そのため、Deploy Agentには「マニフェスト」用リポジトリに対するRead権限のみ与えれば良いので、セキュリティリスクを下げることができる
- 一方で複数のクラスタを一元的に管理する場合など、CIOpsの方が適している状況もある
    - メリデメを考えて採択する必要がある

| 比較ポイント    | GitOps              | CIOps                 |
| --------- | ------------------- | --------------------- |
| デプロイ実行責任者 | クラスタ上の Deploy Agent | 外部CIツール（例：Jenkins）    |
| 権限の範囲     | リポジトリへの Read 権限     | クラスタへの管理権限全般が必要       |
| セキュリティ    | 最小権限構成が可能           | 高い権限を CI ツールに付与する必要あり |
| 運用の柔軟性    | マニフェストのシンク実行に依存     | CI スクリプトで任意フローを実装しやすい |



### 参考文献
- Kubernetes完全ガイド 第2版 (Top Gear)
- Kubernetesの知識地図 —— 現場での基礎から本番運用