OmniAICreator/Qiita-1.07M huggingface dataset:
2026年を目指した技術アーキテクチャ、エンジニア組織、顧客をどう考えるか？

### はじめに
先日、社内イベントで、各領域の政策ヒストリーと未来を整理し、未来に備えることについて考えるというイベントがありました。
その内容が非常に興味深く、今後の技術アーキテクチャ、エンジニア組織、顧客をどう考えるか？に役立つのでは？と思えたので、その手法について紹介させて頂ければと思います。

当社は医療業界に位置しており、そういった意味で医療政策が決まっていることもあり、市場動向を予測することが、ある程度は可能ではという認識です。

インベントは、次のステップで行われました。

ステップ1：知っているか？
ステップ2:それがどう自社に影響があるかを考えられるか？
ステップ3:どう備えて実行するか？

ステップ1の前には、各領域での事前課題書籍を読む、ということが求められました。
各領域とは、医師、薬剤師、健康経営の3領域となります。
私は健康経営を担当いたしました。


### ステップ1：知っているか？
・2013年（10年前)から医療政策では何があったか

健康経営という領域におけるエポックとしては、2017年の電通事件、そこからの働き方改革への流れを振り返りました。
当社では健康経営事業が立ち上がって来たタイミングを振り返りました。


・ (2023年から7年後)2030年に向けて医療政策ではどのような変化が予定されているか

来年2024年、2025年では例えば、下記のような医療政策に関連するようなエポックが予定、予期されています。
`2024年　医師の働き方改革、物流2024年問題`
`2025年　高齢者人口30%超、定年65歳義務化`

このように2030年ごろまでの少子高齢化の予測や生産年齢人口の減少などについての認識を共有しました。


### ステップ2:それがどう自社に影響があるかを考えられるか？

当社では5年ほど前から健康経営領域での事業を開始しています。
以下のような観点で、改めて、自社が寄与できること、取り組むべきことが明確になった気がします。

・高齢化が進む中で健康でいられる期間を長く保てるか？
・生産人口が減少する中でどのように健康をキープして結果として生産性を上げることが可能か？

エンジニアの観点からは医療DXをさらに進めて行くことで可能なことが多くあることを認識できました。


### ステップ3:どう備えて実行するか？

イベントではステップ2を踏まえて、2030年の事業として何を行なっているべきなのか？ということについてディスカション、発表を行いました。
この時間軸では、未来を創るのは自分たちであること、企業としてのミッション、存在意義に再確認することができ、良い機会だったと思っています。

イベント後には、エンジニア組織に焦点を絞って、2030年では無く、もう少し手前の2026年に向けて技術アーキテクチャ、エンジニア組織、をどう考えるか？ということに取り組んでいます。
　
・　技術アーキテクチャ
当社では30〜40事業が存在して、これまでは事業ごとのシステム構築手法がメインでした。今後は、お客様にはシームレスなサービスがより求められて、当社からみて事業の横連携が求められると考えています。

また、健康経営領域では、エムスリーグループでのサービス連携も行えた方が、お客様にはシームレスなサービスがお届け出来ると考えており、グループ各社を連携可能な共通API化にも取り組み始めています。

その中では、前回にも述べさせて頂いた、デジタル庁　「データ連携基盤の整備について　公共サービスメッシュの整備（P5)」などを参考にさせて頂いています。
 https://www.cas.go.jp/jp/seisaku/digital_denen/dai4/siryou8.pdf

 
・エンジニア組織
現在では、toC向け、toB向け、to社内向けの開発チーム構成となっています。
今後は、共通API、データ基盤を専門的に取り組むチームが必要かも知れません。


・　顧客
エムスリーグループの健康経営領域では、ベネフィットワン様のTOBの実施をプレスリリースを出させて頂きました。
今後より多くの企業様、企業で働かれる方々の健康に寄与できるサービスをお届けできるようになりたいと考えています。
Qiita執筆が劇的にラクに！GPTsで実現する新時代の記事作成術

## サマリ
- GPTs「技術記事クリエイター」を使用して、技術記事の執筆をより簡単かつ効率的に。
- 直感的な質問応答形式で思考の整理と記事の構成を支援。
- Qiitaや他の技術コミュニティでの共有が容易に。
- 創造性と効率のバランスを取ることで、より価値あるコンテンツを提供。

※本著もGPTsで記載しています

## この記事で伝えたいこと
技術記事の執筆プロセスを革新する「技術記事クリエイター」GPTsアプリを紹介し、その利用により技術コミュニティ内の知識共有がいかに容易になるかを示す。
![DALL·E 2023-11-26 13.08.41 - An illustrated concept showing a person overwhelmed with a large pile of technical documents and another person offering a simplified, organized binde.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262854/e1c62f54-2353-f0c4-5805-f98eb2df08ce.png)

## 解決したい課題
技術記事の構成を練りながら内容を考えることの複雑さと時間消費の大きさ。
![DALL·E 2023-11-26 13.08.43 - A graphic illustration depicting a person sitting at a desk, surrounded by scattered notes and a computer screen filled with various open documents. T.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262854/a0097fcb-b4e6-adad-9f15-2aa29e197219.png)


## 課題の原因
既に頭の中にある知識を他人が理解しやすい形に再構成する際の労力と時間の要求。

## 課題の解決手段
GPTsアプリ「技術記事クリエイター」を用いて、質問に答えることで自然に記事を構築する。

## 解決する技術や手段の概要
### GPTsアプリ「技術記事クリエイター」の紹介
- [技術記事クリエイター](https://chat.openai.com/g/g-baN2JdIEj-ji-shu-ji-shi-kurieita)
- 概要: 質問に答えることで記事を自動的に構成するAI駆動のツール。
- 特徴: ユーザーの思考プロセスをサポートし、記事作成の効率を大幅に向上。

## その手段をとる効果
- ユーザーは自分のペースで質問に答えることで、執筆プロセスを非同期に進められる。
- 脳の負荷が軽減され、よりクリアな思考で内容を整理できる。

## 具体的な実装
OpenAIのGPTsを基に構築された「技術記事クリエイター」は、質問応答形式を通じてユーザーが自然に記事を構成する手助けをする。

## 想定される応用事例
- Qiitaや他のプラットフォームでの技術記事執筆。
- プロジェクトの経験や学習内容の整理と記録。
- 新しい知識や技術の効率的な共有。

## 留意点やデメリット
- GPTsアプリが提供する構成の枠組みにより、記事の創造性が制限される可能性。
- 自動生成された内容は、個人のスタイルや深いニュアンスを完全に反映しきれない。
Pythonで「変数の定義と値の代入」の動作を確認してみた

# 概要

Pythonで「変数の定義と値の代入」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/python/var/index1.html

# 実装

以下のファイルを作成しました。
```sample.py
old = 24
str = "Hello"
colorlist = ["red", "blue", "yerllow"]
num = 10
print(num)
address2019 = "Tokyo"
print(address2019)
年齢=25
print(年齢)
str = "Hello"
STR = "Python"
print(str, STR)
name = "Yamada"
name = "Tarou"
personal = "Yamada"
personal = 24
personal = "Yamada"
print(personal)
personal = "Tarou"
print(personal)
personal = 24
print(personal)
num = 10
print(num + 5)
name1 = "Yamada"
print("name1=" + name1)
name2 = name1
print("name1=" + name1)
print("name2=" + name2)
name1 = "Suzuki"
print("name1=" + name1)
print("name2=" + name2)
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
10
Tokyo
25
Hello Python
Yamada
Tarou
24
15
name1=Yamada
name1=Yamada
name2=Yamada
name1=Suzuki
name2=Yamada
```

# まとめ

何かの役に立てばと。
Python Tkinterとラズパイで自分専用のダッシュボードアプリを作ってみる #1 やりたいこと整理

# 概要
机の上に
・デジタル時計
・室温湿度計
・カレンダー
が並んでおり、どうせなら一つのフォトフレーム的なディスプレイにまとめて、+アルファで天気予報、ニュース、も表示させたいと思い作成に望みました。

この記事はそのメモやまとめです。
すでに設定済みの項目がいくつかある。
試行錯誤しながらやったので、手順として不要かもしれない。**あくまでメモ用。**

# 実装したい内容とか整理
ざっくりしたものですと

https://qiita.com/Kazuya_Murakami/items/03c218f80377280f5b9f

この方のものに近いです。
画面を大きくして表示させる情報を増やしたイメージです。

pythonではTkinterというライブラリを利用すればこういったダッシュボード的なものを作成できるようですので、これを利用したいと思います。

また、以下のような機能を実装したいと思っています。
・室内の気温と湿度を測定し表示
・12時間分の天気予報を表示
・7日分の週間天気予報を表示
・カレンダーの表示
・現在の時刻の表示
・日本の主要ニュース10件のタイトルと要約の表示
出すだけだし出してみましたが、表示範囲の関係で将来的には表示件数を減らすかもしれません。

## ワイヤーフレームみたいなの作ってみる
こんな感じになればいいかな。figmaを利用して作成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185852/2ec0b740-fca0-9e5d-71b9-42a4cdc6f9d2.png)
実際デザインしてみると結構ギチギチなので表示する情報は最初より削減する必要がありそうです。

# 次やりたいこと
- 各要素を作成
billing データのエクスポートで Google Cloud のコスト管理

BigQuery Advent Calendar 2023 １日目の記事です。

