OmniAICreator/Qiita-1.07M huggingface dataset:
リーンな開発を目指すエンジニアリングマネージャが読んだ本

この記事は、[みらい翻訳 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/miraitranslate) 1日目の記事です。

株式会社みらい翻訳 プラットフォーム部で、エンジニアリングマネージャーをやっています。 @nile_mt です。

[昨年](https://qiita.com/advent-calendar/2020/miraitranslate)に引き続き、みらい翻訳でもAdvent Calendarやることになりました。初日は緊張しますね。

# この記事について

私自身は、機械学習系のエンジニアではなく、Web系で、今はエンジニアリングマネージャーで、つまりマネジメント系の人です。

今年１年は、どうしたらリーンに開発ができるのか、どうしたらフルサイクルエンジニアリングを目指せるのかをテーマに活動してきました。

そんな中、常に考え議論していたのは「プロダクトマネジメントとは？」、「リーンとはどういうことか？」「Agileとは、スクラムとは？」といった、根本をあらためて問うようなことだったように思います。

（その時に、なにを考えたとか、実際どうしたかは、長くなりそうなので、改めてどこかで）

今回は、そういった中で参考にさせていただいた（あるいは、参考にしようと思って買ったけど未読なモノも含む）書籍類を、個人的なメモも兼ねて上げておこうと思います。


# こんな本を読みました＆読みかけです。

## プロダクトマネジメント ―ビルドトラップを避け顧客に価値を届ける
Melissa Perri  (著), 吉羽 龍太郎 (翻訳)

https://www.amazon.co.jp/gp/product/4873119251

- アウトプットよりもアウトカム
- 「何を作るか」ではなく「どんな価値を届けるか」
- 当たり前っちゃ当たり前なんですが、改めてこういう頭の使い方を徹底しないといけないなと

## プロダクトマネジメントのすべて 事業戦略・IT開発・UXデザイン・マーケティングからチーム・組織運営まで
及川 卓也  (著), 曽根原 春樹 (著), 小城 久美子 (著)

https://www.amazon.co.jp/gp/product/4798166391

- 分厚い本ですが読みやすいです。
- プロダクトマネージャーが考えなきゃいけないこと、こんなにあるのかという総覧
- まだ全部読み切れてないです。

## ユニコーン企業のひみつ ―Spotifyで学んだソフトウェアづくりと働き方
Jonathan Rasmusson (著), 島田 浩二  (翻訳), 角谷 信太郎  (翻訳)

https://www.amazon.co.jp/gp/product/4873119464

- これもプロジェクトよりプロダクトというお話
- ちゃんとスクラムやればいいよと言われてる気がしました
- 「ちゃんと」が難しい

## LeanとDevOpsの科学［Accelerate］ テクノロジーの戦略的活用が組織変革を加速する impress top gearシリーズ
Nicole Forsgren Ph.D. (著), Jez Humble (著), Gene Kim  (著), 武舎広幸 (著), 武舎るみ (著) 

https://www.amazon.co.jp/dp/4295004901/

- impress top gearシリーズは面白い本がそろっているのですが、これはDevOps Status Reportについての舞台裏や考察について
- DevOps実践した結果を定量的に表したものです
- なにか新しい知見というよりは、ちゃんとやると効果でるよというお話

## アジャイルな見積りと計画づくり ~価値あるソフトウェアを育てる概念と技法
Mike Cohn (著), マイク コーン  (著), 安井 力  (翻訳), 角谷 信太郎  (翻訳)

https://www.amazon.co.jp/gp/product/4839924023

- 見積もり難しいですよね。と思って買いました。
- まだ読み切れてないですが、かなり実践的です。
- Agileに開発したいなら、見積りも計画の考え方もそれに適したものがあるのだ。

## CTO・エンジニアリングマネージャー養成読本 (技術の泉シリーズ（NextPublishing）
野又 裕道 (著)

https://www.amazon.co.jp/gp/product/4844379356

- CTOやエンジニアリングマネージャーを目指してる人向けかな
- CTOやエンジニアリングマネージャーって実際どんな仕事する人なの？ということをざっくり説明してくれます
- 面白かったです

## アジャイルサムライ−達人開発者への道− 
Jonathan Rasmusson  (著), 西村 直人  (監訳), 角谷 信太郎  (監訳), 近藤 修平  (翻訳), 角掛 拓未 (翻訳)

https://www.amazon.co.jp/gp/product/4274068560

- 定番。古典。あらためて復習。
- 手元になかったので書い直しました。
- アジャイルやりたい人は、まずはコレをよみましょう。
- 結局、これに全部書いてあるという気もする

## SCRUM BOOT CAMP THE BOOK【増補改訂版】 スクラムチームではじめるアジャイル開発
西村 直人  (著), 永瀬 美穂  (著), 吉羽 龍太郎 (著)

https://www.amazon.co.jp/dp/4798163686

- 手元にあるのは旧版
- 昨年、増補改訂版が出たのでこちらを
- 「スクラム」について、あらためて復習

## SCRUMMASTER THE BOOK 優れたスクラムマスターになるための極意――メタスキル、学習、心理、リーダーシップ
Zuzana Sochova (著), 大友 聡之  (翻訳), 川口 恭伸 (翻訳), 細澤 あゆみ (翻訳), 松元 健 (翻訳), 山田 悦朗  (翻訳), 梶原 成親  (翻訳), 秋元 利春  (翻訳), 稲野 和秀  (翻訳), 中村 知成  (翻訳)

https://www.amazon.co.jp/gp/product/4798166855

- あらためて「スクラムマスター」の役割を復習

## アジャイルなチームをつくる ふりかえりガイドブック 始め方・ふりかえりの型・手法・マインドセット
森 一樹  (著)

https://www.amazon.co.jp/dp/4798168793

- 前の二冊とセットでどうぞ
- ふりかえり（レトロスペクティブ）が機能しないと、スクラムは機能しない

# おまけ

## 水平思考クイズゲーム ウミガメのスープ
古川洋平  (著)

https://www.amazon.co.jp/gp/product/434499230X

- カードゲームです。
- 情報を整理し、推論する力。それを端的な質問にまとめる力が問われます
- リモートでもできるので、お勧め。
- MT開発チームでも好評でした。
- たまにこういうゲームでワイワイやるの、メンバー間のコミュニケーションハードルさげるのにいいと思います
Kubebuilder を Docker から利用する

[Kubebuilder](https://github.com/kubernetes-sigs/kubebuilder) は Kubernetes のカスタムコントローラを作成するための支援ツールです。
カスタムコントローラを作成する上でデファクトとなりつつあるツールですが、M1 Mac(Apple Silicon) 向けのバイナリは現在リリースされていません。

https://github.com/kubernetes-sigs/kubebuilder/issues/1932

:::note info
2022/02/10 追記
Homebrew 経由で Apple Silicon 向けのバイナリをインストールできるようになったようです。
https://github.com/kubernetes-sigs/kubebuilder/issues/1932#issuecomment-985317316
https://formulae.brew.sh/formula/kubebuilder
:::

そこで M1 Mac でも Kubebuilder を利用するため、Docker イメージを作成します。
本記事で作成したイメージは Docker Hub にも公開しています。

https://hub.docker.com/repository/docker/hitsumabushi845/kubebuilder

## Dockerfile 

kubebuilder をコンテナ上で動かすため、golang のイメージをもとに kubebuilder をインストールしていきます。  
kubebuilder の利用に bash, make, gcc が必要なので、追加でインストールしておきます。

```dockerfile:Dockerfile
FROM golang:1.17.3-alpine
WORKDIR /workspace

RUN apk add --no-cache bash make gcc libc-dev

ENV KUBEBUILDER_VERSION v3.2.0
RUN wget -O /usr/local/bin/kubebuilder https://github.com/kubernetes-sigs/kubebuilder/releases/download/$KUBEBUILDER_VERSION/kubebuilder_$(go env GOOS)_$(go env GOARCH) && \
chmod +x /usr/local/bin/kubebuilder

ENTRYPOINT [ "kubebuilder" ]
```

Dockerfile を用意したら、イメージをビルドします。
Dockerfile を配置したディレクトリで以下コマンドを実行。

```shell-session
$ docker build -t hitsumabushi845/kubebuilder:3.2.0 .
```

## 利用方法例

引数で実行したいコマンドを叩きます。プロジェクトの初期化だと以下のようになります。
通常はディレクトリ名がプロジェクト名になるのですが、マウントしていることで正しいディレクトリ名が取れないので、`--project-name` でディレクトリ名を指定しています。

```shell-session:bash
$ mkdir -p sample-project
$ cd sample-project
$ docker run -it --rm \
-v $(pwd):/workspace \
hitsumabushi845/kubebuilder:3.2.0 \
init --domain hitsumabushi845.github.io --repo sample-project --project-name $(pwd | xargs basename)
```

プロジェクト作成後の make コマンドの実行はおおむねローカルでも行えます。
プロジェクト作成時に、`./bin` に `controller-gen` などのバイナリが格納されていますが、こちらはコンテナ向けのの（linux 向けの）バイナリになっているので、初めて実行する際は `rm -rf ./bin` などで削除してから実行します。
リモート時代の「今どこにいるの？」をpythonで

この記事は NTTテクノクロス Advent Calendar 2021の2日目の記事です。

こんにちは。安田と申します！
NTTテクノクロスでAI関連の新製品創出を担当しています。
(例えば、こういうの → [BizFront/SmartUI Decision Manager](https://www.ntt-tx.co.jp/products/bizfront/sui/dm/)）

さて、本記事では、pythonで「今どこにいるの？」をロギングする方法を見ていきたいと思います。コロナ禍以降になって、会社オフィスだけでなく、自宅も働く場所になってきました。出社と在宅が混在するようになると、「そういえば先週の火曜日って、どこで働いていたっけ？」って、良く分からなくなります。そこで、私なりの工夫として、肌身離さず持ち歩いているノートPCがその日はどこにあったのかをログに残すことにしています。

原理（どうして居場所がわかるの？）
---
ノートPCがそのときに掴んでいるWifiのSSIDとBSSIDの情報を取得できれば、どこにいるのかは分かると思います。

* SSID = Wifiのネットワークの名前
* BSSID = アクセスポイントの識別子（たいていはMacアドレス）

<img width="400" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271244/0dbeda80-b608-a81c-0832-3c11dfdabaec.png">

SSIDが同じだとしても、アクセスポイントが異なればBSSIDは異なるはずです。
そして、掴んでいるWifiのSSIDやBSSIDはnetshコマンドで調べることができます。
`netsh wlan show interfaces`


ソースコード
---
pythonで書きました。実際にはこれをpyinstallerでexe化してWindowsPCのスタートアップに入れて常に動かしてログを残しています。

``` main.py
import os
from subprocess import PIPE
import subprocess
import datetime


# Const
LOC_LOG_PATH = '../logs/log/'
LOC_LOG_FILENAME = 'loc.csv'
DIFF_JST_FROM_UTC = 9

# Opening Message
print('WIFIのSSID及びBSSIDの検出を開始します。')

loginName = os.getlogin()
prevSsidBssid = ''
nowSsidBssid = ''

while True:
    # SSID 及び BSSIDの取得
    proc = subprocess.run("netsh wlan show interfaces", shell=True, stdout=PIPE, stderr=PIPE, text=True)
    datalist = proc.stdout.split('\n')
    ssid = ''
    bssid = ''
    for data in datalist :
        if data.find('    SSID') == 0:
            ssid = data[data.find(':')+2:len(data)]
        elif data.find('    BSSID') == 0:
            bssid = data[data.find(':')+2:len(data)]
    if (ssid == '') or (bssid == ''):
        ssid_bssid = 'no wifi'
    else:
        ssid_bssid = ssid + '/'+bssid

    now = datetime.datetime.utcnow() + datetime.timedelta(hours=DIFF_JST_FROM_UTC)
    nowDate = now.strftime('%Y%m%d')
    nowTimestamp = now.strftime('%Y/%m/%d %H:%M:%S')    

    nowSsidBssid = ssid_bssid
    if (nowSsidBssid != prevSsidBssid):
        line = loginName\
                 + ', ' + nowTimestamp + ', ' + nowSsidBssid
        fileObject = open(LOC_LOG_PATH+str(nowDate)+LOC_LOG_FILENAME, 'a', encoding = 'shift_jis') # そのままエクセルで分析できるようにsjis
        fileObject.write(line + '\n')
        fileObject.close()
        print(line)
    prevSsidBssid = nowSsidBssid
```

おわりに
---
pythonって、色々できて面白いですよね。
さて、NTTテクノクロス Advent Calendar 2021 の明日（3日目）の記事は、[【AWS】利用料金の詳細通知＆自動化](https://qiita.com/inoue-mn/items/d28a2bb6091bbc7bbec5)のお話です。AWSを使っているエンジニアにとっては、利用料金って、かなり気になるテーマだと思います。こちらも引き続きお楽しみください！
githubの既存リポジトリからローカルリポジトリを設定する手順

# 前提
すでに動いているプロジェクトがあり、githubを利用している中で
ローカルをvirtual boxからDockerに移行する時に
githubからローカルリポジトリを作成する手順をまとめます。

# 作業手順
## ディレクトリ作成
任意のディレクトリを作成します。場所は好きなところに設置できます。

## gitリポジトリに設定
作成したディレクトリをgitリポジトリにします。

```git.sh
$ git init
```

成功すると.gitというディレクトリが作成されていると思います。
以下のコマンドで確かめます。

```gitstatus.sh
$git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
```

上記のように表示されればgitリポジトリとして設定が完了しています。

## リモートリポジトリを設置
リモートリポジトリを設定します。

```gitremoteadd.sh
$ git remote add origin git@github.com:username/example.git
```
※usernam/example.gitの部分はgithubのリポジトリ画面から
右上にある緑のcodeというボタンから取得してください。
リモートリポジトリが設定されたかは以下のコマンドで確認できます。

```remote.sh
$ git remote -v
origin  git@github.com:username/example.git (fetch)
origin  git@github.com:username/example.git (push)
```

これでリモートリポジトリが設定できました。

## ファイルをダウンロード
以下のコマンドを実行しファイルをダウンロードしリモートと同期します。

```gitpull.sh
$ git pull origin master
```

現在ではorigin mainとすることがデフォルトなので
適宜調整してコマンドを実行してみてください。
実行後ファイルがダウンロードされていて
以下のコマンドでブランチ、ログが表示されれば成功です。

```logbranch.sh
$ git log
$ git branch
```

# ブランチを作成
当方のプロジェクトではgithub-flowを採用していたので
featureブランチを切りました。

```feature.sh
$ git checkout -b feature
$ git branch
* feature
  master
```

# テストコミットをプッシュしてみる
テスト的にからファイルを作成してプッシュしてみます。

```test.sh
$ touch test.txt
$ git add .
$ git commit -m "Test commit"
$ git push origin feature
```

これでプッシュが成功すれば新しいローカルリポジトリの設定は完了です。

# なぜDockerなのか？
最後に余談ですがなぜDockerなのか？の理由を書いてみます。
~~M1 MacBookでvirtual boxが使えない。~~
・↑2022年末ごろにM1でも対応されたとのことで現在は使えるようです。（自分では動かしたことないため２次情報）
自分がM1買ってから2年弱の空白があったと記憶しております。
・プログラム言語、DB、CMSのバージョン切り替えがプロジェクトごとに簡単にできる。
・立ち上がりが早く消費リソースも少ない
・公式のコンテナがあればセッティングのコストを減らせる（PHPインストールなど不要でそのまま動かせる）
・日本のWEB業界で広く使われている。
これらの理由からDocker移行をしています。
~~とはいえ自分の場合はM1で使えれば粘っていたかもという感覚でした。~~
今改めて両方使った経験からDockerの方が運用コストが低いという印象があります。
ただDocker特有の学習コストもあるので慣れればという前提があることを付け加えておきます。
bundle installで失敗する

# 問題
- Rails Tutorial (5.1) 第1章 1.3.1
- `bundle install` しようとすると以下のようなエラーが出る

```
Fetching gem metadata from https://rubygems.org/............
You have requested:
  spring = 2.0.2

The bundle currently has spring locked at 2.1.1.
Try running `bundle update spring`

If you are updating multiple gems in your Gemfile at once,
try passing them all to `bundle update`
```

- 書いてあるとおりに `bundle update spring` をしてもまたエラー

```
Fetching gem metadata from https://rubygems.org/............
Resolving dependencies...
Bundler could not find compatible versions for gem "activesupport":
  In snapshot (Gemfile.lock):
    activesupport (= 5.1.7)

  In Gemfile:
    rails (= 5.1.6) was resolved to 5.1.6, which depends on
      activesupport (= 5.1.6)

    coffee-rails (= 4.2.2) was resolved to 4.2.2, which depends on
      railties (>= 4.0.0) was resolved to 5.1.7, which depends on
        activesupport (= 5.1.7)

Running `bundle update` will rebuild your snapshot from scratch, using only
the gems in your Gemfile, which may resolve the conflict.
```

- さらに `bundle update` してもエラー
  - この手順で直る場合もあるみたい

```
Bundler could not find compatible versions for gem "actionpack":
  In snapshot (Gemfile.lock):
    actionpack (>= 5.1.7)

  In Gemfile:
    rails (= 5.1.6) was resolved to 5.1.6, which depends on
      actionpack (= 5.1.6)

Running `bundle update` will rebuild your snapshot from scratch, using only
the gems in your Gemfile, which may resolve the conflict.
```

# 原因
- おそらくプロジェクト作成時にインストールしたGemよりも前のバージョンをインストールしようとしたのが原因
- そのプロジェクト作成時の情報が `Gemfile.lock` に保存されていて、依存関係の影響でうまくいってないのかも

# 解決法
- `Gemfile.lock` を削除して、`bundle install` を行う

```bash
$ rm Gemfile.lock
$ bundle install
```

# 対策
- 自分でGemfileを編集するときは、[RubyGems.org](https://rubygems.org)でGemを検索し、詳細ページの「GEMFILE」をそのままコピーする

# 参考
- [Ruby on Railsでbundle installでエラーが出た時のシンプルな解決方法 | 独学プログラマー🚀](https://code-schools.com/ror-bundleerror/)
- [【初心者向け】bundler、Gemfile、Gemfile.lockの関係性について図でまとめてみた - Qiita](https://qiita.com/nishina555/items/1b343d368c5ecec6aecf)
- [Gemfile.lock にはインストールされている gem のバージョンが書かれている，わけじゃない - Qiita](https://qiita.com/scivola/items/1db3cfbbd96456bd71ab)
rbenvでglobalを使ってもバージョンが切り替わらない

# 原因
- ホームディレクトリに `.ruby-version` ファイルがあるため
- ホームディレクトリで `rbenv local` コマンドを使ったのが原因
- おそらくglobalよりもlocalが優先され、ホームディレクトリでlocalが設定されているので強制的に常にlocalが指定されている状況になっていた

# 解決法
- ホームディレクトリの `.ruby-version` フォルダを削除し、再びglobalで再設定する

```zsh
$ cat ~/.ruby-version
$ rm ~/.ruby-version
$ rbenv global <バージョン>
```

# 参考
- [【Ruby】rbenv global してもバージョンが変らない｜鹿せんべいとエンジニア](https://shikasen-engineer.com/rbenv_global/)
- [[初期設定]なぜ「.ruby-version」を作成するのか？ - Qiita](https://qiita.com/shimadama/items/74033b932800bb61b3f3)
【初心者向け】Railsでのタスク定期実行方法

###■環境
・Windows10(64bit)
・Ruby 2.7.4
・Rails 5.2.6
・clockwork 2.0.4
・本番環境 Heroku
###■Railsでのタスク定期実行方法（開発環境）
####状況
Railsアプリケーション上でタスクを定期実行したい。
そして、Windows環境ではgem「whenever」は使用できないため、gem「clockwork」をインストールし目的を達成する。
####作業内容
１）gem「clockwork」をインストール

```ruby:Gemfile
gem 'clockwork'
```

```ruby:ターミナル
bundle install
```

２）タスクファイルを作成
「config\clock.rb」のように、任意の階層・ファイルを作成する。

３）タスクファイルの内容を記載

```ruby:config\clock.rb
require 'clockwork'

require File.expand_path('../boot', __FILE__)
require File.expand_path('../environment', __FILE__)

module Clockwork
  handler do |job|
  # 実行したい処理を記載
  end
  # 実行したいタイミングを指定。以下ならば、毎日・00:15（24時間表記）が来たときにのみ実行。
  every(1.day, 'midnight.job', :at => '00:15')
end
```

https://blog.piyo.tech/posts/2014-02-17-222721/

４）タスクを実行

```ruby:ターミナル
# ４－１）該当アプリケーションの階層に移動
cd 【該当アプリケーションのルートディレクトリパス】
# ４－２）clockworkコマンドを実行
clockwork config/clock.rb
```

frequent.job・less.frequent.job・hourly.jobの場合は以下の挙動になる。
　コマンド実行→直後にタスクを実行→待機→指定したタイミングでタスクを自動実行→待機（以降繰り返し）
midnight.jobの場合は以下の挙動になる。
　コマンド実行→待機→指定したタイミングでタスクを自動実行→待機（以降繰り返し）
###■Railsでのタスク定期実行方法（本番環境）
####状況
本番環境としてHerokuを利用するが、Herokuにはプロセスの合計稼働時間で課金される・アプリケーションが毎日自動再起動されるなどの仕様がある。

https://www.ownway.info/Ruby/heroku/helloclockwork

https://www.ownway.info/Ruby/heroku/clockwork/long_period

そのため、アドオン「Heroku Scheduler」を使用するとよい。
####作業内容
以下を参考に設定

https://qiita.com/Hijiri-K/items/d436d10d0e1ba6c573c0
テーブル更新時エラー　未完成

コンソールアプリケーション：社員情報管理アプリ

![Something went wrong]()




```DBController.java

//更新機能
	public static void Javadoc_update(String empId ,String empName_up, String gender_up, String birthday_up,  String deptId_up)
		throws ClassNotFoundException, SQLException {
			Connection connection = null;
			PreparedStatement preparedStatement = null;


			try {

				//DBに接続
				connection = DBManager.getConnection();

				preparedStatement = connection.prepareStatement(ConstantSQL.SQL_UPDATE1);

				preparedStatement.setString(1, empName_up);
				preparedStatement.setString(2, gender_up);
				preparedStatement.setString(3, birthday_up);
				preparedStatement.setString(4, deptId_up);
				preparedStatement.setString(5, empId);

                //SQLの実行
				preparedStatement.executeUpdate();

				System.out.println("社員情報を更新しました");

			} finally {
				DBManager.close(preparedStatement);
				DBManager.close(connection);

			}

```


```ConstantSQL.java

public class ConstantSQL {

//全てCASE文で記述した場合
public static String SQL_UPDATE1 = "UPDATE employee e SET \r\n"
			+ "e.emp_name = (CASE WHEN e.emp_name IS NULL THEN e.emp_name WHEN e.emp_name IS NOT NULL THEN ? END),\r\n"
			+ "e.gender = (CASE WHEN e.gender IS NULL THEN e.gender WHEN e.gender IS NOT NULL THEN ? END),\r\n"
			+ "e.birthday = (CASE WHEN e.birthday IS NULL THEN e.birthday WHEN e.birthday IS NOT NULL THEN TO_DATE(?, 'YYYY-MM-DD') END),\r\n"
			+ "dept_id = (CASE WHEN dept_id IS NULL THEN dept_id WHEN dept_id IS NOT NULL THEN ? END)\r\n"
			+ "WHERE emp_id = ?";

//emp_nameのみCASE文で記述した場合
public static String SQL_UPDATE1 = "UPDATE employee e SET \r\n"
			+ "e.emp_name = (CASE WHEN e.emp_name IS NULL THEN e.emp_name WHEN e.emp_name IS NOT NULL THEN ? END),\r\n"
			+ "e.gender = ?, \r\n"
			+ "e.birthday = ?, \r\n"
			+ "dept_id = ?\r\n"
			+ "WHERE emp_id = ?";
			



}

```
##CASE文の説明

```
--CASEで条件をわけてSELECTする
SELECT 
 CASE 
  WHEN 条件1 THEN 条件1の結果
  WHEN 条件2 THEN 条件2の結果
  ELSE 条件1,2以外の結果
 END 
FROM table1;

```


##全てCASE文で入力したとき


エラー文
```java.sql.SQLSyntaxErrorException: ORA-00932:
 データ型が一致しません: NUMBERが予想されましたがCHARです。
```
値を入力して更新しても入力しないで更新しても上記のエラーになる。




##emp_nameのみCASE文で記述した場合

エラー文
```java.sql.SQLException: ORA-01407: 
("CONSOLE_CRUD_USER"."EMPLOYEE"."EMP_NAME")をNULLには更新できません。
```
値を入力しないで更新しないと上記のエラーになる。
ただしemp_nameに値を入れて更新するとエラーは発生せず更新できる。

##別のパターン
同じようにbirthdayのみ、genderのみ、dept_idのみCASE文で記述した場合

エラー文
```java.sql.SQLSyntaxErrorException: ORA-00932:
 データ型が一致しません: NUMBERが予想されましたがCHARです。
```
いずれの場合も値を入力しないと上記のエラーになる。
または値を入力した場合にも同様のエラーになる。




####参考記事
https://rennnosukesann.hatenablog.com/entry/2018/03/02/215120
Pandas: keys, items, iteritems, iterrows, itertuples の違い。


お恥ずかしい話ですが、毎回忘れるのでメモします。
Row を列挙したい時は itertuples() を使うと良いです。iterrows() は型情報を失います。


```python
import pandas as pd

df = pd.DataFrame({'species': ['bear', 'bear', 'marsupial'],
                  'population': [1864, 22000, 80000]},
                  index=['panda', 'polar', 'koala'])

df
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>species</th>
      <th>population</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>panda</th>
      <td>bear</td>
      <td>1864</td>
    </tr>
    <tr>
      <th>polar</th>
      <td>bear</td>
      <td>22000</td>
    </tr>
    <tr>
      <th>koala</th>
      <td>marsupial</td>
      <td>80000</td>
    </tr>
  </tbody>
</table>
</div>



## keys

DataFrame をそのままイテレータとして使ったり、keys() を使うと column 名を列挙する。


```python
for items in df:
    print(items)
```

    species
    population



```python
for items in df.keys():
    print(items)
```

    species
    population


## items, iteritems

items と iteritems は同じ。(column 名, column 値の Series) の組 を列挙する。


```python
for name, items in df.iteritems():
    print("\nname: " + name)
    print(items)
```

    
    name: species
    panda         bear
    polar         bear
    koala    marsupial
    Name: species, dtype: object
    
    name: population
    panda     1864
    polar    22000
    koala    80000
    Name: population, dtype: int64


## iterrows
iterrows は (row 名, row 値の Series) の組を列挙する。型情報は失われる。


```python
for name, items in df.iterrows():
    print("\nname: " + name)
    print(items)
```

    
    name: panda
    species       bear
    population    1864
    Name: panda, dtype: object
    
    name: polar
    species        bear
    population    22000
    Name: polar, dtype: object
    
    name: koala
    species       marsupial
    population        80000
    Name: koala, dtype: object


## itertuples

itertuples は row 値の組を列挙する。型情報は残る。


```python
for items in df.itertuples():
    print(items)
```

    Pandas(Index='panda', species='bear', population=1864)
    Pandas(Index='polar', species='bear', population=22000)
    Pandas(Index='koala', species='marsupial', population=80000)


## 参考

* https://pandas.pydata.org/docs/user_guide/basics.html#iteration
M5StickC内臓RTCをNTPで時間合わせして表示

# 1.はじめに
M5StickC内臓RTCをNTPで時間合わせして表示する方法の覚書

UIFlowはVer.1.8.7
NTPで時刻を取得して、"YYYY-MM-DD"と"HH: mm:SS"として表示する方法の覚書

# 2.UIFlowコード

![NTPtoRTC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/1aec5143-8604-8e4c-622b-2d0a288c5c5b.png)
NTPで時間を取得して、RTCに設定後に時刻表示。
NTPにある日付と時刻の表示機能がRTCにはついていないため、「コードを実行」でそれぞれコマンド実行。


日付表示部分のコード

```python
label0.setText(str(rtc.now()[0]) +"-"+ str(rtc.now()[1])+"-"+str(rtc.now()[2]))
```

時間表示部分のコード

```python
label1.setText(str(rtc.now()[3]) +":"+ str(rtc.now()[4])+":"+str(rtc.now()[5]))
```
PHPの正規表現を具体例を見ながら紐解いてみた


業務で正規表現に触れる機会があったのですがあまり理解していなかったため、備忘も兼ねて改めて整理してみました。

本記事では正規表現の記法を詳述するものではなく、実際に使用される機会の多いパターンを紐解いていくことで、概要を把握することを目的とします。

より詳しい内容は各種リファレンス等を参照ください。また今回はPHPでの記法になります。

# そもそも正規表現って何？

ネット上のいくつかの記事を参考にしたところ、共通して抽出できる言葉は以下のようなものでした。

__『正規表現とは、いくつかの文字列を一つの形式で表現するための表現方法』__

文面上では分かりづらいので具体例で考えてみようと思います。

例えば、果物を表すこれらの文字列を一つの形式で表現してみるとどのようなものになるでしょうか？

```
apple
pineapple
melon
strawberry
orange
```

上記５つの文字列を正規表現で表記すると以下になります。

```
//果物を示す文字列を正規表現で表記
[a-z]+
```

以下で説明していきます。

まず[a-z]は文字クラスと呼ばれるもので、角括弧 [ と ] 内に囲まれたいずれかの一文字にマッチします。その次に”+”は量子定止と呼ばれるもので、ある文字が1回以上の繰り返していることを示します。

したがってまとめると
[a-z]　→　“a” ~ “z”の文字が
 + 　　  →　1回以上繰り返すものにマッチする
文字列という形になります。

結果的に上記５つの果物の文字列を単一で表現できるという形になります。

# 実際によく使用される正規表現を紐解いてみる
それでは実際に正規表現の具体例を見ていきます。
今回は正規表現の使い方の例を確認することが目的であるため、当該正規表現自体の脆弱性（Regular expression Denial of Service）等はスコープ外としております。

:::note warn
実際に使用される場合は、機能要件やセキュリティ等を鑑みる必要がありますのでご注意ください。
:::

##　郵便番号
```
//郵便番号の正規表現
/^[0-9]{3}-[0-9]{4}$/
```
| 正規表現 | 名称 | 役割 |
|:-----------|:-----------|:------------|
|/../|デリミタ|この中に正規表現のパターンを記述|
|^|キャレット|文頭を示す|
|$|ドルマーク|文末を示す|
|[0-9]|大括弧内に数字|0-9までのいずれかの数値にマッチすることを示す|
|{n}|中括弧内に任意の数値|直前の文字の桁数を示す|

まとめると以下になります。

```
//正規表現の開始
/　 

// 文頭から0~9までの数字が3文字続く
^[0-9]{3} 　

//郵便番号を区切るハイフン
- 

// 0~9までの数字が3文字続く
[0-9]{3} 　

//正規表現の終了と文末を示す
$/ 
```

##メールアドレス
```
/^[a-zA-Z0-9]+[a-zA-Z0-9\._-]*@[a-zA-Z0-9_-]+[a-zA-Z0-9\._-]+$/
```

上記と重複する内容は割愛致します。
今回新しく出てきた内容のみをピックアップしてみます。

| 正規表現 | 名称 | 役割 |
|:-----------|:-----------|:------------|
|+|プラス|1回以上の繰り返し|
|＊|アスタリスク|0回以上の繰り返し|
|\|バックスラッシュ|直後のメタ文字をエスケープする。ここでは直後の’.’ピリオドをエスケープしています|

まとめると以下になります。

```
//正規表現の開始
/ 

//文頭から小文字・大文字の英数字のみが１回以上繰り返される
^[a-zA-Z0-9]+　

//@マークの直前では大文字・小文字の英数字と文字列”., _, -”が0回以上繰り返される
[a-zA-Z0-9\._-]*@ 

//上記の続きで@マーク直後から小文字・大文字の英数字のみが１回以上繰り返される
[a-zA-Z0-9]+　

//大文字・小文字の英数字と文字列”., _, -”が0回以上繰り返される
[a-zA-Z0-9\._-]+ 

//正規表現の終了と文末を示す
$/ 
```

# まとめ
今回はPHPでの正規表現についてざっくりまとめてみました。
上記は正規表現の記法のほんの一部でしかないので詳細は各種リファレンスを参照ください。
また各言語によって記法も異なるのでご注意ください。

## 参照サイト

http://okumocchi.jp/php/re.php

https://qiita.com/takana_335/items/7f8a5eb3b9edc13e246c

https://qiita.com/n_oshiumi/items/62f5d21c4837f76932ab

https://qiita.com/prograti/items/9b54cf82a08302a5d2c7

https://e-words.jp/w/%E3%83%87%E3%83%AA%E3%83%9F%E3%82%BF.html

https://www.javadrive.jp/regex-basic/meta/index9.html
[JavaSilver受験対策]　非検査例外と検査例外の違い　

この記事は、[シアトルコンサルティング株式会社 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/seattleconsulting "Advent Calendar 2021")の8日目の記事です。
こんにちは、シアトルコンサルティングの村田です。
## はじめに
Javaの例外クラスに関して非検査例外と検査例外の内容と違いを解説しており、下記の方を対象としています。

* 非検査例外と検査例外ってなに  
* Javaシルバーの勉強中で例外についての問題が分からない
<br/>

## 1. 例外は2種類に分けられる
&emsp;Javaには例外処理をしなくてもコンパイルエラーにならないクラスがあります。
これを**非検査例外**と呼び（コンパイラが検査しないから「非検査」）
try-catchやthrowsで例外ハンドリングをする必要がありません。
反対に例外ハンドリングが必要なクラスが**検査例外**です。
検査例外はハンドリングしなければコンパイルエラーになります。  
&emsp;例外クラスは大きくError、Exception、RuntimeExceptionに分けられ、順にエラー、検査例外、非検査例外を表します。
（補足：RuntimeExceptionはExceptionクラスのサブクラスです）  

## 2. 非検査例外について
&emsp;非検査例外(RuntimeException)には以下のようなものがあります。

* NullPointerException
* ArrayIndexOutOfBoundsException
* IllegalArgumentException ...etc  

&emsp;これらはわざわざ例外処理をする必要がない程度のエラーです。
nullチェック等は例外処理するまでもなくプログラムで回避できるでしょ？という理由だからです。

&emsp;例えば以下のサンプルコードでは、非検査例外であるRuntimeExceptionをthrowしているためコンパイルエラーにはなりません。
実装する際はこのうようにコンパイラがスルーしてしまうため、受け取る変数の中身や型を拾って対応しましょう。

```java
public class Sample {
	public static void main(String[] args) {
			sample();
	}

	private static void sample() {
			throw new RuntimeException();
	}
}
```


## 3. 検査例外について
&emsp;検査例外(Exception)には以下のようなものがあります。

* IOException
* SQLException
* InterruptedException ...etc　　

&emsp;これらはコンパイル時に検査を行うためハンドリングしなければなりません。
読み込むファイルが壊れていたり、DBが壊れているという事象はプログラムでは回避できません。
そこでコンパイラによりハンドリングを強制されています。
&emsp;以下のサンプルコードでは、検査例外であるExceptionをthrowしている箇所で「処理されない例外の型 Exception」と、コンパイルエラーになります。

```java
public class Sample {
	public static void main(String[] args) {
			sample();
	}
	
	private static void sample() {
			throw new Exception();
	}
}
```


## 4. コンパイルエラーの解消
コンパイルエラーを解消するには以下の2つの方法があります。
&emsp;**・throwsを用いる**
&emsp;**・try-catchで例外ハンドリングする**  
■throwsを用いる
&emsp;対象メソッドと呼び出し元の両方で、throwsを用いてスローする可能性を宣言します。

```java
public class Sample_1 {
	public static void main(String[] args) throws Exception{
			sample();
	}
	
	private static void sample() throws Exception{
			throw new Exception();
	}
}
```

■try-catchで例外ハンドリングする
 &emsp;対象メソッドでthrows宣言および呼び出し元でのtry-catchによるハンドリングをします。

```java
public class Sample_2 {
	public static void main(String[] args) {
		try {
			sample();
		} catch (Exception e) {
			System.out.println("error");
		}
	}
	
	private static void sample() throws Exception{
			throw new Exception();
	}
}
```

## さいごに
&emsp;Javaシルバー学習のお供として分からなかったことをまとめました。
選択肢を絞るための一助としていただければと思います。

### 参考
(1) 志賀澄人 徹底攻略Java SE 11 Silver 問題集[1Z0-815]対応 株式会社インプレス 2019
(2) 25際で独立したフリーランスエンジニアじゃけえのあれこれ
【Java】検査例外と非検査例外の違いを図でまとめてみた
https://freelance-jak.com/technology/java/1157/
WordPressが自分でルート証明書の一覧を持ってた話

# WordPressが自分でルート証明書の一覧を持ってた話
## 概要
2021/9/30でLet's Encryptが使ってたルート証明書が期限切れになった。
サーバへのデプロイ時にWP CLIを使ってプラグインをインストールしていたが証明書期限関連のエラーが発生してデプロイが失敗するようになったので、それで確認したこととかをつらつら書いていく。

## 結論
WordPressは[自前でルート証明書](https://github.com/WordPress/WordPress/blob/master/wp-includes/certificates/ca-bundle.crt)を管理していた。
WP CLIなどWordPressの機能に依存したものを使ってプラグインなどをダウンロードする場合にはこの証明書を内部でプログラム内で指定してダウンロードを行なっている。
GitHub上でこのファイルが更新されたのは10/4だが、9/22付近でマイナーバージョンアップを施した際にはこの変更は入っておらず、10/4以降にマイナーバージョンアップされたWordPressが公開はされなかったのでバンドルファイルだけダウンロードして差し替えを行った。
※ マイナーバージョンが更新されなかっただけで稼働しているものと同じバージョンを新しく落としたWordPressのバンドルファイルは更新されてたので単にバージョンアップするルールになってなかったっぽい。

## 経緯
1. デプロイ後に一部機能が動作していないのを発見
2. デプロイログ確認時にプラグインのダウンロード時にcurlが証明書エラーで落ちていることを確認
3. curlなのでシステムのルート証明書を更新
4. curlコマンドを直打ちした場合は成功するが依然デプロイ時のログが解消しない
5. WP CLIのプログラムをおってWordPress側が用意しているバンドルファイルを直接指定してダウンロードを実行していることを確認
6. WordPressが持つバンドルファイルを更新
7. デプロイ時のエラーログが解消したことを確認

## やったこと
### サーバで持ってるシステムの証明書を更新
yumでca-certificatesを入れていたため以下で更新できた。

```bash
$ sudo yum update ca-certificates
```

### WordPressのバンドルファイルの更新
一応上書き前にバックアップ取りたかったのでwgetで単純にダウンロード。

```bash
$ sudo wget https://raw.githubusercontent.com/WordPress/WordPress/master/wp-includes/certificates/ca-bundle.crt
```

## まとめ
滅多に無いことではあるが、WordPressを使ってる場合にルート証明書に変更が入る場合は注意が必要。
WordPress内部のRequestのクラスを使ったりしている場合にはWordPressが持つ証明書が使われることになる。
fluent-bit を Docker コンテナで起動して 他の Docker コンテナのログを ElasticSearch に送る

## 経緯

- Docker で動かしている バックエンドアプリのログを ElasticSearch + Kibana で閲覧したくなった (ElasticSearch + Kibana の構築手順はここでは述べない)
- ElasticSearch のログ収集といえば fluentd だが、fluentd より軽量らしい fluent-bit を採用してみた

## 対応

- [公式ドキュメント](https://docs.fluentbit.io/manual/pipeline/outputs/elasticsearch)を見て作成
- バックエンドアプリコンテナがあるサーバに fluent-bit の Docker コンテナを稼働させるようにする
- fluent-bit が待ち受け状態になったことを確認したら、ログを送信するバックエンドアプリの方にも fluent-bit にログを送る設定を仕込む

### 構成

![fluent-bit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199780/8956e1c0-01dc-0275-1240-d83a728d5673.png)


## fluent-bit の設定


- parser で json を指定すると、json で出力したアプリログを ElasticSearch に JSON オブジェクトとして登録してくれる
  - 逆に指定しないと String として登録されてしまう 
- ローカル環境で試験的に試したものなので、本番環境に採用するときは適宜変えてください



```text
/
├ docker-compose.yml
├ fluent-bit.conf
└ parsers.conf
```

### docker-compose.yml

```yaml
version: '3.7'
services:
  fluentd:
    image: fluent/fluent-bit:1.8.8-debug # docker exec で コンテナの中に入りたければデバッグバージョンが必要
    container_name: fluent-bit
    ports:
      - "24224:24224" # ポート固定を指定
    volumes: # テストのためボリュームマウント
      - type: bind
        source: "./fluent-bit.conf"
        target: "/fluent-bit/etc/fluent-bit.conf"
      - type: bind
        source: "./parser.conf"
        target: "/fluent-bit/etc/parser.conf"
# バックエンドアプリとネットワークを合わせる
    networks:
      - "my-network"

networks:
  my-network:
    external:
      name: my-network
```

### fluent-bit.conf

```config
[SERVICE]
    Flush 1
    Grace 30
    Log_Level debug
    Parsers_File /fluent-bit/etc/parsers.conf

[INPUT]
    Name forward
    Listen 0.0.0.0
    Port 24224

[FILTER]
    Name parser
    Match *
    Key_Name log
    Parser docker

[OUTPUT]
    Name es
    Host my.elasticsearch.server
    HTTP_User elastic
    HTTP_Passwd mypassword
    Port  443
    Type doc
    tls On
    Generate_ID On
    Logstash_Format On
    Logstash_Prefix my-backend
    Logstash_DateFormat %Y-%m-%d
    Include_Tag_Key On
```

### parsers.conf

```config
[PARSER]
  Name docker
  Format json
  Time_Key timestamp
  Time_Format %Y-%m-%dT%H:%M:%S.%L%Z
```

## バックエンドアプリの設定

- ロギングドライバーを fluent-bit に設定する
- 注意点
  - fluent-bit の待ち受け TCP ポートを固定にしているので、ECS や K8S に転用すると、ローリングアップデートが出来ない問題があり
  - ホスト名指定にしてやれば上手くいくと思われる

### docker コマンドで起動する場合

- log-driver オプション 及び log-opt オプションを付けて起動

```bash
docker container run \
  --log-driver=fluentd \
  --log-opt fluentd-address=localhost:24224 \
  --log-opt tag=docker.{{.Name}} \
   my-image
```

### docker-compose で起動する場合

- logging 項目に記載する

```yaml
version: "3.7"
services:
  my-api:
    container_name: my-api
    logging:
      driver: "fluentd"
      options:
        fluentd-address: "localhost:24224"
        tag: "docker.{{.Name}}"
    restart: always
    networks:
      - "my-network"

networks:
  my-network:
    external:
      name: my-network
```

Kibana で Index を登録し確認できれば OK
3行でRust

O'Reilly刊 [Programming Rust, 2nd Edition](https://www.amazon.co.jp/Programming-Rust-Systems-Development-English-ebook/dp/B0979PWD4Z/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=Programming+Rust&qid=1637747243&sr=8-1) を読んでいるところ。 冒頭の Chapter 2 "Tour of Rust" 。たった3行のRustコードで *ownership*、*borrowing*、*reference*といったRust独特の概念を例示している。


```
    for m in &numbers[1..] {
        d = gcd(d, *m);
    }
```

著者がこの3行を読み下した原文がこれ：

>When we iterate, we want to tell Rust that *ownership* of the vector should remain with `numbers`; we are merely *borrowing* its elements for the loop. The `&` operator in `&number[1..]` borrows a *reference* to the vector's elements from the second onward. The `for` loop iterates over the referenced elements, letting `m` borrow each element in succession. The `*` operator in `*m` dereferences `m`, yielding the value it refers to; this is the next u64 we want to pass to `gcd`. Finally, since numbers owns the vector, Rust automatically frees it when numbers goes out of scope at the end of `main`.

これをお経のように百遍唱えればRustがわかりそうな気がします。

超訳してみた。

>このコードの1行目はRustに対してこう言っています。このベクタの全要素を処理するあいだ、変数`numbers`がベクタの所有権(*ownership*)を手放すことなく持ち続ける、ベクタの要素をループの中で処理するにあたっては要素を所有するのではなく要素への参照を借用(*borrow*)するにとどめる、と。`&number[1..]`という式の先頭にある`&`が『借用』演算子です。`number[1..]`が意味するのはベクタの２番目から末尾までの各要素ですが、これに`&`を付けると各要素への参照を『借用』する、という意味になります。`for`ループがベクタの全要素を順番に処理しますが、このとき変数`m`はベクタ要素への参照を指しています。2行目にある`*m`という式の`*`は『参照はずし』演算子（dereference）です。`*m`が意味するのはu64型の数値であり、これを`gcd`関数に対して引数として渡します。ループが済んで`main` 関数が完了するとき変数`number`はスコープから外れます。ベクタの所有権を持っていた変数`number`がスコープから外れたとき、Rustはベクタが占めていたメモリを自動的に解放します。

<details>
  <summary>main.rsぜんぶ</summary><div>

```rust
use std::str::FromStr;
use std::env;

fn gcd(mut n: u64, mut m: u64) -> u64 {
    assert!(n != 0 && m != 0);
    while m != 0 {
        if m < n {
            let t = m;
            m = n;
            n = t;
        }
        m = m % n;
    }
    n
}

fn main() {
    let mut numbers = Vec::new();
    for arg in env::args().skip(1) {
        numbers.push(u64::from_str(&arg).expect("error parsing argument"));
    }
    if numbers.len() == 0 {
        eprintln!("Usage: gcd NUMBER ...");
        std::process::exit(1);
    }
    let mut d = numbers[0];

    for m in &numbers[1..] {
        d = gcd(d, *m);
    }
    
    println!("The greatest common divisor of {:?} is {}",
             numbers, d);
}
```
O'Reilly, Programming Rust, 2nd Edition, Chapter 2: A Tour of Rust, p14
</div>
</details>
Fake Time

# Overview
Fake Time for test. not best way.

# Detail
```golang

var now = Time.Now

// if you want to use specify time, you call it. then replace time to argument valuen.
// then, you receive function is for revert original time module. for finish test, recommend call by defer
func switchFakeTime(t time.Time) (revertFakeTime func()) {
	now = func() time.Time {
		return t
	}

	return func() {
		now = time.Now
	}
}


fmt.Println(now())

revertFunc := switchFakeTime.(Time.Now())

fmt.Println(now())
time.Sleep(10 * time.Second)
fmt.Println(now())

revertFunc()
fmt.Println(now())

```
C＃を使用してWordの脚注と文末脚注の内容を読み取る方法

##C＃を使用してWordの脚注と文末脚注の内容を読み取る方法

##背景

脚注と文末脚注は、Word文書の本文を補足説明のために追加した内容です。脚注は通常、ページの下部にあり、ドキュメントのコンテンツに注釈を付けるために使用できます。文末脚注は通常、ドキュメントの最後にあり、引用されたドキュメントを説明するために使用できます。この記事では、C＃を使用してWord文書の脚注と文末脚注の内容を読み取る方法を紹介します。

***Word文書のスクリーンショット：***
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/8bb0af01-a7f5-248d-c473-89c367b309b6.png)

##使用するコンポーネント：
***[Free Spire.Doc](https://www.e-iceblue.com/Download/download-word-for-net-free.html)***
次のコードを使用する前に、C＃アプリケーションを作成し、Spire.Doc.dllをプロジェクトに参照する必要があります。

##コード一覧

###脚注を読み取る（Footnote）
```
//documentのインスタンスを作成する
Document doc = new Document();
//Word文書をロードする
doc.LoadFromFile("sample.docx");
//Word文書内全ての脚注を取得する
List<Footnote> footNotes = doc.Footnotes;
//StringBuilderのインスタンスを作成する
StringBuilder sb = new StringBuilder();
//脚注の内容をStringBuilderインスタンスに追加する
foreach (Footnote footNote in footNotes)
{
    foreach (DocumentObject obj in footNote.TextBody.ChildObjects)
    {
        if (obj is Paragraph)
        {
            sb.AppendLine((obj as Paragraph).Text);
        }
    }
}
//txtファイルに書き込む
File.WriteAllText("脚注.txt", sb.ToString());
```
***読み取りをした結果は以下の通りです：***
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/9cdc2eca-e8a4-f09f-1b7b-f02f1066822a.png)


###文末脚注を読み取る（EndNotes）
```
//documentのインスタンスを作成する
Document doc = new Document();
//Word文書をロードする
doc.LoadFromFile("sample.docx");
//Word文書内全ての文末脚注を取得する
List<Footnote> endNotes = doc.Endnotes;
//StringBuilderのインスタンスを作成する
StringBuilder sb = new StringBuilder();
//文末脚注の内容をStringBuilderインスタンスに追加する
foreach (Footnote endNote in endNotes)
{
    foreach (DocumentObject obj in endNote.TextBody.ChildObjects)
    {
        if (obj is Paragraph)
        {
            sb.AppendLine((obj as Paragraph).Text);
        }
    }
}
//txtファイルに書き込む
File.WriteAllText("文末脚注.txt", sb.ToString());
```
***読み取りをした結果は以下の通りです：***
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/8201cc78-2a31-3865-275c-f9c56e846413.png)

以上は脚注について簡単な操作でした、最後まで読んでいただきありがとうございます。
HTMLで文章を横三等分にする

##文章を三等分にする方法
![スクリーンショット 2021-12-01 144811.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515025/bec52110-0403-074c-eb72-d7872506cc68.png)

```HTML:HTMLファイル
<div style="display: flex; gap: 20px;">

  <div style="width: calc(100% / 3);">
    <h1>
    タイトル1
    </h1>
    <P>
    テキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
    </P>
  </div>
  
  <div style="width: calc(100% / 3);">
    <h1>
    タイトル2
    </h1>
    <P>
    テキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
    </P>
  </div>

  <div style="width: calc(100% / 3);">
    <h1>
    タイトル3
    </h1>
    <P>
    テキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
    </P>
  </div>

</div>
```
禁断の速読術の習得方法！速読英単語のアプリを個人開発してリリースした話

#禁断の速読術の習得方法

速読のアプリというのは、大体高額のセミナーに参加したり、速読をするための訓練が必要な事がほとんどだと思います。
そんな中無料でアプリをリリースしたので、皆さんに使って貰いたいので、記事を書く事にしました。

まずリリースしたアプリはこちら

https://play.google.com/store/apps/details?id=com.english.sokudoku&hl=ja&gl=US


現在は、google playストアにしかリリースしていません。
androidユーザーが登録してくれたら、iOS版版も出そうと思っています。

##開発環境はMonacaです

Monacaとは、「ハイブリッドアプリ」を作成することができるWEBサービスです。ネット上にアプリの開発環境を用意してくれるので、面倒な環境構築は一切必要ありません。

また、サンプルのアプリもいくつか用意されているので、簡単にアプリ開発を体験することができます。

私はここの最小限のアプリケーションを作るから、JQueryとFont Awesomeをダウンロードして
www配下に設定してアプリケーションを作成しました。

ハイブリッドアプリとは「iOS」「Android」「WEB」のどのデバイスでも動作するWEBアプリのことです。「HTML5」「CSS」「JavaScript」の3つのWEBプログラミング言語を使ってアプリを作ります。

興味がある方は、Monacaおススメです。

https://ja.monaca.io/


##使い方

使い方は簡単で、再生ボタンを押したら、速読が始まります。
実際に操作している動画はこちら

https://www.youtube.com/watch?v=na8omFdWKYE

読み上げる間隔を変更する場合は、読み上げる間隔左ほど早くなりますのしたのバーを一番左にすると、
速読する速度が変わります。
速度を変更するには、バーを動かして、再生ボタンを押すことで、速度の調整が出来ます。

このバーがとても便利で、HTMLのタグ< input type="range" >
と入力するだけで、速度などの値を変更することが出来ます。

詳細な使い方は、下記のようになります。
下に使い方のリンクも張っているので、気になる方は要チェックです。

```html
<div>
  <input type="range" id="volume" name="volume"
         min="0" max="11">
  <label for="volume">Volume</label>
</div>
```

https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/range

##要望受け付けます

文字の色も変更出来ます。もっと色の種類が必要だという声があったら、追加しますので、こちらにコメントして下さい。
速読する文字の大きさも変更出来ます。
これは、文字の大きさのバーを右にする程大きくなります。
速読の再生をしている場合でも色の変更と文字の大きさの変更は出来ます。

色の種類は現在Black、Red、Blue、Greenの4種類があります。

##文字の大きさを変えるコードの説明

文字の大きさは最大100PXまで大きく出来ます。
コード的には、スライダーが変更される毎にmain_nowのIDの文字サイズを変更しています。

```html
<input type="range" id="text-slider" value="30" min="1" max="100" step="1" oninput="onTextSliderInput(this.value)">
<!-- 変更する文字の出力先 -->
<div id="main_now" class="main_now"></div>
```

```javascript
function onTextSliderInput(size) {
  textSize = size;
  document.getElementById("text-slider").value = textSize;
  document.getElementById("main_now").style.fontSize = textSize + "px";
}
```

##HTMLの参考例

一番簡単な文字のサイズを変えるコードはこちら
下のHTMLをコピーして、HTMLファイルにすると実際に文字の大きさを変える事が出来ます。

```html
<html>
<head>
</head>
<body>
<script>
function onTextSliderInput(size) {
  textSize = size;
  document.getElementById("text-slider").value = textSize;
  document.getElementById("main_now").style.fontSize = textSize + "px";
}
</script>
<input type="range" id="text-slider" value="30" min="1" max="100" step="1" oninput="onTextSliderInput(this.value)">
<!-- 変更する文字の出力先 -->
<div id="main_now" class="main_now">大きくするテキストの例</div>
</body>
</html>
```

使ってみて、こんな機能があったら良いなどの要望がありましたら、コメントしてくれると嬉しいです。
Androidユーザーは是非とも速読体験をして下さいね。
第二新卒 エンジニア面接 質問集

# はじめに
私は新卒未経験でエンジニアとして就職し、現在2年目です。
主に業務システムの開発や保守開発を行っています。
最近ゆるく転職活動をしており、その際の面接で聞かれた質問内容についてアウトプットしようと思います。

# 履歴
- 2021/12/01 初投稿
- 2021/12/15 感想、質問に対するコメントを追加

# 技術知識に関する質問
- MVCモデルとは
- DAOとは
- トランザクションとは
- CI/CDツールと、それを利用する利点とは
- Gitの利点とは
- 好きな言語とその理由は？<br>
    ⇒ その言語の特徴をきちんと把握しているかを見ているのではないかと思います。
- AWSで知っているサービスは？
- DBのテーブル設計の手順は？
- DBのデータ移行で気を付けることとは？<br>
    ⇒ やったことがなかったので、想像で答えていいよとのことでした。<br>
    　 今後携わりそうな業務に関するアンテナも張っておかないとなと感じました。
- IoTとは？身近なものにはどのようなものがある？

# 業務経験に関する質問
- 現在まで携わったプロジェクトの概要（システムの内容、プロジェクト規模、自身の担当を含めて）<br>
    ⇒ プロジェクトがどういう位置づけか理解し、盛り込むと好印象でした。
- 現在までで使用したことのある言語やフレームワークは？
- 詳細設計で気を付けていること
- 製造で気を付けていること
- テストケースを作る際に気を付けていること
- 保守開発時に心掛けていること
- 製造が完了した状態とは厳密にどんな状態？
- 分からないところがあった場合、どのように解決してきた？
- 他のチームと一緒に仕事をする際に気を付けていること
- リーダーとして納期に間に合わない場合どのような対応をする？
- タスクが複数ある場合、どのように優先順位をつける？
- 業務で失敗をしたことと、それをどう乗り越えた？
- 業務で難しかったことと、それをどう乗り越えた？
- 業務でリーダーシップを発揮した経験は？<br>
    ⇒ 研修でリーダーを務めたことがあると答えました。<br>
    　 すると、それに対して「どのようなフィードバックをもらったか？」とも聞かれました。
- 業務で新人教育や、新しい技術の教育を行った経験は？
- 自分やチームの業務クオリティーを上げるために取り組んでいることは？


# 基本的な質問
### 仕事に関する質問
- 志望動機
- 仕事で成し遂げたいことは？<br>
    ⇒ その企業で成し遂げられることを言うべきでしょう。<br>
    ⇒ 人生において仕事とは？といったニュアンスでもありました。
- 当社の事業で魅力を感じる部分は？<br>
    ⇒ 同業他社との違いを調査し、魅力として挙げるといいでしょう。
- 5年後、10年後のキャリアビジョンは？
- エンジニアになった理由は？<br>
    ⇒ 私自身未経験からエンジニアになったのでよく聞かれました。<br>
    ⇒ カジュアル面談の時から聞いてくる企業が多かったです。
- 現職に就いた理由は？
- 転職する理由は？<br>
    ⇒ カジュアル面談の時から聞いてくる企業が多かったです。
- 転職活動の軸は？<br>
    ⇒ カジュアル面談の時から聞いてくる企業が多かったです。
- 当社で活かせる能力や経験は？
- 当社の事業でやりたいことは？（今はないことでも可能）<br>
    ⇒ クリエイティビティと、事業内容への理解を見ているのかな？
- 長く当社で働きたいと考えているか？

### 人生経験に関する質問
- 今までの人生で困難だったことや挫折は？
- ボランティアをした経験と気を付けたことは？

### プライベートな質問
- プライベートでは技術面に関してどのような勉強をしている？
- プライベートで何か個人的に勉強している？（技術面以外で）
- 個人開発のアプリで工夫したところは？

### もしもシリーズ
**最終面接で聞かれました。このような質問をする方もいらっしゃるんだな～。**

- もし資金をもらえたらどのような事業を立ち上げる？その理由は？
- ドリーム企業（可能かどうかは分からないが、働いてみたい企業）などはある？その理由は？
- 生産性が高いチームや企業とはどんな環境を持っていると思う？
- どこかの企業のCEOになれるならどこ？

### その他
**この企業だけでしか聞かれないだろうなと思う内容のものです。
事業内容によってはこのようなことも聞かれると思うので、企業研究をしておくことが重要だと思います。**

- SDGsとは？その中で興味があるものは？
- リモートワークに対する考えは？
- ビジネスで英語を使うことの利点は？
- 英語学習の経歴は？

# 感想
第二新卒の場合、実務未経験者の方と同じレベルの知識に関する質問がある傾向が強いです。
さらに、実務で経験したことについて深堀りされる印象です。
企業研究は念には念を入れて行い、そこから予測される質問についてもさらに考えておけばよかったなぁと個人的に反省しました。

面接のフィードバックでは、

- 事業内容とのマッチ度
- 自身のキャリアを意識している姿勢
- 自身の弱みを知っている点
- 結論から話すことができる点
- 作業の背景を落とし込めている点

などについてお褒めの言葉をいただきました。

個人的には自身の経験の棚卸しを行い面接対策を十分に行った上で、面接本番では

- 分からないことは分からないと言う。
- やったことがないことはやったことがないと言う。
- 質問の意図が理解できなければちゃんと聞き返す。

ことを意識していました。自分にとってもBe Honestが一番だなと思います。
これから転職活動を行う同じような境遇の方のお力になれれば幸いです。
techpitのlaravel講座の手順通りにやっていたらTarget class [UserController] does not exist.が出た件

techpitのlaravel講座をやっていたら

![スクリーンショット (1622).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/1f81358b-12dd-7807-d556-b1b546718995.png)


とあった。
しかし、ユーザーコントローラーファイルはちゃんとあるし、クラスもある
講座通り進めていたが、誤字などがあると思ったので、今度は講座のコードを完全コピペで試してみた
![スクリーンショット (1622).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/1f81358b-12dd-7807-d556-b1b546718995.png)

はい、ダメでした
<h2>原因</h2>
私のlaravelのバージョンが８で、講座で使用しているlaravelのバージョンが６だった

laravel8とlaravel6では、ルーティングの仕様が変わって違うことが判明（正確には８から変更）

laravel7までのルーティング

```php:web.php
Route::group(['prefix' => 'users', 'middleware' => 'auth'], function () {
    Route::get('show/{id}', 'UserController@show')->name('users.show');
});
```
laravel8までのルーティング仕様に変更

```php:web.php
Route::group(['prefix' => 'users', 'middleware' => 'auth'], function () {
     Route::get('show/{id}', [UserController::class, 'show'])->name('users.show');
});
```
これで、UserControlerのクラスであるshowを参照しますという意味になる
しかし、これでも足りないみたいで以下の記述が必要になる

```php:web.php
use App\Http\Controllers\UserController;　//追記
Route::group(['prefix' => 'users', 'middleware' => 'auth'], function () {
     Route::get('show/{id}', [UserController::class, 'show'])->name('users.show');
});
```
これでユーザーコントローラーファイルを使いますよという意味になる。
これで、ルーティング通りにshow/{id}にアクセスすると

![スクリーンショット (1624).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/5d5e0924-8f34-f0d1-5f7b-b621c1e5ef78.png)

<h2>感想</h2>
laravelの仕様変更が原因とは思いもつかなかった
laravel8でlaravel7以前の教材や動画を学習している場合気を付けなければいけないと感じた。
WSL + UbuntsでWindows上にReact開発環境を作る

#目次
[1.はじめに](#1-はじめに)
[2.インストール](#2-インストール)
[3.anyenvが起動できない](#3-anyenvが起動できない)
[4.そしてsshでのクローンでハマる](#4-そしてsshでのクローンでハマる)
[5.おわりに](#5-おわりに)

#1. はじめに
Windowsで基幹システムしか作ってこなかったエンジニアがReact/Typescriptに挑戦する。
[前回の記事](https://qiita.com/saisuke3309/items/4c7f550d42609144a957)にて、「Web開発ならLinuxを使え」という結論に至りました。しかし2児の父がそんなMacを買ってもらえるわけもありません。
なので、WSLを使ってWindows上に作る形にしました。

#2. インストール
前回の記事で紹介しましたが、[今読んでいる書籍](https://oukayuka.booth.pm/items/2368045)にあった手順に従いインストールをします。

https://github.com/oukayuka/Riakuto-StartingReact-ja3.1/blob/master/extra/build-win-env.md

#3. anyenvが起動できない
上記リンク先の手順に従ってインストールをしていると、以下の箇所で詰まります。

```
anyenv install nodenv
```

実行してもanyenvにパスが通っておらず（gitからダウンロードしただけだから当然だな）、コマンドが失敗します。そこでanyenvの公式サイトの「Manual git checkout」の以降の箇所を参照しました。

https://github.com/anyenv/anyenv

**パスを通す**ために実行したコマンドは以下です。

```
echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.zshrc
```

書籍の手順ではパスを通すコマンドが足りなかったのでした。

#4. そしてsshでのクローンでハマる

さて、順調にセットアップを進めていったところ、VSCodeの拡張機能インストール確認の手順でハマりました。

* 適当なプロジェクトをローカルに用意する

```
git clone git@github.com:oukayuka/Riakuto-StartingReact-ja3.1.git
```

SSH経由でのGit Clone手順。そう、やったことがなかったのです。
ここの手順が一番わかりやすかったかしら。

https://blog.katsubemakito.net/git/github-ssh-keys

1. ローカル側LinuxでSSH公開鍵を作る
1. 作った公開鍵の中身（テキスト）をコピペ
1. GithubのsettingからSSH keysを登録する

#5. おわりに
Linuxも触ったことがあったのでパスとは思いましたが、やはり作法は公式に従ったほうが良いと思い、anyenvのサイトを参照しました。

なお、書籍ではzsh(MacOSでは標準なの？)を使っているらしいので、それに合わせていきます。**はい。従いますお姉さま。**（元bash使い）

改めてインストールしたものをまとめます。

Windows上

* dism.exeからWSL
* WSL2へアップグレード
* マイクロソフトストアからUbuntu
* マイクロソフトストアからWindows Terminal
* Visual Studio Code (もともとあった)
* VSCodeにRemote - WSL拡張機能

Ubuntu上

* anyenvからnodenv
* nodenvからNode.js (現在の最新17.1.0と14.4.0)
* 使うパッケージたち（yan, typescript, ts-node, typesync)　これはnotenv rootのdefault-packagesというファイルに記述する
* Github接続用のSSHキー生成
PostgreSQL 


ロール作成
create role [ロール名] with login password [パスワード]


```
create role postgres_dev with login password postgres_dev
```

管理者権限付与

grant postgres to [ロール名]

```
grant postgres to postgres_dev
```

ロールにスキーマを付与
grant usage on schema [スキーマ名] to [ロール名]

```
grant usage on schema tym to postgres_dev
```




なんかスキーマに権限付与

revoke create on schema [スキーマ名] from public;

```
revoke create on schema tym from public;
```

外部キーの取得

```
select *
from infomation_schema.table_constraints
where constraint_type = 'FOREIGN KEY'
```
Qiita Markdown記法

ソースのタグ

バッククォートを3っで上下を挟む

「Shift」+「@」でバッククォート
<span style="color:red">色</span>

→ ```
public class

→ ```


エスケープのやり方がわかりません(-_-)

```
public class
```


マークダウン(記法)
【Vue.js 入門】Vueの特徴

# Vue.jsの特徴
* 段階的に拡張できる。
    * プログレッシブ(1ページからnページまで段階的に作れる。)
* コンポーネント分割
    * メンテしやすい
* SPAが作れる
    * ユーザービリティ向上

# インストール(CDN)
[CDNリンク](https://jp.vuejs.org/v2/guide/installation.html#CDN)

ここでは2.6.11を指定してhead内に保存している。

Hello Vue!と表示されれば成功。

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        {{ message }}
      </div>

      <script>
        let app = new Vue({
            el: '#app',
            data(){
                return{
                    message:'Hello Vue!'
                }
            }
          })
      </script>
</body>
</html>
```

# API(elとdata)

* Vueをインスタンス化した時のelやdataなどのことをAPIをいう。
    * [API一覧](https://jp.vuejs.org/v2/api/)

```js

<div id="app"> //elで指定した仮想DOMの範囲
    {{ message }} //dataで指定したkeyをマスタッシュで囲む。
 </div>
 <script>
    let app = new Vue({
        el: '#app', //仮想DOMの範囲を指定する。
        data(){ //elで指定した仮想DOMの範囲でオブジェクト形式でデータをセットする。
            return{
                message:'Hello Vue!'
            }
        }
        })
  </script>
```

# 仮想DOM
* DOM(Dockument Object Model)
    * HTMLをプログラムから操作できる仕組み
    * DOMはツリー状の構造となっている。
    * ![スクリーンショット 2021-12-01 13.34.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/8eb59ed0-9cfb-cda4-2a11-9dba1e9358b3.png)


以下、検証ツールで確認することもできる。

``` js
 const html = document.querySelector('html')
 console.dir(html)
```


* 仮想DOM
    * 旧DOM（変更前）と新DOM(変更後)のDOMを比較し、変更があった差分だけを実際のDOMに反映する。
        * 処理が速くなるメリットがある。
 



# 参考
[【Vue.js2&Vue.js3対応】基礎から【Vuetify】を使った応用まで！ 超初心者から最短距離でレベルアップ](https://www.udemy.com/course/vuejs-basic/)
[vue.js公式リファレンス](https://jp.vuejs.org/v2/guide/index.html)
SQL初心者がサブクエリ使ってみた。

## きっかけ
業務で下記のようなテーブルがあって、欲しい値が取れず苦労したのですが
サブクエリを使用したら取得できたので記録。

## subjectテーブル

| id | subject |
|:-:|:-:|
| 1 | 国語 |
| 2 | 数学 |
| 3 | 英語 |
| 4 | 理科 |
| 5 | 社会 |

## teacherテーブル

| id | name |
| :-- | :-: |
| 1 | yamada |
| 2 | shimizu |
| 3 | sato |



## teacher_subjectテーブル

| id | teacher_id | subject_id |
|:-:|:-:|:-:|
| 1 | 1 | 1 |
| 2 | 1 | 3 |
| 3 | 2 | 1 |
| 4 | 3 | 2 |
| 5 | 3 | 4 |
| 6 | 3 | 3 |


## 国語と英語ができる先生を知りたいとき

```sql:試したこと1
select teacher.name
    from teacher_subject
        left join teacher on teacher.id = teacher_subject.teacher_id
        left join subject on subject.id = teacher_subject.subject_id
        where teacher_subject.subject_id = 1 and teacher_subject.subject_id = 3;　 //-①
```
→１件もヒットしない。
　原因はwhereの中。
　1レコード上にsubject_idが2つあることはありえないので1件もヒットしない。

```sql:試したこと2
select teacher.name
    from teacher_subject
        left join teacher on teacher.id = teacher_subject.teacher_id
        left join subject on subject.id = teacher_subject.subject_id
        join (select count(*) as cnt, teacher_id //-②
            from teacher_subject
            where subject_id in (1, 3)
            group by teacher_id) as rd on rd.cnt = 2 and rd.teacher_id = teacher.id group by teacher.name;
```

→無事山田さんを取得できた。

## 解説

試したこと1で失敗したけどやりたかったことは、teacher_subjectテーブルからsubject_id=1(国語)と、subject_id=3(英語)の両方があるteacher_idを取得し、teacherテーブルのnameを取得したかった。（①）

なので、それを実現するために追加したのが、試したこと2の5~9行目（②）。
teacher_subjectテーブルにsubject_id=1かsubject_id=3があるteacher_idを取得し、teacher_idでgroup byしカウントする。
（カウントしたものをcntに入れる）

subject_id=1とsubject_id=3の両方がないといけないので、カウントした数(cnt)が2となり、該当したteacher_idから名前を取得する。
ColaboratoryでRDKit (2021.12.1版)

※過去の記事はこちら
　→ColaboratoryでRDKit (2021.2.26版) - Qiita https://qiita.com/tonets/items/0d991dd16911a689e1ee
※ **書いてから検索して同じ内容の記事があることを見つけてしまいました** が、勿体ないのでそのまま残します。
　→RDKit　超簡単インストール - Qiita https://qiita.com/bono0/items/891fb8bde303e782c05d

Google ColaboratoryでRDKitを使うときのインストール方法。
数多の記事があるが、更新されてなくて動かなくなっていることも多いので、現時点版を書きます。

```
!pip install rdkit-pypi
```
以上！

いけたかどうかを確認。

```
from rdkit import Chem
from rdkit.Chem import AllChem, Descriptors
from rdkit.Chem.Draw import IPythonConsole
from IPython.display import display
from IPython.display import Image
```
```
m = Chem.MolFromSmiles("CC1=CNC2=CC=CC=C12")
display(m)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57626/e871f4e1-f2e9-424a-d8b0-5bc0e743334d.png)

無事Colabで化合物が表示されていれば成功です。よいRDKitライフを。
【SwiftUI】NavigationBarのカスタマイズ

自分が設定に少し手間取ったので、メモとして残します。色々と調べた結果をまとめ、汎用化コードを設計。
これさえあれば、ナビゲーションバーのデザインは完璧。

###関数の準備

```swift
func setupNavigationBar() {
    let appearance = UINavigationBarAppearance()
    appearance.configureWithOpaqueBackground()
    //    背景色
    appearance.backgroundColor = UIColor(red: 33/255, green: 73/255, blue: 125/255, alpha: 1)
    //    タイトル文字色
    appearance.titleTextAttributes = [.foregroundColor: UIColor.white]
    UINavigationBar.appearance().standardAppearance = appearance
    UINavigationBar.appearance().scrollEdgeAppearance = appearance
    UINavigationBar.appearance().compactAppearance = appearance
    //    遷移後の「<戻る」ボタンの色
    UINavigationBar.appearance().tintColor = .white
}
```


###あとはinit()の際に読み込む
```swift
    init(){
        setupNavigationBar()
    }
```

###補足
```swift
# インライン表示(ほぼ全てのアプリがインライン表示)
 .navigationBarTitleDisplayMode(.inline)
# ナビゲーションバーを一時的に消したいとき
 .navigationBarHidden(true)
```

#####あとはNavigationbarItemsでメニューを追加するだけ。