https://qiita.com/advent-calendar/2023/bigquery

この記事では BigQuery の機能の１つである billing データのエクスポートを紹介します。

# billing データのエクスポート

Google Cloud の課金データ（使用量、費用予測、料金データなど）は自動的に BigQuery にエクスポートすることができます。

https://cloud.google.com/billing/docs/how-to/export-data-bigquery?hl=ja

課金データを BigQuery にエクスポートすることで、課金状況を細かく分析することができるようになります。
BigQuery は Google Cloud の様々なサービスと連携しやすいため、使いやすい機能だと思います。
この記事では[株式会社ギックス](https://www.gixo.jp/)でも利用している課金データの利用方法についてご紹介します。

## billing データに含まれる情報

billing データとしてエクスポートすることができるテーブルは３種類あります。
各テーブルの詳細な説明についてはリンク先をご確認ください。
- [標準の使用料金テーブル](https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage?hl=ja)
    -  アカウントID、請求書の日付、サービス、SKU、プロジェクト、費用など、様々な使用料金やが含まれます。
    -  特に使用したリソースに関する列が多いです。
    -  ギックスではこのテーブルを利用しています。
- [詳細な使用料金テーブル](https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage?hl=ja)
    - 標準の使用料金テーブルのすべての項目に加えて、リソースレベルのデータを提供する追加の項目（例: サービス使用量を生成する仮想マシンまたは SSD）が含まれます。
- [料金データテーブル](https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/pricing-data?hl=ja)
    - 標準の使用料金テーブルと比較して特に料金に関する列が多いです。
    - 例えば discount の情報など料金に関する詳細はこのテーブルにしか含まれていません。


なお、標準の使用料金テーブルと料金データテーブルを見比べたところ、共通の列は以下でした。

- currency_conversion_rate
- export_time
- service.id
- sku.description
- sku.id



## 更新頻度

あるサービスで課金が発生した場合にどれくらいの時間で billing にエクスポートされるのかは公式ドキュメントで明言されていません。
BigQuery の billing データを見る限りでは数十分に一度更新されていますが、課金発生からの数十分後に反映されているわけではないため注意が必要です。


# 活用事例

ギックスでは現在２つの活用事例があります。

## 想定外課金の検知と自動課金停止

billing データをもとに各プロジェクトの課金額を算出し、一定金額を超えたことを検知することができます。
ギックスでは検知した結果としてそのプロジェクトの課金を停止し、想定外の大量課金の発生およびクラウド破産を防いでいます。
アーキテクチャとしては次のようになります。

![スクリーンショット 2023-11-25 20.01.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415560/22c04572-9c8a-0002-2a9a-e1f1cb1c8328.png)

Workflows から BigQuery で billing データに対してクエリを発行し、プロジェクトごとの課金額を集計しています。
１つのプロジェクトを対象として一定金額を超えたことを検知するのは簡単なのですが、すべてのプロジェクトを対象とする場合は個別に設定するのが大変です。
そこで billing データのエクスポートを使えばすべてのプロジェクトの課金状況を簡単に取得できるため、それを元に一律に設定できます。

詳しくは [公式ブログ](https://www.gixo.jp/blog/23275/) に記載しているためそちらをご参照ください。

## Looker Studio でコスト状況を可視化する
ギックスでは Looker Studio でコスト状況のレポートを毎朝 slack に連携しています。

![スクリーンショット 2023-11-26 12.11.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415560/78d19c31-6496-3a00-54e1-872975dfafa8.png)
このように可視化することで、料金が突然高くなっていないかを確認できるようにしています。
各プロジェクトの前日との料金の比なども同じレポート内で出力しています。

Looker Studio を採用した理由としては、料金が無料で簡単に BigQuery と連携して可視化できるためです。
レポートはメールとして出力することができて簡単に slack に送ることができたのも良かったです。

Looker Studio の使い方についてはこの記事では取り扱いません。
詳細は[公式ドキュメント](https://cloud.google.com/looker-studio#)をご確認ください。
Looker Studio での可視化についてはまだまだ改善の余地があり、どのような可視化を作っていくかは今後の課題です。

## 今後の展望

ギックスの組織規模はまだ小さいため、コストの最適化をすること自体のコストメリットが小さいです。
例えば Cloud 利用料が数十億円のような企業様であれば 1% の改善でも数千万円の改善につながるため取り組みやすいものの、ギックスではその規模に届いておらずまだ早いかなと思います。

とはいえ無駄遣いが細かく生じていることは間違いないため、引き続きコスト管理について検討していきたいです。
表示が崩れるよぉCSSって大変ね＞＜ の解決策？そんなの・・・あるぞ！（自動生成ツール）

みなさん日々の開発で困りごと、ありますよね？
私も日々困りながら、色々トライしています。今回は、自動生成ツールを実際に取り入れてみたので、感想を語ろうと思います。

# ケース：　表示が崩れるよぉ・・・CSSって大変
決して崩そうと思ってる訳ではないのですが＞＜
CSSって大変ですよね。
目視で見てもレイアウト崩れに気づけない場合も。
何か楽でいい方法はないかな？と思い、自動生成ツールを試してみることにしました。
![スクリーンショット 2023-11-26 12.09.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247390/75bd496f-b33f-99df-3067-7aaaab64554f.png)

# 自動生成ツールとは？
Figmaのデザインデータをもとに、HTMLとCSSを書き出してくれるツールのことです。ReactやVueにも対応しています。
私のお勧めは<a href="https://teleporthq.io/">TeleportHQ</a>です
![スクリーンショット 2023-11-26 12.11.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247390/e73475a3-7ce6-313f-e645-87be29def4d6.png)

# 自動生成ツールを使ってみて
## 良かった点
### デザイン通り、綺麗にスタイリングできる
基本的にデザインデータがそのままページになるので、レイアウト崩れがかなり少なくなりました。デザイナーさんから絶賛の声が届くほど
### とにかく早い
手動開発だと、HTMLのDOM構造を考え、クラス名を考え、CSSを書き、レイアウト崩れを直して・・・それらのステップが全部省略されます！

## 悪かった点
### 不要なCSSが増える
自動生成ツールという仕様の都合上、手動のコーディングでは、当たり前すぎて省略しているCSSもしっかり出力されてしまいます。そのため、だいぶCSSが長くなってしまいますね・・・
### 無意味なクラス名が多い
class12442 といった意味のないクラス名がつくことがあります。ここら辺は、しっかり吟味する通常の開発フローに慣れたエンジニアの方だと、抵抗あるかもしれません。なお、Figmaのレイヤー名に対応しているので、デザイナーさんが命名したクラス名がしっかり反映されている部分もあります。
### 頼りすぎてコンポーネント分けを怠ってしまった・・・
ページ全体に適用して終わった気になりますが、しっかりコンポーネント分けを行いましょう！（痛い目）

# まとめ
今回は自動生成ツールを実際に取り入れてみた感想を語りました。みなさんの体験談もぜひ教えてください！
The method 'getIdToken' can't be unconditionally invoked because the receiver can be 'null'. Try making the call conditional (using '?.') or adding a null check to the target ('!')

# はじめに
```
The method 'getIdToken' can't be unconditionally invoked because the receiver can be 'null'.
Try making the call conditional (using '?.') or adding a null check to the target ('!')
```
の解決に地味に苦戦したので、備忘録として残しておく。

# 対処方法
以下がエラーが発生したソースコード(必要な場所のみ抜粋)
```
User? user;
user = (await FirebaseAuth.instance.signInWithEmailAndPassword(
                      email: _email, 
                      password: _password
                      )).user;
String? token = await user.getIdToken();
```
tokenはString?にしてるから問題なくない？って思ったので、全然エラーの原因が分からなかった。
そしたら、エラーの原因について、詳しく説明している[記事](https://www.appsloveworld.com/flutter/200/165/the-method-foreach-cant-be-unconditionally-invoked-because-the-receiver-can-be)があった。
この記事によると、今回のエラーの原因はtokenではなく、userがnullになる可能性があるために発生しているエラーだった。
そのため、プログラムを
```
if (user != null){
    String? token = await user!.getIdToken();
}else{
    //userがnullだったときの処理
}

```
に変更したら、エラーは解決した。
Viteによって作成したReactアプリをGithub Pagesを使ってデプロイ！

# はじめに

前回、以下の記事でデプロイした際に画面が真っ白になったことを紹介しました。

https://qiita.com/otohusan/items/39160086ceec63c5b04a

今回の記事では、デプロイの流れを忘備録として記録しておこうかと思います。
<br>

※こちらの記事は
```
https://ユーザ名.github.io/リポジトリ名/
```
のようなURLにデプロイすることを想定しています。


## デプロイ

### 利用するツール

***Github Actions*** :

デプロイをする際に利用します。

また、指定したブランチにpushを行った際の行動などをworkflowsとして決めることで、自動でデプロイを行うことを可能にします。


### デプロイの流れ

大きな流れとしては、以下のVite公式を参考にしています。

https://ja.vitejs.dev/guide/static-deploy.html

<br>

 まず、***vite.config.ts*** に以下のコードを追加することで、baseを指定します。

```typescript
base: import.meta.env.DEV 
    ? "/" 
    : "/リポジトリ名/",
```

これにより、開発環境か否かでURLのbase部分を変更することができます。

<br>

次に、Githubのデプロイを行いたいアプリのrepositoryを開き、***Settings*** をクリックします。

![スクリーンショット 2023-11-26 11.50.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708101/87b5e454-0207-2532-87d2-d4859482010b.png)


そして、Settingsで ***Pages*** をクリック

***Source*** に ***Github Actions***を選択

最後に、***Static HTML*** を選択します。

![スクリーンショット 2023-11-26 11.55.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708101/655404f3-beb7-7bcf-b240-3f696a9395b4.png)

<br>

すると ***.Github/workflows/static.yml*** を編集するページに飛ばされるので、以下のコードをコピペします。

```yml
# 静的コンテンツを GitHub Pages にデプロイするためのシンプルなワークフロー
name: Deploy static content to Pages

on:
  # デフォルトブランチを対象としたプッシュ時にで実行されます
  push:
    branches: ['main']

  # Actions タブから手動でワークフローを実行できるようにします
  workflow_dispatch:

# GITHUB_TOKEN のパーミッションを設定し、GitHub Pages へのデプロイを許可します
permissions:
  contents: read
  pages: write
  id-token: write

# 1 つの同時デプロイメントを可能にする
concurrency:
  group: 'pages'
  cancel-in-progress: true

jobs:
  # デプロイするだけなので、単一のデプロイジョブ
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Set up Node
        uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: 'npm'
      - name: Install dependencies
        run: npm install
      - name: Build
        run: npm run build
      - name: Setup Pages
        uses: actions/configure-pages@v3
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v2
        with:
          # dist リポジトリのアップロード
          path: './dist'
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v2
```
上記のコードは、mainブランチにpushが行われた際に、自動的にデプロイすることを可能にしています。

最後に、commit changesを行なってstatic.ymlを更新しましょう。
<br>

### React Router の利用者向け

React Router を利用している方は ***main.tsx*** の **BrowserRouter** を以下のように編集します。

```typescript
<BrowserRouter basename={import.meta.env.DEV ? "/" : "/リポジトリ名/"}>
    <App />
  </BrowserRouter>
```

これにより、React Routerが誤ったURLを開くことを防ぎます。

# 終わりに

以上によって、デプロイ先のURLを開くとアプリを利用することが可能になっているはずです！

お読み頂きありがとうございます。
少しでもこの記事がお役に立てると光栄です！
Next.js のインストール時にsrcを選択した時と、しない時の差分の調査 (Next.js 14 App router)

Next.js のインストール時にsrcを選択した時としない時の差分の調査

Configuring: src Directory | Next.js

https://nextjs.org/docs/app/building-your-application/configuring/src-directory

# 理由
Next.jsサンプルなどで、srcフォルダを使わないApp routerのサンプルがあったので、
その時の差分はどこを修正すればいいのか調べました。

※自分は自分のコードをすべてsrcの下に置きたい派

↓例えば Vercel公式サンプルですが、srcフォルダは使われていません。

vercel/nextjs-subscription-payments: Clone, deploy, and fully customize a SaaS subscription application with Next.js.
https://github.com/vercel/nextjs-subscription-payments


この時自分でこのスターターを使う時に、ほんのちょっとファイルを修正するだけで、srcフォルダを使用できるようになります。

# 参考

Next.js App Router と Supabase と Stripe のスターターアプリに色んなパターンの環境変数を設定 #Next.js - Qiita
https://qiita.com/masakinihirota/items/1ae7d17377b8bac524d5

※Vercelのスターターを利用して、↑この記事を書いています。

----------------------------------------
----------------------------------------
----------------------------------------

# 差分＆移動＆修正

src/appフォルダを作ります。

```terminal
mkdir src/app

```

appフォルダの中身を、
src/appへ移動します。


```tailwind.config.ts
  content: [
    './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
    './src/components/**/*.{js,ts,jsx,tsx,mdx}',
    './src/app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
```

インストール時にTailwindCSSを使用しなければ修正は不要です。

```tsconfig.json
    "paths": {
      "@/*": ["./src/*"]
    }
```

必要なコードの修正箇所は2箇所だけです。
インストール時にpathsを設定しなければ修正は不要です。



# 追加

publicディレクトリはプロジェクトのルートに残しておきます。

package.json、next.config.js、tsconfig.jsonのような設定ファイルも、プロジェクトのルートに残しておきます。

.env.*ファイルはプロジェクトのルートに残しておきます。

src/appは、ルート・ディレクトリにappやpagesが存在する場合、無視されてしまいます。

srcを使用している場合、おそらく/componentsや/libなどの他のアプリケーションフォルダも移動します。（パスがきちんと設定してあれば移動させなくても大丈夫です。）

Middlewareを使用している場合は、srcディレクトリ内に配置されていることを確認してください。(※重要：結構忘れがち。)

Tailwind CSSを使用している場合は、contentセクションのtailwind.config.jsファイルに/srcプレフィックスを追加する必要があります。

# VSCodeのPath設定

VSCodeを利用している場合、ファイルを移動させるとファイル内のパスの設定が、
「自動で」変更されます。その時はpathが通るように「手動で」修正してください。



----------------------------------------
【Swift】標準イニシャライザとメンバーワイズイニシャライザの違い

# この投稿は何？

Swiftの構造体について、自動的に提供される2種類のイニシャライザを解説します。

> Swiftを基礎から学ぶには
自著、工学社より発売中の「[まるごと分かるSwiftプログラミング](https://amzn.asia/d/7YPWJwl)」をお勧めします。変数、関数、フロー制御構文、データ構造はもちろん、構造体からクロージャ、エクステンション、プロトコル、クロージャまでを基礎からわかりやすく解説しています。
> また、Swiftプログラミングを基礎から動画で学びたい方には、Udemyコース「[今日からはじめるプログラミング](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwii1qTuj_2BAxV4hlYBHbj5BqEQFnoECBYQAQ&url=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Fstart-programming-today%2F&usg=AOvVaw2vs4Sccq-bpfA4ZD2rCyNm&opi=89978449)」をお勧めします。

### 実行環境

- macOS Sonoma 14.1.1
- Xcode 15.0.1
- Swift 5.9

# 標準イニシャライザとメンバーワイズイニシャライザ

イニシャライザは、構造体のインスタンスを作成するため初期化を行う特別なメソッドです。
インスタンスの初期化手続きでは、型に定義されたすべてのプロパティに値が設定しておく必要があります。

Swiftのコンパイラは、構造体に2種類のイニシャライザを自動的に提供します。
標準イニシャライザとメンバーワイズイニシャライザです。

## 標準イニシャライザ

コンパイラは「すべてのプロパティに既定値が設定されている構造体」に対して、自動的に標準イニシャライザを提供します。
標準イニシャライザは、型名の後に括弧`()`があるだけのシンプルな形式です。

以下に定義する`SomeType`型は、すべてのプロパティに既定値が設定されています。
したがって、標準イニシャライザが自動的に提供されます。

```swift
struct SomeType {
    var number = 123
    var alphabet = "ABC"
}

SomeType()
```

## メンバーワイズイニシャライザ

構造体に「既定値が設定されていないプロパティ」がひとつでもあると標準イニシャライザは提供されなくなり、その代わりに**メンバーワイズイニシャライザ**が提供されます。
メンバーワイズイニシャライザは、呼び出し時にすべてのプロパティに値を設定できます。

```swift
struct AnotherType {
    var number: Int
    var alphabet = "ABC"
}

AnotherType(number: 123, alphabet: "XYZ")
AnotherType()   // error; standard initializers are no longer provided.
```

メンバーワイズイニシャライザが提供される場合、標準イニシャライザを呼び出すことはできなくなります。標準イニシャライザでは初期化を完了できないからです。

なお、型の定義で既定値が設定されているプロパティに関しては、メンバーワイズイニシャライザの呼び出し時に値の指定を省略できます。

```swift
AnotherType(number: 123)
```

実際のところ、標準イニシャライザが提供される場合はメンバーワイズイニシャライザも呼び出すことができます。

```swift
SomeType(number: 456, alphabet: "EFG")
SomeType(number: 789)
SomeType(alphabet: "XYZ")
```
Ubuntu22.04上でTypeScriptの環境構築

## Node.jsをインストール
公式から直接インストールすることもできますが、一般的にはバージョン管理ツールを使用することが推奨されているので、ここでは代表的なバージョン管理ツールであるnvmを使ってインストールします。

### nvmをインストール
[nvmの公式](https://github.com/nvm-sh/nvm#installing-and-updating)に従ってコマンドを打っていきます。環境に合わせて以下のどちらかを実行します。

```
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
```
```
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
```

以下は実行結果の最後のほうの抜粋です。

```
=> Appending nvm source string to /home/test/.bashrc
=> Appending bash_completion source string to /home/test/.bashrc
=> Close and reopen your terminal to start using nvm or run the following to use it now:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion 
```
nvmを使うにはターミナルを再度開くか、最後の三行のスクリプトを実行する必要があるとのことなのでどちらかを実行します。

実行できたら以下の確認用コマンドを打ちます。nvmと返ってくればインストール成功です。
```
command -v nvm
```

### nvmを使ってNode.jsをインストール
nvmをつかってNode.jsをインストールしていきます。ここでは直近のLTS(Long Time Support)をインストールします。2023年11月現在、LTSはv20.10.0です。

```
nvm install --lts
```

インストールできたら下記コマンドで確認します。バージョン情報が出力されればインストール成功です。
```
node -v
```
```
npm -v
```

## TypeScriptをインストール
nvmでNode.jsがインストールできたらTypeScriptをインストールしていきます。今回はローカルインストールを行います。

### 初期設定
まずTypeScriptをインストールしたいディレクトリに移動します。ない場合はmkdirで作成してください。ここでは事前に用意しておいたts_testに移動します。

```
cd ts_test
```

移動できたらpackage.jsonを作成します。作成しなくてもインストールはできますが管理が難しくなるため作成したほうがよいでしょう。下記コマンドを実行してください。

```
npm init -yes
```

ここでは全てデフォルトで作成するので-yesを付けています。

### TypeScriptのインストール
package.jsonが作成できたらTypeScriptをインストールします。ここではローカルインストールのため--save-devを付けます。

```
npm install typescript --save-dev
```

インストールできたか確認します。ローカルインストールしているのでコマンドの前にnpxを付けます。バージョン情報が出力されれば成功です。
```
npx tsc -v
```

### 設定ファイルの作成
最後にTypeScriptの設定ファイルであるtsconfig.jsonを作成します。

```
npx tsc --init
```
ここではデフォルトで進めますが、詳細を確認したい場合は以下の記事などを参考にしてください。
 - [tsconfigリファレンス [TypeScript公式]](https://www.typescriptlang.org/tsconfig)
 - [tsconfig.jsonの主要オプションを理解する [Qiita記事]](https://qiita.com/ryokkkke/items/390647a7c26933940470)

## TypeScriptを使ってみる
TypeScriptをインストールしたディレクトリに以下のような簡単な内容のファイルを作成してください。

```
vi index.ts
```

```index.ts
const hello: string = 'Hello, World!'
console.log(hello)
```

作成できたらtscコマンドでJavaScriptファイルにコンパイルして実行します。

```
npx tsc index.ts
```
```
node index.js
```
Hello, World!が出力されれば成功です。

## 便利なパッケージ

### [ts-node](https://github.com/TypeStrong/ts-node#installation)
TypeScriptファイルをJavaScriptファイルにコンパイルせずに直接コンソールに出力できます。


**インストール**
```
npm install ts-node --save-dev
```


**実行**
```
npx ts-node index.ts
```

### [ts-node-dev](https://github.com/wclr/ts-node-dev#install)
TypeScriptファイルの変更を監視し、変更があったら自動で直接コンソールに出力してくれます。

**インストール**
```
npm install ts-node-dev --save-dev
```

**実行(ctrl+c/command+cで中止)**
```
npx ts-node-dev --respawn index.ts
```

**実行文が長いのでショートカット作成**
package.jsonのscriptsの欄に以下のように追記してください。

```package.json
  "scripts": {
    "dev": "ts-node-dev --respawn"
  }
```

**実行**
```
npm run dev index.ts
```

エディタでTypeScriptファイルを変更し、保存するとコンソールの出力結果も変わるはずです。
sympy の primerange と sieve.primerange の違い

# はじめに

`sympy.ntheory.generate.primerange` と `sympy.ntheory.generate.sieve.primerange` はどちらも指定する範囲内の素数を列挙してくれる。

```python
>>> from sympy.ntheory.generate import sieve, primerange
>>> list(primerange(3, 20))
[3, 5, 7, 11, 13, 17, 19]
>>> list(sieve.primerange(3, 20))
[3, 5, 7, 11, 13, 17, 19]
```

ただし、
* `sieve`はメモリを確保する
* `sieve`は最大値が決まっている
* `primerange`は`sieve`を利用する

という違いがある。

# `sieve`はメモリを確保する

sieve(篩)という名前から予測できると思うが、`sieve`の裏にはエラトステネスの篩が実装されている。なので、例えば、

```python
sieve.primerange(1000, 2000)
```

というコードを実行すると、裏では2000以下の素数リストが作成される。1000以下の素数については不要であるのにもかかわらずだ。対して`primerange`は、`sieve`に保存されていればそれを使うが、基本的には指定された範囲の数に対して素数判定を行っている。なので、実行後にメモリ上には残らない。

# `sieve`は最大値が決まっている

`sieve`は、既知の素数をリストとして保存しているが、要領削減のため一般的な`list`形式ではなく、`array`を使っている。コンパクトに表現できる代わりに、C言語の型のサイズの影響を受けるので、sympy 1.12以前では$2^{31}-1$より大きい素数、1.13以降では$2^{32}-1$より大きい素数は扱えない。

つまり、

```python
sieve.primerange(2**100, 2**100+1000)
```

のような処理はエラーになる。対して`primerange`は、先ほども述べた通りの実装なので

```python
primerange(2**100, 2**100+1000)
```

が問題なく実行できる。

# `primerange`は`sieve`を利用する

```python
sieve.extend(100)
```
を実行すると、100以下の素数リストが確保され、この範囲では`sieve.primerange`も`primerange`も同様にリストを使って答えを返す。

100以上の場合、`sieve`は、素数リストを伸長することは既に述べた。では、`primerange`の場合はどうだろうか？　sympy 1.12以前では、逐一素数判定を行うため効率が悪かった。しかし、エラトステネスの篩のアルゴリズムを応用すれば、$100^2$までは篩による効率的な列挙方法が存在する。そこで、sympy 1.13以降では、既知の素数の最大値の2乗以下であれば、(結果は保存しないが)篩アルゴリズムを実行するようになっている。

# まとめ

`primerange` と `sieve.primerange` はどちらも指定する範囲内の素数を列挙する関数だが、どちらを使うべきかは使用場面によって異なるので、アルゴリズムの特性を良く理解していないと効率的な素数列挙ができない。
【ChatGPT＋DALL-E3】で透明人間を描く。


　どうも、カーブミラーです。

　今回は、DALL-E3で透明人間を描きます。X-Twitter上でアップされたものです。

:::note info
本記事は、ChatGPTの有料版で
行なっております。無料版では、
行なえません。あしからず。
:::

　2023/11/20に
　　X-Twitterで出てきた
　　　透明人間のプロンプトです。
[Creating the Invisible: A Guide to Unseen Figure Imagery Using GPT-4"](https://x.com/umesh_ai/status/1726506528608600293?t=FZyJ8V8tjA8yCmS0C5raIg&s=03)

　プロンプトは
　　こちらです。
```Text:透明人間Prompt
Create an image of a person doing something as an unseen figure with clothes on but invisible
```
　DeepL翻訳すると
「服は着ているが姿は見えない人物として、何かをしている人のイメージを作る」

　これを描画すると、
![DALL·E 2023-11-26 11.34.21 - An image showing a person as an unseen figure, wearing clothes but invisible. The scene depicts the clothes appearing as if floating in mid-air, perfo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/ac6ba1e4-064a-65a7-2d4b-040a736bd470.png)

***
　今回は、
　　紹介したかったものが
　　　エラーになることがわかり、
　　　　急遽、題材を変更しました。

　Advanced Data Analysis
　　以前、Code Interpreterと
　　　呼ばれた機能を頼る作業
　　　　だったのですが、
　　　　　そこでエラーに
　　　　　　なってしました。

　作業を確認して
　　良かったです。
　　　記事にしたあとで、
　　　　みなさんに
　　　　　ご迷惑をかける
　　　　　　ところでした。

　ということで、
　　今回は、ここまで。
フロントエンドがバックエンドよりも先に開発できるだと・・？（スキーマ駆動開発）

みなさん日々の開発で困りごと、ありますよね？
私も日々困りながら、色々トライしています。今回は、スキーマ駆動開発を実際に取り入れてみたので、感想を語ろうと思います。

# ケース：　フロントが後工程なのつらたん問題
![スクリーンショット 2023-11-26 11.44.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247390/24d1d70e-953e-4219-a10b-1ff12fe80422.png)
通常の開発は、バックエンドが先でフロントエンドが後という流れになりますよね。
しっかり計画を立てるんですが、ただそこは理想と現実の差があって、バックエンドが遅れちゃった場合に、後工程であるフロントエンドがアタフタするということがあります。そこで、「スキーマ駆動開発」をやってみることにしました。


# スキーマ駆動開発とは？
スキーマとは「構造」のことです。
構造をメインにして開発を進めるといった意味合いになります。今回、構造とは、OpenAPI定義書（通称yaml）を指します。
OpenAPI定義書を作ると、そこから、フロント側では、APIのリクエストレスポンスのTypescriptの型を作成して使うことができ、バックエンド側では、MockAPIとして、仮のレスポンスを返すサーバーを立てることができます。それによって、バックエンドがまだ開発前であっても、フロントエンドの開発を開始できます。
![スクリーンショット 2023-11-26 11.45.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247390/43527322-03ed-ee33-8e4b-fb669734befc.png)
# スキーマ駆動開発をやってみて
## 良かった点
### バックエンドがまだ開発前であっても、フロントエンドの開発を開始できる
納期のプレッシャーがある中、早く始めることができるということで、安心して開発を進めることができました。
### フロントだけで作業完結！APIが未完成・バグっていても関係なくガシガシ進められる
影響範囲をまずフロントだけで考えることができるので、整理できて集中することができました。

### APIのリクエストレスポンスのTypescript型定義をする必要がない
かなりスピードアップになったのと、自分で管理するコードが減ったことでシンプルになりました。

## 悪かった点
### OpenAPI定義書(yaml)を書くのが面倒
当初は、レスポンスの例をしっかり書いていたので、型が変わった際にその例も更新する必要があるなど、複雑で時間がかかっていました。そこで「<a href="https://mswjs.io/">MSW</a>」を取り入れてみると、型からレスポンスの例を生成してくれるので、その手間がなくなりました！MSWおすすめです

### 主に使うのはフロントエンドだが、レポジトリはバックエンドにある問題
あくまでAPIの定義書なので、バックエンドのレポジトリで管理しています。これに関して、使うのはフロントエンドなので、バックエンドのレポジトリにあっても、しっかりフロントエンド側で保守管理していくという気持ちが必要です。

# まとめ
今回はスキーマ駆動開発を実際に取り入れてみた感想を語りました。みなさんの体験談もぜひ教えてください！
twilloでchat-GPTと電話で会話する

## chat-GPTと会話する
コールセンターでの活用に向けて、電話で会話してみたいと思いコードを書いてみた。
### 事前に必要なアカウント
2. chat-GPT(API🔑)
2. twillo
2. ngrok

```python:main.py
from flask import Flask, request, redirect
from twilio.twiml.voice_response import VoiceResponse
import twilio.twiml
import time
import requests
from twilio.twiml.voice_response import Gather, VoiceResponse, Say
import openai
import json

OPENAI_API_KEY = ""
app = Flask(__name__)


def question(comment):
    headers = {
        "Content-Type": "application/json",
        "Authorization": "Bearer " + OPENAI_API_KEY,
    }

    json_data = {
        "model": "gpt-4-1106-preview",
        "messages": [
            {
                "role": "user",
                "content": comment + "短文で答えてください。",
            },
        ],
        "temperature": 0.7,
    }

    response = requests.post(
        "https://api.openai.com/v1/chat/completions", headers=headers, json=json_data
    )
    json_data = json.loads(response.text)
    print(json_data["choices"][0]["message"]["content"])
    return json_data["choices"][0]["message"]["content"]


@app.route("/answer", methods=["GET", "POST"])
def answer_call():
    """Respond to incoming phone calls with a brief message."""
    # Start our TwiML response
    response = VoiceResponse()
    gather = Gather(input="speech", language="ja-JP", action="/sendsms", method="POST")
    gather.say(
        "お電話ありがとうございます。メッセージをどうぞ。", language="ja-JP", voice="Polly.Kazuha-Neural"
    )
    response.append(gather)

    return str(response)


@app.route("/sendsms", methods=["POST"])
def sendsms():
    # 音声認識結果を取得する
    result = request.form["SpeechResult"] or ""
    to = request.form["From"] or ""
    if result != "" and to != "":
        print(result, to)
        resp = VoiceResponse()
        resp.say(
            "音声を認識しました。ありがとうございます。確認しますので、少々お待ちください、",
            language="ja-JP",
            voice="Polly.Kazuha-Neural",
        )
        res = question(result)
        resp.say(
            res,
            language="ja-JP",
            voice="Polly.Kazuha-Neural",
        )
        return str(resp)
    else:
        resp = VoiceResponse()
        resp.say("申し訳ございません。音声認識ができませんでした。", language="ja-JP", voice="alice")
        return str(resp)


if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=8000)
```
1. twillo登録
1. 電話番号を取得
1. ngrokも登録　**☜これ大事**
1. main.pyを立ち上げ
1. 別ターミナルで以下を実行、出てきたURLをtwilloに登録
```
ngrok http 8000
```
### 感想
音声にして聴くと、chat-GPTのフレンドリーさが、ますますフレンドリーになりました。

chat-GPTって、文字の言葉が基本優しいしフレンドリー。
あの優しい文面を音声で話すと、もっとフレンドリーに感じる。優しい、沁みる。

クレームの一次対応は、chat-GPTで正解な気がする。
Security Hub におけるセキュリティ基準のコントロール一覧を一回で全部出力するスクリプトを作った

<h3>背景

「[AWS Security Hub が AWS CloudFormation を使用した管理機能の強化を発表](https://aws.amazon.com/jp/about-aws/whats-new/2023/06/aws-security-hub-enhanced-management-capabilities-cloudformation/)」で以下のような update(Jun. 2023) がありました。

<i>また、新しい AWS::SecurityHub::Standard リソースを使用することで、NIST 800-53 や PCI DSS など、特定のセキュリティ基準を有効にして、そこに含まれる個別のコントロールを管理することもできます。

コントロール毎の有効化/無効化の設定をするために、Security Hub のコントロール情報を AWS CLI で出力したくなった人が急増(?)しているのではないでしょうか。

以下のように `aws securityhub describe-standards-controls` コマンドでセキュリティ基準の ARN を指定することで、該当のコントロール一覧を出力することができます。

```bash
# AWS Foundational Security Best Practices (FSBP) 標準のコントロール出力コマンド例

aws securityhub describe-standards-controls \
--max-results 100 \
--standards-subscription-arn arn:aws:securityhub:<region>:<account-id>:subscription/aws-foundational-security-best-practices/v/1.0.0
```
(参考: [AWS CLI Command Reference](https://docs.aws.amazon.com/cli/latest/reference/securityhub/describe-standards-controls.html))

<h3>課題

が！しかし、このコマンドは出力数が多くなると、途中までしか出力してくれません。上限は、上記の例のように `--max-results` で変更できますが、これも 100 までです。(なお、AWS FSBP のコントロールの数は、2023年11月時点で221個・・・)

出力が途中で途切れた場合は、下記のように "NextToken" という識別子が最後に出力されます。

```
    "NextToken": "U2FsdGVkX18tJIExN ～省略～"
```

これを上記のコマンドに "--next-token" という引数のパラメータに指定することで、残りのコントロールを出力することができます。

```bash
aws securityhub describe-standards-controls \
--next-token "U2FsdGVkX18tJIExN ～省略～" \
--max-results 100 \
--standards-subscription-arn arn:aws:securityhub:<region>:<account-id>:subscription/aws-foundational-security-best-practices/v/1.0.0
```

いかがでしたでしょうか？簡単ですね。

・・・え？「面倒くさい。こんなの毎回やりたくない。」ですか？はい！私もそう思いました！

<h3>Bash のスクリプトを使って解決

そうするとスクリプトや、プログラムを作って、効率化できそうですよね。ということで、コントロールの量が多くても一撃で一覧を出力できる Bash スクリプト作りました。

```bash
#!/bin/bash

export script=$0
export standardsArn=$1
export maxResults=100
export nextToken=""
export outputFile="outputFile.json"

while true ; do

    aws securityhub describe-standards-controls --next-token "${nextToken}" --max-results "${maxResults}" --standards-subscription-arn "${standardsArn}" > ${outputFile}
    
    cat ${outputFile} # 結果出力箇所、なおここで jq コマンドにパイプするなどして、出力形式をカスタマイズすることも可能

    export nextToken=$( cat ${outputFile} | jq -r ".NextToken" ) 

    if [ $nextToken = "null"  ]; then # .NextToken がnullなら終了
        exit 0
    fi
done

```

実行はスクリプト(例: `describe-standards-controls_loop.bash`)とセキュリティ基準の ARN を指定することで出力が可能です。

```bash
bash describe-standards-controls_loop.bash arn:aws:securityhub:<region>:<account-id>:subscription/aws-foundational-security-best-practices/v/1.0.0
```

このサンプルで、誰かがちょっとでも楽になっていただければ幸いです。
Array の処理は可能な限り map, reduce, find を使ってほしい件

# 配列処理をわかりやすく書きたい

いきなりですがエンジニアの皆さん、配列の処理はどうやっていますか？

例えば以下のケースではどんなコード/関数/メソッドを使うか考えてみてください。

1. ある配列から同じ長さで別の配列を生成したい
1. ある配列のうち条件を満たす要素を一つ取得したい
1. ある配列のうち条件を満たす要素を複数取得したい
1. ある配列から一つの計算結果を出したい

今回の説明においては、言語は TypeScript/JavaScript を使います。

配列は `[1, 2, 3, 4, 5, 6, 7, 8, 9]` として

1. 配列の全ての要素を 2 倍して新しい配列を生成する
1. 配列で値が 4 である要素を取得する
1. 配列の要素のうち偶数のみの配列を生成する
1. 配列の要素の合計値を出す

で解説をします。

## 1~4 を全て for で実装

最もわかりやすい例は for 文を使うことでしょう。

for で 1~4 を実装した例を示します。

Playground にサンプルコードを載せていますので動かしてみたい方は[こちらから](https://www.typescriptlang.org/play?#code/MYewdgzgLgBAhgJwXAnjAvDA2gRgDQwBMBAzAQCwECsBAbAQOwEAcBAnALoDcAUD6JFgAzEAhwAlAKYQArgBsoALhhgZAWwBGkhFg4Zs3HiIQwAFAOgxJcyWslhYIIfCSoAlDADePGDGMTpeSgAOgAHGQgAC1NrW3tYACoiN14AX35wCBAbYLkQAHNTfylZBRS+HhthUUISoOVVTW19AFocXmMzC1hYuwcYJxdkFA9vXwBLZxibPth0eZhyUZ9fPxq6hX1e+N5VmA0ESTgAa12YdPSLbMlcgqL1wLLePm61hBINpRV1LR09TF0HVEXUyPRm8QGzkQw2WEym236AFIiBgFgAGWGrYwfR4hcJRaZxBzlPYHI6nFYXDKQa63QrYz7lSqSaoIcifBo-ZqYNFAkzmUFWcH9QbQ9xeFbGdm4mAAakwCKgaWpWRyeXpomlpSg5SAA)。

```typescript
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const for1Result: number[] = [];
for (const element of array) {
  for1Result.push(element * 2);
}
console.log(for1Result);

let for2Result: number = -1;
for (const element of array) {
  if (element === 4) {
    for2Result = element;
    break;
  }
}
console.log(for2Result);

const for3Result: number[] = [];
for (const element of array) {
  if (element % 2 === 0) {
    for3Result.push(element);
    break;
  }
}
console.log(for3Result);

let for4Result: number = 0;
for (const element of array) {
  for4Result += element;
}
console.log(for4Result);
```

一見は問題なく実装はできていますが、個人的には

- アウトプット用の定数/変数を定義して書き換えているのが関数型っぽくない
- for の中身を見ないと期待する結果がわからない

といった理由から直したい衝動に駆られます。

## じゃあどうするか

1~4 を叶えるメソッドが JavaScript にはあるので、それらを使いたい。

ざっくりまとめると

1. ある配列から同じ長さで別の配列を生成したい: **map**メソッドを使う
1. ある配列のうち条件を満たす要素を一つ取得したい: **find**メソッドを使う
1. ある配列のうち条件を満たす要素を複数取得したい: **filter**メソッドを使う
1. ある配列から一つの計算結果を出したい: **reduce**メソッドを使う

となる。公式の解説は[こちらのページから](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array)。

それぞれ解説していきます。

### ある配列から同じ長さで別の配列を生成したい: **map**メソッドを使う

```typescript
// 配列の全ての要素を2倍して新しい配列を生成する map
const mapResult = array.map((element) => element * 2);
console.log(mapResult);
```

外部にアウトプット用の定数を定義することなく、かつ map を使っているので array と同じ長さの別の配列が来ると考えられるので意味もわかりやすくなっています。

ついでに 1 行で書けてスッキリしていますね。

### ある配列のうち条件を満たす要素を一つ取得したい: **find**メソッドを使う

```typescript
// 配列で値が4である要素を取得する find
const findResult = array.find((element) => element === 4);
console.log(findResult);
```

こちらも外部にアウトプット用の定数を定義することなく、かつ filter を使っているので array から特定の値が来ると考えられるので意味もわかりやすくなっています。

### ある配列のうち条件を満たす要素を複数取得したい: **filter**メソッドを使う

```typescript
// 配列の要素のうち偶数のみの配列を生成する filter
const filterResult = array.filter((element) => element % 2 === 0);
console.log(filterResult);
```

ry

### ある配列から一つの計算結果を出したい: **reduce**メソッドを使う

```typescript
// 配列の要素の合計値を出す reduce
const reduceResult = array.reduce(
  (accumulator, currentValue) => accumulator + currentValue
);
console.log(reduceResult);
```

ry

## まとめ

JavaScriptに限らずPythonやRustにも同様です。

for一辺倒で片付けずにどの書き方が良いかを考えるきっかけにしてみてください！
checkstyleをコマンドラインから実行し、循環的複雑度のレポートをXML形式で作成する

表題の通り、checkstyleをコマンドラインから実行し、循環的複雑度のレポートをXML形式で作成する手順を示します。

**① checkstyleのjarファイルの取得**

GitHubのcheckstyleレポジトリのリリースページからcheckstyleのjarファイルをダウンロードします。

https://github.com/checkstyle/checkstyle/releases

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/3ffb209b-8701-cb4f-3a85-7e4bf8d3a894.png)

**② 設定XMLファイルの作成**

以下のような設定XMLファイルを準備します。

```xml:
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" "https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name = "Checker">
  <module name="TreeWalker">
    <module name="CyclomaticComplexity">
      <property name="max" value="0"/>
    </module>
  </module>
</module>
```

循環的複雑度以外の情報は不要なため、循環的複雑度用の設定だけを記載しています。また、max=0とすることで、循環的複雑度の値にかかわらず、すべてのメソッドの循環的複雑度を取得できます。

**③ checkstyleの実行**

checkstyleコマンドラインから実行して、XML形式のレポートを作成します。

```
java -jar path\to\checkstyle-10.12.5-all.jar ^
     -c   path\to\config.xml ^
     -f   xml ^
     -o   path\to\cc_report.xml ^
     path\to\source
```

実行結果は次のようになります

```xml:path\to\report.xml
<?xml version="1.0" encoding="UTF-8"?>
<checkstyle version="10.12.5">
  <file name="path\to\source\package001\A001.java">
    <error line="11" column="1" severity="error" message="循環的複雑度が 1 （最大 0 まで）です。" source="com.puppycrawl.tools.checkstyle.checks.metrics.CyclomaticComplexityCheck"/>
  </file>
  <file name="path\to\source\package002\B002.java">
    <error line="22" column="2" severity="error" message="循環的複雑度が 2 （最大 0 まで）です。" source="com.puppycrawl.tools.checkstyle.checks.metrics.CyclomaticComplexityCheck"/>
    <error line="33" column="3" severity="error" message="循環的複雑度が 3 （最大 0 まで）です。" source="com.puppycrawl.tools.checkstyle.checks.metrics.CyclomaticComplexityCheck"/>
  </file>
</checkstyle>
```
日本語プログラミング言語 スミレ Java C# でHello World実行時間を仲良く競う

# はじめに
日本語プログラミング言語 スミレ とJava C# とで「Hello World」コンソール出力の反復実行時間を仲良く競い合わせてみます。前回プロデルコンパイラ2.0で検証したソースコードをスミレコンパイラ1.9でコンパイルし、C#と同じ.NET Core 6で実行してみます。

## この記事内容の作業環境
Windows11 Pro 22H2
VSCode(Visual Studo Code)　1.78.2
java Eclipse Adoptium jdk-20.0.2.9-hotspot
C# 10 dotnet-sdk-6.0.404-win-x64
sumire Version 1.9.1191
CPU Intel(R) Core(TM) i3-5005U 2.00 GHz

## この記事内容の保証
※この記事の実行結果は参考情報です。実行環境に大きく依存します。

## 参考記事
### プロデルの結果
[日本語プログラミング言語 プロデル Java C# でHello World実行時間を仲良く競う](https://qiita.com/mylifewithviolin/items/fdc00911a1600a4786c4)

### スミレ とは
[日本語プログラミング言語 スミレ とは](https://qiita.com/mylifewithviolin/items/8f90f8452d65439fd825)

# お題のソースコード
#### Java
お手数ですが[参考記事 プロデルの結果](https://qiita.com/mylifewithviolin/items/fdc00911a1600a4786c4)をご参照ください。

#### C#
お手数ですが[参考記事 プロデルの結果](https://qiita.com/mylifewithviolin/items/fdc00911a1600a4786c4)をご参照ください。

#### スミレ
```mind:helloworld.rdr
※コンソール
    【count:整数】は、0
    【countMax:整数】は、0
    
    もしプログラムのコマンドライン引数が無なら
    　　countMax=0
    そうでなければ
       例外監視
    　　  countMax=プログラムのコマンドライン引数(1)
    　　発生した場合
     　　 countMax=0
        監視終わり
    もし終わり
    
    開始日時は、今日
    count < countMaxの間、繰り返す
    　 「Hello World!」をコンソールへ表示して改行する
    	count =count +1
    繰り返し終わり
    終了日時は、今日
    時間差は、終了日時-開始日時
    
    「処理回数：」＆ count＆ 「回」をコンソールへ表示して改行する
    「処理時間：」＆ 時間差の合計ミリ秒数＆ 「ミリ秒」をコンソールへ表示して改行する
    
```
# 実行結果
#### Java
お手数ですが[参考記事 プロデルの結果](https://qiita.com/mylifewithviolin/items/fdc00911a1600a4786c4)をご参照ください。

#### C#
お手数ですが[参考記事 プロデルの結果](https://qiita.com/mylifewithviolin/items/fdc00911a1600a4786c4)をご参照ください。

#### スミレ

```:
C:\sumire\evalution>\sumire\sumire.exe helloworld.rdr 40000
Hello World!
・・・
Hello World!
Hello World!
Hello World!
処理回数：40000回
処理時間：6368.4163ミリ秒

C:\sumire\evalution>
```
# 実行結果まとめ
表1　「Hello World」コンソール出力の反復実行時間（ミリ秒）
| 実行回数 | Java | C# | スミレ |
|-:|-:|-:|-:|
|  40 |  8 | 16  | 57 |
| 400  | 72  | 57  | 132  |
| 4,000  | 563  | 468  | 761  |
| 40,000  | 4,565  | 4,206  | 6,368  |
| 400,000  | 42,618  | 40,075  | 56,089  |

※ナノ秒台は切り捨て

# おわりに
いかがでしたでしょうか？コンソール出力を単純にループさせているだけですので、各言語、実装によってはいろいろな差異がでるものと思われますので、この件はあくまで参考情報です。
集合の結合 Python3編

https://paiza.jp/works/mondai/data_structure/data_structure__set_boss

2つの集合を１つにしてソートして出力する問題
和集合は下記のように　`A | B`　または　`A.union(B)`

```py
N = int(input())
A = {int(x) for x in input().split()}
B = {int(x) for x in input().split()}
print(*sorted(A | B))
```

他のやり方

```py
N = int(input())
A = [int(x) for x in input().split()]
B = [int(x) for x in input().split()]

c = set(A + B)

print(" ".join(map(str, sorted(c))))
```

下の方が直感的にわかりやすいか？
エラトステネスの篩で素数を出力するpythonプログラム

エラトステネスの篩で素数を出力するpythonプログラムです。
`chmod +x sieve.py`
`./sieve.py <n>`として実行してください。
```sieve.py
#!/usr/bin/python3
import sys

def sieve(n):
  tab=[_ for _ in range(2,n+1)][::-1]
  l=[]
  while (tab):
    l+=[v:=tab.pop()]
    tab=[_ for _ in tab if _ % v ]
  return l

if __name__ == "__main__":
    if (len(sys.argv)!=2):
        print("Invalid argument.")
        print(f"Usage: {sys.argv[0]} <number>")
        exit()
    else:
        n=int(sys.argv[1])
    primes=sieve(n)
    print (f"{primes}\nNumber of primes is {len(primes)}.\n")
```
エラトステネスの篩で素数を出力するperlスクリプト

エラトステネスの篩で素数を出力するperlスクリプトです。
`chmod +x sieve.pl`
`./sieve.pl <n>` として実行してください。

```sieve.pl
#!/usr/bin/perl

sub sieve {
  local($n,@tab,@l,$v,$x,@t);
  $n=$_[0];
  @tab=(2..$n);
  @l=();
  while (@tab) {
    $v=shift(@tab);
    push(@l,$v);

    @t=();
    while (@tab) {
        $x=shift(@tab);
        if ( $x % $v ) {
            push(@t,$x);
            }
        }
    @tab=@t;
    }
  return @l;
}

@primes=&sieve($ARGV[0]);
$,=',';
$len=@primes;
print "@primes\nNumber of primes is $len.\n";
```
重複の判定 1 (paizaランク C 相当)

https://paiza.jp/works/mondai/data_structure/data_structure__set_step3

>N 個の要素からなる数列 A が与えられます。2 ≦ i ≦ N の各 i に対して、A_i と同じ値が A_1 から A_{i-1} の間にあるかどうかを判定してください。


考え方としては、まずAのリストをつくり、そこからBのリストに、まず１個入れ、そこからループするたびにBのリストにA１つずつ入れていき、
ループするたびにあるかどうか確かめ出力し、また１個入れ。。。というのを繰り返す

```py
N = int(input())
A = [int(x) for x in input().split()]
B = []
for i in range(N):
    if i == 0:
        B.append(A[i])
    else:
        if A[i] in B:
            print('Yes')
        else:
            print('No')
        B.append(A[i])
```
上をもっと短くするなら
Bの配列を作る時にしれっとA[0]をいれてしまっておくと
if文が１つなくなり可読度が上がる

```py
N = int(input())
A = [int(x) for x in input().split()]
B = [A[0]]
for i in range(1,N):
    if A[i] in B:
        print('Yes')
    else:
        print('No')
    B.append(A[i])
```

答えだと集合を使っていた
・メリットとしてはデータから重複削除するので、データを検索する時間が短くなる（はず）
・集合に要素を追加する場合は`append()`の代わりに`add()`を使う

```py
N = int(input())
A = [int(x) for x in input().split()]

memo = {A[0]}
for i in range(1, N):
    if A[i] in memo:
        print("Yes")
    else:
        memo.add(A[i])
        print("No")
```
思考方法-メンタルモデル

## メンタルモデル
メンタルモデルとは、頭の中でシステムの挙動をイメージすることです。
つまり、「どこで何をしているのか」を頭の中で考えられることです
システム開発では、この思考方法が重要だと感じてます。

### 理由
システム開発では、様々なインシデントが発生します。
その際に、システムの挙動がイメージ出来ていると、問題点を素早く見つけることが容易になります。また、試験項目票作成では、確認したい機能が明確なものを作ることができるようになります。
技術力向上のためにエンジニア組織全体で取り組んでいること

### 技術力向上のためにエンジニア組織全体で取り組んでいること

エムスリーキャリア社のFY23 Advent Calendarは、近藤（@atkondo)からスタートさせて頂ければと思います。
私からはエンジニア組織全体の取り組みについて述べさせて頂きます。

FY23には、組織としては以下のような課題が顕著となって来ていました。

・1つのチームが5名前後でチーム内の育成には問題が無いもののの、さらにチームを超えたレベルアップの仕組みが不足している
・要件定義や仕様調整能力をレベルアップしたい
・Modern Data StackやChatGPTなどの新しい技術にキャッチアップして行きたい
　
FY24では3つの取り組みを実施しています。
・レビュー力アップ（→技術標準の設定）
・学ぶ場の形成
・新規技術への取り組み

### レビュー力アップ（→技術標準の設定）
この施策のきっかけが生まれたのは、チーム内に閉じたサポートでは、チーム内の知見、経験を超えたフォローが難しいのでは無いか？という意見でした。
当社では1チームが4〜6名程度のサイズで、9チーム存在しています。
コードレビューのスタイルとしては全員でレビューを行うチームもあれば、当番制で行っているチームもあります。

レビュー力アップの取り組みでは、チーム相互レビューということを実施してみました。
レビューを受けるチームのメンバーから概要を説明した後、もう片方のチームがレビューをしてみる、簡単に振り返るという段取りで実施してみました。

1、2度の取り組みでは、レビュー観点での気付きを得るというところまで行くのは難しいですが、他チームのシステム、技術、開発の進め方などへの関心を増すことができたという効果はあったかと思います。

下期からチームで採択している技術のうち、未採用であれば取り入れたり、運用が異なっていればベターな運用に合わせて行くという、技術標準化につながっています。
具体的には、WAF,CI/CD,Docker,Terraformなどをテーマとしています。

### 学ぶ場の形成

・ 「ソフトスキル（特にコミュニケーション）」
　この施策が必要では無いか？という話が上がったのは、ビジネスサイドとの要件定義や仕様調整を担当するメンバーが増えたことがきっかけでした。

 取り組みの1つとして実施したのが、グループワークです。ソフトスキルとは何か？どのような試みがコミュニケーションを円滑にすることに繋がるのか？議論してみました。
 
 グループワーク後に、行動として試みていることは、ビジネスサイドの方々座っている座席島にお邪魔して業務を行うということです。
 
 グループ外留学とネーミングしています。すでに5名ほど数回に渡って実施しており、直接話をせずとも日頃どのような会話がなされているのか聴こえてくる会話を聴いているだけでも、業務の背景などへの理解、解像度が上がりつつあるようです。

 
・ 「ソフトウェア設計スキル」
同様にメンバーの中からはソフトウェア設計スキルを上げて行く機会が欲しいという声が上がりました。
取り組みとして実施したのが、アーキテクチャを語る会です。日頃疑問に思っていることをざっくばらんに語り合う、相談し合うという場です。

数回のステップを得て、会社全体のシステムのアーキテクチャーを再考して行く場に昇華して行きたいと考えています。

当社では現在、システムグランドデザインを作成しています。30〜４０ある事業の垂直的な立ち上げ時期から、お客様に向けたシームレスなサービス提供を可能とする時期に変化して来ていると考えています。

検討に当たっては、デジタル庁　「データ連携基盤の整備について　公共サービスメッシュの整備（P5)」などを参考にさせて頂いています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66640/53b20d97-2959-9cec-34e9-3bc08043f486.png)


https://www.cas.go.jp/jp/seisaku/digital_denen/dai4/siryou8.pdf


### 新規技術への取り組み
今季は2つの技術について取り組んでいます。
1つはデータ基盤（DataModern Stack)、もう1つはChatGPT (AzureOpenAI / GithubCopilot)です。

・ データ基盤（DataModern Stack)
これまでのデータ基盤はDWH（AWS Aurora） ＋　BIツール（Redash等）という形式でした。ただ、ここ数年、サービスをシームレスに提供するために、データ連携をさせたいというニーズが高まって来ています。

さまざまデータソースからデータを取得して、かつ、集計データを保持するということで、BigQueryを用いて以下のような構成を新たに構築しました。
`Datalake→DataWarehouse→DataMart`

また、ETLツールとして、troccoを採用して、データ転送をより分かりやすい仕組みに変更しています。

現時点では、地理空間データをさまざまなサービスで利用できないか？などプロトタイプによって検討を進めています。



・　ChatGPT (AzureOpenAI / GithubCopilot)
当社では社内ChatbotとしてAzureOpenAIを、コード支援としてGithubCopilotを利用しています。

今後はサービス/業務上の直接的な用途に利用をして行こうと、ワーキンググループにて試験的な活用を進めています。
日本語プログラミング言語 スミレ とは

# はじめに
日本語プログラミング言語「スミレ」とは、日本語プログラミング言語「プロデル」の開発者@jpl_produireさんが密かに？開発された「プロデル」の.NET Core版のことです。ダウンロードの仕方がちょっとわからなかったので備忘録です。「スミレ」自体を知らなかった方はよろしくです。

# 参考リンク
「プロデル」の開発者@jpl_produireさんによるQiita上の「スミレ」関連の記事は唯一こちらとなります。（2023/11/26時点）

https://qiita.com/jpl_produire/items/fb1625aa1dcde2c1bbf2

しかし、こちらの記事はよく読むと、言及されているのは「スミレ畑」の方のことでした。

# スミレ畑とは

こちらはスミレが咲き誇るお花畑のメタファーから（私の勝手な解釈）命名された、.NET Core版プロデルであるスミレの発展的な実行環境としてWeb標準の次世代実行環境であるのWebAssemblyアセンブラ言語をコンパイル出力するようにしたバージョンで、実行環境はブラウザとなります。

# スミレとは

日本語プログラミング言語「プロデル」が.NET FrameworkのCLR中間コードにコンパイルするのに対して、「スミレ」は日本語プログラミング言語「プロデル」言語を.NET CoreのCLR中間コードにコンパイルするコンパイラ言語です。

# スミレの入手方法（ダウンロード先）

日本語プログラミング言語「プロデル」の公式サイトのトップページでは「プロデル」のダウンロードと「スミレ畑」の起動が大きくクローズアップされていますが、「スミレ」のダウンロード情報は特に記載がなく、どこで入手するのかなとしばらく思っていました。（公式ブログ記事で「スミレ」のリリースは認識）

https://rdr.utopiat.net/

![utopiat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118036/a0504ea0-0e75-4434-ae06-57421d58d88d.png)

今回、「スミレ」の検証記事を書こうと思い立ち、入手方法を確認しましたところ、下記のサイトからダウンロードすることができました。

https://sum.irelang.jp/

![sumire.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118036/1e7e6799-92b4-1fc0-83c7-7e2c6050a221.png)


このサイトの「スミレ(ダウンロード版)使い方」リンクから入っていくと、詳しい使い方が記載されています。


「スミレ」は別ドメインの別サイトだったのですね！:writing_hand:
ABC330回答メモ

# 0.はじめに
　B問題すら難しい感じのコンテストで、苦戦しました。
　どうにかABDを正解したものの若干レートを落として
　-9でした。

　E問題はもう少し頑張ればACもらえそうですが
　解説を丸々参考にして解いているのでここのメモは残さないでおきます・・。

# 1.A - Counting Passes
　さすがにA問題は単純な問題で
　リストを頭から見て、Lを超えている数を数える
　だけの簡単なお仕事でした。

　https://atcoder.jp/contests/abc330/submissions/47892558


# 2.B - Minimize Abs 1
　正直問題の意味が全く分からず、例題をみて、
　リストの値が、L以下ならL、R以下ならR、それ以外はリストの値
　ではないかと、直感的に思い実装したところ
　正解でした。

　https://atcoder.jp/contests/abc330/submissions/47903056


# 3.C - Minimize Abs 2
　コンテスト時は、XをDの平方根から1ずつ減らしていき
　それに合うYを求める・・・という方式を思いつきましたが
　TLEかと思い断念しDに行ってしまいました。

　コンテスト後、解説を見たら、考え方はあっていたようだったので
　改めて組みなおしつつ、微調整をしたところACをもらえました。

　【実装】
 　　1.Nの平方根をmにセット、ansに10の18乗をセット
 　　2.iを１～mまでループ
   　　2-1.Nからiの2乗を引いた数をpにセット
   　　2-2.pの平方根をqにセット(qはint型に切り捨て)
   　　2-3.ansに、以下の数の中で最小の値で置き換える
     　　・ans
       　・Nからiの2乗とqの2乗をマイナスした数
       　・Nからiの2乗とq+1の2乗をマイナスした数
 　　3.ansを出力して終了

　https://atcoder.jp/contests/abc330/submissions/47955214


# 4.D - Counting Ls
　NがMAX2000なので、1回くらいはNの2乗のチェック可能と思いそこから組み立て。
　【考え方】
    ・列ごと、行ごとに”o”の数を求める。
    ・Sの表を端から見ていき”o”だった場合そのアドレスの
    　行列のoの数-1をそれぞれかけた値をansに加算
    ・ansを出力して終了

　最初行だけ集計すればOKかなと思いチャレンジしてTLE等、無駄な時間を
　過ごしたことが悔やまれます。

　https://atcoder.jp/contests/abc330/submissions/47933991


以上
Amazon Route53の耐障害性を考える

# はじめに
この記事はDevOps on AWS大全の一部です。
DevOps on AWS大全の一覧は[こちら](https://qiita.com/tech4anyone/items/b06f88035d27c6ef13b2)。

この記事ではAmazon Route53を耐障害性の観点から超詳細解説しています。

具体的には以下流れで説明します。

- Amazon Route53とは
- 耐障害性を考慮したルーティング


AWSの区分でいう「Level 200：トピックの入門知識を持っていることを前提に、ベストプラクティス、サービス機能を解説するレベル」の内容です。

# この記事を読んでほしい人
- Amazon Route53を採用するときのベストプラクティスを説明できるようになりたい人
- Amazon Route53の耐障害性に不安を感じている人
- AWS Certified DevOps Engineer Professionalを目指している人

# Amazon Route53とは
Amazon Route53とは高可用、スケーラブル、そして完全マネージド型の権威DNSサーバです。
また、Route53は権威DNSサーバであると同時にドメインレジスターでもあります。

Route53を理解するためには、Record、Hosted Zone、Routing Policyの3つを理解する必要があります。

## Record
Route 53の基本的な構成要素はRecordです。
これは、ドメインに関連付けられた各リソースのエントリーで、主にドメイン名をIPアドレスに対応付けます。

Recordの中にはDomain/subdomain Name、Record Type、Value、Routing Policy、TTLという5つの設定項目があります。

Domain/subdomain Nameはドメイン名、ValueはIPアドレス、TTLはDNSリゾルバでのキャッシュ期間です。
Routing Policyは耐障害性を考慮したルーティングのところで詳しく説明します。

Record Typeの主なものには以下があります。
| レコード名 | 説明 |
|--- | ---|
| A | ドメイン名をIPv4アドレスに解決 |
| AAAA | ドメイン名をIPv6アドレスに解決 |
| CNAME | 別のドメイン名にエイリアスを設定 |

ほかにもMXやTXTなどのレコードがありますがDNSの項目になるのでここでの説明は割愛します。

## Hosted Zone
Route 53では、ドメインを管理する単位としてHosted Zoneがあります。
これは特定のドメインに関連するDNSレコードの集合体で、各Hosted Zoneには一意の名前が付与されます。

Hosted Zone内でレコードセットを設定することで、ドメインの挙動や解決ルールを定義できます。
例えば、www.example.com をどのIPアドレスに解決するかなどがホステッドゾーンで設定されます。

Hosted ZoneにはPublicとPrivateが存在し、インターネットからつなぐ場合にはPublicをVPC内部での通信に閉じる場合にはPrivateを利用します。

なお、PublicとPrivateで同じドメインを登録するとインターネットからのアクセスにはPublic Hosted Zoneが応答し、VPCからのアクセスにはPrivate Hosted Zoneが応答します。

あまりないとは思いますが、どうしても内部で通信をひねりたいがクロスドメインにしたくないというときには活用できる仕組みです。

# 耐障害性を考慮したルーティング
Route53はAWSのサービス内で唯一SLAが100%のサービスです。
そのため、Route53自体の耐障害性を考える必要はありません。
Route53の耐障害性で考える必要があるのはルーティング先のサービスまで含めて可能な限りダウンタイムを短くする、というパターンです。

そのために使うRoute53の機能がRouting Policyです。
代表的なRouting Policyごとの説明を以下にまとめます。

## Simple Routing Policy
単一のリソースにトラフィックを転送します。主に単一のエンドポイントを持つシンプルな用途に適しています。

## Weighted Routing Policy
複数のリソースに対して異なる重みを設定し、トラフィックを分散させることができます。例えば、新しいバージョンのアプリケーションに一部のトラフィックを導入する場合に有用です。

## Latency-Based Routing Policy
クライアントの地理的位置に応じてトラフィックを最も低いレイテンシを持つエンドポイントに導くことができます。グローバルに展開されたアプリケーションで効果的です。

## Failover Routing Policy
プライマリとセカンダリの2つのリソースを設定し、プライマリが利用できない場合にセカンダリにトラフィックを自動的にフェイルオーバーさせます。

## トラフィックフロー
耐障害性という観点でRouting Policyを見るとFailover Routing Policyが最も優れています。
ただ、実際の運用を考えるとFailover Routing Policyだけで運用するというのはあまり現実的ではありません。

例えば、リリース作業を考えるとトラフィック分割のためにWeighted Routing Policyも使いたいという場面は多いでしょう。

そのため、トラフィックフローを用いたRouting Policyの組み合わせがRouting Policyのベストプラクティスです。

![](https://storage.googleapis.com/zenn-user-upload/0840dc5371b8-20231126.png)

トラフィックフローとは複雑なルーティングのサポートをしてくれるサービスです。
具体的には複数のRouting Policyを組み合わせて使用する場合に発生するレコード設定の複雑な階層構造管理をできるようにしてくれます。

このサービスを利用するとWeighted Routing Policyでトラフィック分割しながらリリースできる仕組みを作りつつ、バックエンドがダウンした時に備えたFailover Routing PolicyでSorry画面に自動で向くようにする、といったことが可能になります。

# まとめ
この記事ではAmazon Route53を耐障害性の観点から超詳細解説しました。

- Amazon Route53とは
- 耐障害性を考慮したルーティング

次回はRDSの耐障害性を考えます。