OmniAICreator/Qiita-1.07M huggingface dataset:
IBM Rhapsody評価版（無償）をダウンロードする（URLを更新しました）

#IBM Rhapsodyとは
[IBM Rhapsody](https://www.ibm.com/jp-ja/products/uml-tools)は、OMG Systems Modeling Language™ (OMG SysML) を使用して、迅速な要件分析とモデルベースの設計を可能にします。モデルは、実行およびシミュレーションによって検証することができ、システムエンジニアチームが複雑な機能を短時間で設計するのに役立ちます。

#概要
本記事ではWindows用Rhapsodyの評価版（無償）をダウンロードする手順を説明します。

#手順
##ダウンロードサイトへのアクセス
以下のサイトから評価版をダウンロードします。
https://www.ibm.com/products/systems-design-rhapsody
[Start your no-cost trial]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228422/2db11c10-b3ef-754f-5984-b67c67202672.png)

##利用目的の登録
必須項目を選択し[I confirm]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228422/1ec0a5e5-a891-75d6-39dd-63c3c6fa6ae8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228422/7bf0f3b9-2943-16b9-f018-bbe8f3b01455.png)

ダウンロード可能なファイル一覧が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228422/430f3029-6307-2c4f-19d1-5dbf39214375.png)

ここでは最新版の9.0.1.0を選択し、[Continue]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228422/eb1ce9d9-2fb2-452f-4759-bfec2858be5b.png)
##バージョンの選択
ダウンロード可能なファイル一覧が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228422/20a453db-8d54-751c-dc15-c1a154f719bb.png)

お使いのWindowsの種類に応じてRhapsodyの32 Bit版か64 Bit版を選択してください。また、評価ライセンスが必要となるため、Evaluation Keyも選択してください。ダウンロードの方法は2種類ありますが、ここでは[Download using Download Director]を選択します。[Download Now]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228422/1e057840-4934-934b-507c-a3ad65446958.png)
##IBM Download Directorを利用したダウンロード
IBM Download Director[^2]アプリが起動します。「IBM Download Directorを開く」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228422/2069b578-740b-4acc-7eeb-ce9d6ed1d9d7.png)

ダウンロード場所を入力し、[OK]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228422/198ebbd8-f77c-9ad4-4a02-cc30416bb511.png)

ダウンロードが開始されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228422/ce08972e-03ce-8702-d581-cabaf819adb5.png)

ダウンロードが完了しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228422/cb8c79a6-0706-868b-1113-ca0db358c529.png)

#次の記事
[IBM Rhapsody評価版（無償）をインストールする](https://qiita.com/daikan_murata/items/c5dc416c3912e36dae84)

[^1]: [IBMidを作成してみる。](https://qiita.com/Shumpei_Kubo/items/564126081dea547dd742)
[^2]: [Download Director - セットアップ・ガイド](https://www.ibm.com/support/fixcentral/dldirector/installation_ja.html)
.NET Core + Docker(Alpine)でZStandardを使う

# はじめに
.NET Core + Docker(Alpine)な環境で[ZStandard](https://facebook.github.io/zstd/)で圧縮したデータをAPIに投げる要件が出てきました。
この記事では、[ZstdNet](https://www.nuget.org/packages/ZstdNet/)を利用して[ZStandard](https://facebook.github.io/zstd/)で圧縮したデータをHTTPでリクスエトする方法について説明します。

# ZStandard(zstd)と.NET Core
[ZStandard](https://facebook.github.io/zstd/)はfacebookがオープンソース化したライブラリで、高い圧縮率を実現する高速圧縮アルゴリズムだそうです。[ZStandardのホームページ](https://facebook.github.io/zstd/)には、.NETで利用できるライブラリとして下記3つが紹介されています。

- https://github.com/skbkontur/ZstdNet
- https://github.com/bp74/Zstandard.Net
- https://github.com/ImpromptuNinjas/ZStd

今回はgithubで最もスターが多かった[ZstdNet](https://github.com/skbkontur/ZstdNet)を利用していきます。

# 圧縮とHTTPリクエスト

コード自体は[ZstdNetのgithub](https://github.com/skbkontur/ZstdNet)にあるサンプルコードを参考にとりあえず次のコードで圧縮しています。CompressionOptionsクラスのコンストラクタに対する引数は圧縮レベルで、1-19の範囲で指定することができます（デフォルトは3）。

``` cs
ReadOnlySpan<byte> Compress(string text)
{
    var options = new CompressionOptions(16);
    var bytes = Encoding.UTF8.GetBytes(text);
    using var compressor = new Compressor();
    return compressor.Wrap(bytes);
}
```

あとは圧縮したデータのcontent-typeをzstdにして送ってあげればよいです。

``` cs
var requestContent = new ByteArrayContent(Compress(json).ToArray());
requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
requestContent.Headers.Add("Content-Encoding", "zstd");

var response = await _httpClient.PostAsync(uri, requestContent);
```

# ZstdNetをDockerで動くように調整する。
Visual Studioが作ってくれるDockerfileでそのまま動かそうとすると、下記のようにlibzstdが見当たらないよという例外が発生してしまいます。

> zstd net Unable to load shared library 'libzstd' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: Error loading shared library liblibzstd: No such file or directory

ZstdNetはネイティブライブラリであるlibzstdのラッパーでしかないので、Windows以外の環境で実行する場合は個別にインストールする必要があります（Windows用のlibzstd.dllはnugetで一緒にインストールされます）。
Alpineの場合、[zstd-libs](https://pkgs.alpinelinux.org/package/edge/main/x86/zstd-libs)というパッケージがmainリポジトリで公開されているのでapk addしてあげます。

また、上記のパッケージを追加した場合、/usr/lib/ディレクトリに`libzstd.so.1`と`libzstd.so.1.4.5`の2つのファイルが配置されるのですが、ZstdNetは`libzstd.so`という名前でネイティブライブラリを探しに行くのでシンボリックリンクを作成して騙してあげます。

Dockerfileは次のようになります。

``` Dockerfile
FROM mcr.microsoft.com/dotnet/core/runtime:3.1-alpine AS base
RUN apk add --update --no-cache zstd-libs && \
    ln /usr/lib/libzstd.so.1 /usr/lib/libzstd.so
WORKDIR /app

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine AS build
WORKDIR /src
COPY ["ZstdLibSample/ZstdLibSample.csproj", "ZstdLibSample/"]
RUN dotnet restore "ZstdLibSample/ZstdLibSample.csproj"
COPY . .
WORKDIR "/src/ZstdLibSample"
RUN dotnet build "ZstdLibSample.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "ZstdLibSample.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ZstdLibSample.dll"]
```

通信電文を見た限りちゃんと圧縮されているようです。

# まとめ

- .NET CoreでZStandardを使って圧縮をしたい場合、ZstdNetを使うと簡単
- ZstdNetはネイティブライブラリを使うので、別途apkでインストールしてあげよう
- ZstdNetはネイティブライブラリを/usr/lib/libzstd.soで探しに行くのでシンボリックリンクでだましてあげよう
【Salesforce】Testという名前のApexクラスは作らない

コード修正してたら下記のエラーが。

```apex:apex.cls
Method does not exist or incorrect signature: void isRunningTest() from the type test
```

確認してみたところ以下のメソッドでエラーが出ていた。

> Test.isRunningTest()

あーでもない、こーでもないと試行錯誤していた結果。

Salesforceが用意しているTestクラスではなく、以前、挙動確認のために作成した**Test.cls**を参照し「isRunningTest()が無いっすよ」と言っていただけだった。

解決した瞬間「こんな凡ミスで・・・」とめっちゃ恥ずかしかった。

Testという名前のクラスは作成しないようにしましょう。
tmux: SSHの接続先ごとにターミナルの背景色を変更する

こちらの神記事まんまです。

> SSHの接続先ごとにターミナルの背景色を変更する
https://bacchi.me/linux/change-terminal-bgcolor/

```bash
function ssh() {
  # tmux起動時
  if [[ -n $(printenv TMUX) ]] ; then
      # 現在のペインIDを記録
      local pane_id=$(tmux display -p '#{pane_id}')
      # 接続先ホスト名に応じて背景色を切り替え
      if [[ `echo $1 | grep 'prd'` ]] ; then
          tmux select-pane -P 'bg=colour52,fg=white'
      elif [[ `echo $1 | grep 'stg'` ]] ; then
          tmux select-pane -P 'bg=colour25,fg=white'
      fi

      # 通常通りssh続行
      command ssh $@

      # デフォルトの背景色に戻す
      tmux select-pane -t $pane_id -P 'default'
  else
      command ssh $@
  fi
}
```

ダメサーバのtmuxが1.6で使えなかったのでそこらをサルベージしてtmux3.1aを発見。それでは動きました。

# ハマったところ
tmux経由だと .bashrcを読まない。 .bash_profile もなんだかうまく行かず困ってたけど解決したけどそれが朝3時の話で、起きた今、どうやったか忘れてしまった。つまりここの情報ゼロです。

おしまい
T検定と正規分布の関係性について

Rを用いて、

```
t.test
```
と入力するだけで、簡単に実施できるT検定。しかし、その前提条件について理解している人は少ないのではないでしょうか。

T検定の勉強をしていくと、必ず「正規分布とT検定の関係性」について悩むことがあると思います。
ネット上の記事を見ていると、「T検定を実施する際は標本の母集団の分布が正規分布でないといけない」という記事や、「T検定は頑健性があるから正規分布以外でも問題ない」という記事もあります。

どちらの主張が正しいのか分からなかったので、自分なりに調べてまとめて見ました。
なお、以下で登場するT検定はウェルチのT検定を意味しています。


#正規分布の必要性
「標本の母集団の分布が正規分布していないとT検定が使えない」という主張は、半分正しくて半分正しくないです。

小標本（T検定にかける2群それぞれのサンプル数が1桁など）では、確かに母集団の分布が正規分布している必要があります。

しかし、標本のサンプル数が30以上の場合、この限りではありません。なぜなら、中心極限定理により、サンプル数が30程度あれば、標本平均値の母集団の分布は正規分布になることが証明されているからです。

T検定において、正規分布している必要があるのは、**それぞれの標本の母集団の分布ではなく、それぞれの標本平均の「差」の母集団の分布です。**これはT検定を理解するうえで、とても重要なポイントです。

例えば、A群とB群があった場合、T検定を実施できる前提条件は、A群、B群の平均値の差の母集団の分布が正規分布していることです。A群、B群の母集団が正規分布している必要はありません。

ではなぜ、「標本の母集団の分布が正規分布していないとT検定が使えない」という主張が出てくるのでしょうか？

それは、**「標本平均の「差」の母集団の分布が正規分布である」**という前提条件を満たす方法が2通りあるからです。



###標本の母集団分布とT検定

パターン①
A群、B群の母集団分布が正規分布であることが分かっている場合
→母集団の分布が正規分布である場合、それぞれの標本の平均値の母集団の分布も正規分布であることが数学的に証明されている。（つまり、A群とB群の平均値の母集団分布が正規分布になる）
→標本A、Bの平均値の母集団の分布が正規分布の場合、その**平均値の差の母集団分布も正規分布になる**ことが数学的証明されている。

つまり、**「A群、B群の母集団分布が正規分布」の場合、「平均値の差の分布も正規分布になる」ことから、T検定の前提条件を満たし、T検定が利用できる。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/936505/a47c0233-3648-92ba-79ac-ed88f0d2492d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/936505/c61ce2c8-4332-c316-8a16-2ef3466d334d.png)


パターン②
A群、B群の母集団の分布系が分からないが、それぞれのサンプル数が30以上ある場合
→中心極限定理により、サンプル数が30以上ある場合、それぞれの群の平均値の母集団の分布は正規分布になる。
→標本A、Bの平均値の母集団の分布が正規分布の場合、その**平均値の差の分布も正規分布になる**ことが数学的証明されている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/936505/bec4e415-35c2-fba3-0a4d-5c5552e2c1fe.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/936505/e70ec054-c4e9-4f2c-4dbc-23ce7dedeac0.png)



つまり、**「A群、B群の母集団の分布系によらず各群でサンプル数が30以上ある」場合、「平均値の差の分布も正規分布になる」ことから、T検定の前提条件を満たし、T検定が利用できる。**


以上が、「標本の母集団の分布が正規分布していないとT検定が使えない」という主張が半分正しく半分間違っている理由です。T検定を実施したいそれぞれの群で、サンプル数が30以上ある場合、何も気にせずにT検定を実施しても良い、ということになりますね。

ただ、そうは言っても、標本の母集団の分布が正規分布である方が検出力が高いらしい（理由は勉強中）ので、対数変換やBox-Cox変換などで、正規分布に近似してからT検定を実施するのが良さそうです。


#まとめ

・小標本の場合
標本の母集団分布が正規分布であることが必要
正規分布以外の場合は、対数変換やboxcox変換を実施する

・標本サイズが30以上の場合
そのままT検定を利用してOK
ECサイトコーディングでよく使うcss

仕事でECサイトのフロントコーディングをさせていただくにあたって、度々目にするソースをメモ

# Masonry

- フッターでよく使うレイアウト
    - https://codepen.io/Mimuko/pen/poEwMJE
    - jsライブラリ：https://masonry.desandro.com/index.html

# 「…」で文章を省略
- https://codepen.io/Mimuko/pen/ExgXqyQ

# PCはテーブル、SPは縦積み商品カード
- https://codepen.io/Mimuko/pen/PoGGLzz
CakePHPのget/set/withなどのクラス別まとめ

CakePHP初学者がコーディングの時にget/set/withの使い方で迷ったのでクラス別にまとめました。

バージョン：
PHP7.4
CakePHP3.9

リクエストクラス
-
参考：
https://book.cakephp.org/3/ja/controllers/request-response.html


###getParam
ルーティングパラメーターなどを取得する

```
$controllerName = $this->request->getParam('controller');
```

###getQuery
クエリー文字列パラメーター
キーが存在しない場合nullが返る

```
// URL は /posts/index?page=1&sort=title
$page = $this->request->getQuery('page');
```


###getQueryParams
全てのクエリー文字列パラメーターにアクセスできる

```
$query = $this->request->getQueryParams();
```

ここのページも分かりやすかった
https://qiita.com/egcmrsk/items/5312e81a366c6a6a8209
getQueryParams()について下記のような記載があるけど公式のサンプルコードとの差が理解できず、、

```
// GET
$this->request = $this->request->withQueryParams([
    'year' => date('Y'),
    'month' => date('n')
]);
```



###getData
リクエストのボディーデータ、全てのPOSTデータはこれを使いアクセスする
キーが存在しなければnullを返す

```
// name 属性が 'MyModel[title]' の入力は次のようにアクセスします。
$title = $this->request->getData('MyModel.title');
```


レスポンスクラス
-


###withData

###getParsedBody









エンティティクラス
-
参考：
https://qiita.com/satthi/items/59b689df628a0fcc2ce0

###set
テーブルクラスでnewする時など、

###get
ビューで呼び出すときなど


###おまけ：アクセサーとミューテーター
参考：
https://hacknote.jp/archives/55024/

アクセサーとは、、
プロパティを取得する時に使用する

```
echo $book->name;
echo $book->get('name');
```

ミューテーターとは、、
プロパティを設定する時に使用する

```
$book->name = 'harry potter'; //HARRY POTTER
$book->set('name', 'Harry Potter'); //HARRY POTTER
```


テーブルクラス
-
参考：
https://book.cakephp.org/3/ja/orm/table-objects.html

###setTable
テーブルを指定、initialize()に記載するのはこちら

###getTable
実際に活用する時に使う、単体での処理としてはクエリの実行のためにテーブル名そのもの（string)を返す

※上記は昔のバージョンではtable()として存在して、メソッド内で引数の状態によって処理を分けていたようです。

###getRegistryAlias
テーブルインスタンスを作るためにレジストリーキーを取得する
モータルメソッド仕様では引数がnullならgetとして扱っていた


###setRegistryAlias
レジストリーキーをセットする
モータルメソッド仕様では引数がnullでない場合引数をセットしていた

おまけ：
インスタンスを取得するのはTableRegistry
canvasをiPhoneのsafe area内に収めてみた

##はじめに
最近のiPhoneにはいやーなsafe areaというのがありますね。
普通に作ってると、ホームバーがcanvasと重なりやがる。

くそーAppleめー、めんどくさいじゃ無いか。

いろいろ情報収集してると、padding-bottomにenv(safe-area-inset-bottom)を入れておけばいいらしい。ほうほう、そうなんですね。

ぶー、かなりダメだ。稀にしか動かないような。styleは詳しく無いんだよ。

でもなんとかなった。

##やり方
```html
    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
```
viewport-fit=coverを追加して

```html
<canvas style="position:absolute;
       left:env(safe-area-inset-left);
       top:0px;
       width:calc(100% - env(safe-area-inset-left) - env(safe-area-inset-right));
       height:calc(100% - env(safe-area-inset-bottom));">
</canvas>
```
これでsafe area内にcanvasがいい感じで収まる。縦横切り替えても、Safariのツールバー非表示にしてもOK。

ちなみにenv(safe-area-inset-bottom)の値はjsでは取れないらしい。
js（これはdartだけど）からいじる時はこんな感じでいけた。

```dart
canvas.style.height = "calc(100% - ${なんか数字}px - env(safe-area-inset-bottom))";

```
しかーし`calc(100% - env(safe-area-inset-left) - env(safe-area-inset-right))`とは・・・いまいちかなあ。

で、改良。こうなった。

```html
    <div
        style="visibility: visible;position:absolute;top:0px;left: 0px;right: 0px;bottom: 0px;margin-left: env(safe-area-inset-left);margin-right: env(safe-area-inset-right);margin-bottom: env(safe-area-inset-bottom);">
        <canvas id="stage"
        style="position: absolute;left: 0px;top: 0px;width: 100%;height: 100%;"></canvas>
    </div>
```
このdivのstyle、canvasだとうまくいかないんだよね。displayとかbox-sizingとかも試したけどダメ。
何がダメだったのかわからない。誰か教えて。

##終わりに
paddingじゃなくて、大きさを調整すればよかったんだけど、canvasはよくわからんね。

htmlはめんどくさい。
【初学者】AWS Elastic IPで課金が発生した話

#はじめに
私はプログラミングスクール生で、カリキュラム上AWSを使用したデプロイを行っていました。
無料枠内の使用だと思っていたら、請求書を見ると僅かながら課金が発生していて驚いたのでここに原因と対策を書き留めておきます。
Elastic IPは料金が発生する可能性があることは確かにカリキュラムには載っていたのでスクール側は何も悪くありません！私の勉強不足でした！
#Elastic IPとは
EIP（Elastic IP）は、EC2インスタンスにパブリックIPアドレスを紐付けることができるサービスです。
EC2インスタンスは再起動すると、パブリックIPアドレスが変わってしまいます。
EC2インスタンスとEIPを関連づけることで、同じパブリックIPアドレスを継続して利用することができます。
#結論
・使用していないElastic IP アドレスがあった。
・Elastic IP アドレスに関連付けられているインスタンスが停止中だった。
#行ったこと
まず料金明細をクリックし、料金の発生源を確認。
$0.005 per Elastic IP address not attached to a running instance per hour (prorated)
この時、どのインスタンスにも関連づけていないEIPを２つ発見。
これか！と思い、使用していないEIPを全て解放しました。
しかし課金は止まらない・・・でも額が減っている・・・。
原因は一つではなかったのか・・・。
公式サイトで解決方法を確認すると、
Elastic IP アドレスに関連付けられているインスタンスが実行中である。
との表記が・・・。使っている方が無料のパターンなのか！とここで気づき、本番環境の挙動を確認したら毎回停止にしていたインスタンスを実行中にし続けると課金は止まりました・・・。
#参考
https://aws.amazon.com/jp/premiumsupport/knowledge-center/elastic-ip-charges/
MoviePyを使ってPythonで動画編集をする

#前置き
この記事は[MoviePyの公式ドキュメント](https://zulko.github.io/moviepy/index.html)を簡単にまとめたものです。本格的にMoviePyを使いこなしたい人はおやつでもつまみながら**公式ドキュメント全体をじっくり読むことをおすすめします**。英語ですが、Google翻訳を使いつつ、難解な部分はDeepLを使用しながら読み進めば大丈夫なはずです。[Github](https://github.com/Zulko/moviepy)も読んでおくと良いかもしれません。この記事はとりあえず全体を理解したい、とにかく今すぐ使いたいという人向けです。誤り、情報の更新などがありましたら遠慮なくお教え下さい。

#MoviePyとは？
Pythonで動画編集ができるライブラリです。Pythonでは他にも動画編集を行う手段があります。画像編集ライブラリopenCVをつかった手法、ffmpegをコマンドラインで操作する手法などです。場合によってはこれらを検討するのもアリです。
YouTubeにMoviePyで[具体的にどのようなことができるのかのサンプル](https://www.youtube.com/watch?v=rIehsqqYFEM)があります。

#インストール
windwosの人は色々躓くと思いますのでWSLの利用を推奨します。（WSL最高）

```
pip install moviepy
```
WSLが使えない場合は下の参考に書かれた手順が必要かもしれません。
[参考](https://zulko.github.io/moviepy/install.html)

#基本
具体的な編集例を列挙する前に、基本をおさえとおくと混乱が少ないのでまとめます。

##クリップ
MoviePyではクリップという概念で編集をします。クリップには動画クリップ、音声クリップ、画像クリップ、テキストクリップなどがあります。それらを編集したり、つなぎ合わせることで編集をおこないます。

##座標
座標は左上を0として、右にX、下にYとなります。
![座標概念の図](https://zulko.github.io/moviepy/_images/videoWH.jpeg)
引用: https://zulko.github.io/moviepy/getting_started/compositing.html

##時間指定
時間指定の基本単位は秒で、様々な指定方法があります。

```python
t=15              # 15秒
t=15.12           # 小数点もいける
t=(3, 15.12)      # この場合3分15.12秒
t=(1, 3, 15.12)   # この場合1時間3分15.12秒
t=('1:03:15.12')  # このような指定もできる
```

#できること
##サンプル素材
サンプル素材として[NHKクリエイティブ・ライブラリー](https://www.nhk.or.jp/archives/creative/)から[猫の動画](https://www9.nhk.or.jp/das/movie/D0002160/D0002160514_00000_V_000.mp4)をダウンロードしました。数十秒程度の動画素材ならなんでもかまいません。ただし編集の効果がわかりやすいよう、カット等がされていない素材がいいと思います。これを`cat.mp4`として保存します。

##実行環境
Ubuntu20.24 (WSL)
Python 3.8.5


##複数の動画をつなげる
`cat.mp4`の0~2秒、4秒～5秒、10秒～11秒をつなげて一つにファイルにします。

```py
from moviepy.editor import *
clip1 = VideoFileClip("cat.mp4").subclip(0, 2)              # 動画の切り出し
clip2 = VideoFileClip("cat.mp4").subclip(4, 5)
clip3 = VideoFileClip("cat.mp4").subclip(10, 11)
final_clip = concatenate_videoclips([clip1, clip2, clip3])  # 動画の結合
final_clip.write_videofile("final_cat.mp4")                 # 動画の書き出し
```


##動画に効果を加える
###動画の反転
`<クリップ>.fx(<効果>)`でクリップに効果を与えることができます。
この場合左右上下反転された動画ができます。

```py
clip4 = VideoFileClip("cat.mp4")
clip5 = clip4.fx(vfx.mirror_x)  # x軸で動画を反転
clip6 = clip4.fx(vfx.mirror_y)  # y軸で動画を反転
```

###動画のりサイズ
`<クリップ>.fx(<効果>, オプション)`でクリップの効果にオプションを与えることができます。
この場合アスペクト比はそのままで、横が200pxの動画が書き出されます。

```py
clip7 = VideoFileClip("cat.mp4")
clip8 = clip7.fx(vfx.resize, width=200)
```

###動画の切り取り
これらの効果はつなげて書くことができます。
この場合横幅500pxで左上から200px * 200pxの範囲が切り出されます。

```py
clip9 = VideoFileClip("cat.mp4")
clip10 = (clip9.fx(vfx.resize, width=500)
               .fx(vfx.crop, x1=0, y1=0, x2=200, y2=200))
```

ほかにも本当にたくさんの色々なことができます。詳しくは[公式ドキュメント](https://zulko.github.io/moviepy/ref/videofx.html?highlight=vfx#)をご覧ください。

#MoviePyを作って作られたもの
[ここ](https://zulko.github.io/moviepy/gallery.html)にMoviePyを用いて作られた作品例があります。

今後他にも内容を追加していく予定です…
スプレッドシートからGitHubのIssueを作成する

この記事は移行しました！[最新の内容はこちら](https://naoqoo2.github.io/blog/%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88%E3%81%8B%E3%82%89GitHub%E3%81%AEIssue%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B/)をご覧ください😀


これは[SOUSEI Technology アドベントカレンダー2020](https://qiita.com/advent-calendar/2020/st) 24日目の記事です。
メリークリスマスイブ :santa:

## はじめに
スプレッドシートからIssueを作りたいこと、あるよねー！
ということでGASで。

## やり方

1. 行を選択する（複数行OK）
2. GAS→Issueを作成する
3. OK押す
![capture.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56789/471593ff-4581-96cb-48fa-17d06e40e957.gif)




## スクリプト

こちらをスプレッドシートのGASにコピペして `{$_〇〇}` 部分を書き換えてください。
アクセストークンは[公式ドキュメント](https://docs.github.com/ja/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token)を参考に作りましょう！

```js
function makeIssues() {

  // GitHubの情報
  var OWNER = "{$_GitHubのアカウント名}";
  var REPO = "{$_Issueを作成するリポジトリ名}";
  var ACCESS_TOKEN = "{$_アクセストークン}";
  
  // スプレッドシートの情報
  var title_column_no = 1;
  var description_column_no = 2;
  var issue_url_column_no = 3;
  
  // 選択しているセルの開始行番号を取得
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  var upper_left_cell = sheet.getActiveCell();
  var start_row = upper_left_cell.getRow();

  // 選択しているセルの行数を取得
  var range = SpreadsheetApp.getActiveRange();
  var rows = range.getNumRows();

  // 確認ダイアログ
  var message = '';
  var start_title = sheet.getRange(start_row, title_column_no).getValue();
  message += start_title;
  if (rows > 1) {
    message += ' など' + rows + '行';
  }
  var result = Browser.msgBox('Issueを作成します。よろしいですか？', message, Browser.Buttons.OK_CANCEL);

  if (result == 'cancel') {
    return;
  }

  // Issue作成
  for (var i = 0; i < rows; i++) {
    var row = start_row + i;
    var title = sheet.getRange(row, title_column_no).getValue();
    var description = sheet.getRange(row, description_column_no).getValue();

    var payload = {
      "title": title,
      "body": description,
    };

    var response_data = createIssue(payload);
    sheet.getRange(row, issue_url_column_no).setValue(response_data['html_url']);
  }

  function createIssue(payload) {
    var url = "https://api.github.com/repos/"+ OWNER + "/" + REPO + "/issues";
    
    var header = {
      "Authorization": "Basic " + Utilities.base64Encode(ACCESS_TOKEN),
      "Accept": "application/vnd.github.symmetra-preview+json",
      "Content-Type": "application/json",
    };
    
    var options = {
      "method" : "post",
      "payload" : JSON.stringify(payload),
      "headers" : header,
    };
    
    var response = UrlFetchApp.fetch(url, options);
    Logger.log(response);
    var response_data = JSON.parse(response.getContentText());
    return response_data;
  }
}

function onOpen() {
  // メニューバーにカスタムメニューを追加
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [
    {name : "Issueを作成する", functionName : "makeIssues"},
  ];
  spreadsheet.addMenu("GAS", entries);
}

```

## さいごに

- [スプレッドシートからTrelloのカードを作成](https://qiita.com/naoqoo2/items/956d3294e9da861c2975)
- [Trelloからスプレッドシートに転記](https://qiita.com/naoqoo2/items/87dad19771b370877f06)

もよければどうぞ😎
[Tips] React で highlight.js を適用する方法

# はじめに

[React](https://ja.reactjs.org/) に [highlight.js](https://highlightjs.org/) を組み込もうとしたのですが、若干躓いてしまったので対処法についてメモっておきます。

また、[React](https://www.npmjs.com/package/react) は既にプロジェクトにインストール済みと仮定します。

```bash
# 一応 React をインストールするためのコマンドは ↓
npm i --save react react-dom
```

# React に highlight.js を組み込む

まずは [highlight.js](https://www.npmjs.com/package/highlight.js?activeTab=readme) を NPM or Yarn でインストールします。

```bash
# NPM で highlight.js をインストールする
npm i --save highlight.js
yarn add highlight.js
```

その後、React ソースコードに highlight.js を組み込みます。
ソースコードの該当部分のみを載せると下記の感じになります。

```javascript
import Head from 'next/head'
import styles from '../styles/Home.module.css'

import React, { useState, useEffect } from 'react';

/**
highlight.js を import する
*/
import hljs from 'highlight.js/lib/core';

/**
シンタックスハイライトしたい言語のみ import として登録する
今回は html をハイライトしたかったので xml を import した

デザインは highlight.js/styles/~ を変更することで調整可能
https://highlightjs.org/ のトップページから各種デザインについては確認可能
(コード右下にある style の右側リンククリックで各種デザインのプレビューが可能)
*/
import xml from 'highlight.js/lib/languages/xml';
import 'highlight.js/styles/github.css';

hljs.registerLanguage('xml', xml);

let inputChecker = null;
export default function Home() {
  const [user, setUser] = useState('nikaera');
  const [previewUser, setPreviewUser] = useState('nikaera');
  const [badgeCode, setBadgeCode] = useState('nikaera');
  const [style, setStyle] = useState('plastic')

  /**
  useEffect のタイミングで hightlight.js の初期化を行う。
  called プロパティを false にすることで highlight.js で、
  コードが変更された場合でも常にシンタックスハイライトすることが可能
  */
  useEffect(() => {
    hljs.initHighlighting();
    hljs.initHighlighting.called = false;
  });

  useEffect(() => {
    /**
    シンタックスハイライトしたいコード input フォームへの入力内容に応じて動的に変わる
    */
    setBadgeCode(`  <!-- highlight.js でハイライトする -->
  <div>Hello ${user}!</div>
  }`, [user, style]);
  });

  const handleChange = (event) => {
    if (inputChecker)
      clearTimeout(inputChecker);

    inputChecker = setTimeout(() => {
      clearTimeout(inputChecker);
      inputChecker = null;

      setPreviewUser(event.target.value);
    }, 1 * 1000); // 1 seconds

    setUser(event.target.value);
  };

  return (
    <div className={styles.container}>
      <Head>
        <title>Highlight</title>
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>
          Highlight sample
        </h1>

        <input type="text" value={user} onChange={handleChange} />

        <div>
          { /* pre -> code タグ内に highlight.js で
            シンタックスハイライトしたい内容を出力する */ }
          <pre style={{ width: '80vw' }}>
            <code className="xml">
              {badgeCode}
            </code>
          </pre>
        </div>
      </main>

      <footer className={styles.footer}>
      </footer>
    </div>
  )
}
```

# おわりに

React に highlight.js を組み込むやり方は多々見つけたものの、中々上手くできなかったのでメモっておきました。同様のケースで悩んでいる方の助けになれれば幸いです:pray: 

# 参考リンク

- [React – ユーザインターフェース構築のための JavaScript ライブラリ](https://ja.reactjs.org/)
- [highlight\.js](https://highlightjs.org/)
これからデータ分析するなら Data Science Virtual Machines が最高の環境！

この記事は、[求ム！Pythonを使ってAzureで開発する時のTips！【PR】日本マイクロソフト Advent Calendar 2020](https://qiita.com/advent-calendar/2020/azure-python) の 4 日目です（後から追っかけで書いています）。

----

これからデータ分析するなら Data Science Virtual Machines が最高の環境！って話です。

## [Data Science Virtual Machines](https://azure.microsoft.com/ja-jp/services/virtual-machines/data-science-virtual-machines/?WT.mc_id=AZ-MVP-5001601) が最高の環境の理由は何があるんでしょうか？ 他じゃダメなんでしょうか？

その理由は以下になります。

* 問題
    * 誰しもデータ分析に最適な環境を持っているわけではない
    * データ分析に最適な環境を構築するのは大変（時間など）
* 解決策
    * 「[Data Science Virtual Machines](https://azure.microsoft.com/ja-jp/services/virtual-machines/data-science-virtual-machines/?WT.mc_id=AZ-MVP-5001601) ならデータ サイエンスと AI 開発向けに事前構成されたクラウドの仮想マシン」なので、誰しも簡単に準備ができる

## Azure Machine Learning と Data Science Virtual Machines の違いは？

[これから機械学習するなら Azure Machine Learning が最高の環境！](https://qiita.com/changeworld/items/deab548b7ad6dbbb7b4d) を書いている通り、[Azure Machine Learning](https://azure.microsoft.com/ja-jp/services/machine-learning/?WT.mc_id=AZ-MVP-5001601) と [Data Science Virtual Machines](https://azure.microsoft.com/ja-jp/services/virtual-machines/data-science-virtual-machines/?WT.mc_id=AZ-MVP-5001601) の違いをご説明します。

[Data Science Virtual Machines](https://azure.microsoft.com/ja-jp/services/virtual-machines/data-science-virtual-machines/?WT.mc_id=AZ-MVP-5001601) がデータ サイエンス向けにカスタマイズされた VM イメージであるのに対し、[Azure Machine Learning](https://azure.microsoft.com/ja-jp/services/machine-learning/?WT.mc_id=AZ-MVP-5001601) はフルマネージドのサービスという違いがあります。

他にも、[Azure Machine Learning](https://azure.microsoft.com/ja-jp/services/machine-learning/?WT.mc_id=AZ-MVP-5001601) のサポート言語は Python と R ですが、[Data Science Virtual Machines](https://azure.microsoft.com/ja-jp/services/virtual-machines/data-science-virtual-machines/?WT.mc_id=AZ-MVP-5001601) では Python と R 以外にも、Julia、SQL、C#、Java、Node.js、F# をサポートしています。

このように根本的に用途が異なっています。フルマネージドのサービスではないため、カスタマイズ性は [Data Science Virtual Machines](https://azure.microsoft.com/ja-jp/services/virtual-machines/data-science-virtual-machines/?WT.mc_id=AZ-MVP-5001601) の方が明らかに上です。

ただ、要件によっては機能がファットな面もあるので、どちらが優れていて、どちらが劣っているということはありません。要件にあったサービスを使い分けることが大事だと思います。

**5 日目は @changeworld の「[データサイエンティストのための最強のフロントエンド Streamlit を Azure にデプロイ！](https://qiita.com/changeworld/items/b7370520dcce052da62f)」です。引き続きお楽しみください。**
VSCode + Remote Containerで環境構築(Go・応用編)

# 序文と謝辞

先日Go言語で簡単な方法を使ってリモートコンテナをつくりました（参考：[VSCode + Remote Containerで環境構築(go編)](https://qiita.com/honami/items/a1d943c31874cf576e43)）が、作ったあと心の師匠(@MegaBlackLabel)からLGTMとともに以下のような~~ツッコミ~~天啓が。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">いいですね。<br>次のステップでdocker-composeに差し替えしつつ、srcフォルダをプロジェクト内のsrcフォルダにvolumeをアタッチするのをするといい感じかと。</p>&mdash; れいな@底なし沼の魔女 (@MegaBlackLabel) <a href="https://twitter.com/MegaBlackLabel/status/1340831934067273728?ref_src=twsrc%5Etfw">December 21, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

数日後に本格的にアプリ作れというお上のお達しが入り、流石に先の環境では不十分だということが見えてきたため、この課題に改めて向き合ってそれっぽい環境を作ったので、改めてまとめます。

# 目次
- [1. 前提環境](#1-前提環境)
- [2. 作業フォルダの作成](#2-作業フォルダの作成)
- [3. コンテナ用のファイルを作成](#3-コンテナ用のファイルを作成)
- [4. リモート用のコンテナ設定ファイルを作成](#4-リモート用のコンテナ設定ファイルを作成)
- [5. コンテナの起動](#5-コンテナの起動)

# 1. 前提環境

- [Visual Studio Code](https://code.visualstudio.com/download)
    - [Remote - containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)プラグインがインストール済
- [Docker Desktop](https://www.docker.com/products/docker-desktop)

これ以外には基本的に準備不要。Remote - containersのインストールがわからない場合は前記事（[VSCode + Remote Containerで環境構築(go編)](https://qiita.com/honami/items/a1d943c31874cf576e43)）を参照。

Windows 10(Pro)で動作確認しているが、恐らくhome含め他OSでも問題ない（homeの場合は別途WSL2が必要）。

# 2. 作業フォルダの作成

今回はざっくり以下のような構成にします（".devcontainer"を除き、フォルダ名は任意です）。

```
go-proj
├─ .devcontainer
│    └─ devcontainer.json
├─ docker
│    └─ go
│        └─ Dockerfile
├─ src
└─ docker-compose.yml
```

トップディレクトリ以下を作成してください。各ファイルについては以降の項目で記載します。

# 3. コンテナ用のファイルを作成

フォルダ構成を変えた場合は適宜変更してください。

## docker-compose.yml

（本記事通りに作る場合、トップディレクトリ"go-proj"下）

```:docker-compose.yml
version: '3.8'

services:
  app:
    build: ./docker/go/
    command: /bin/sh -c "while sleep 1000; do :; done"
    ports:
      - 8080:8080
    volumes:
      - ./src:/go/src:cached
```

## Dockerfile

（本記事通りに作る場合、"go-proj/docker/go"下）

```:Dockerfile
# 本記事記載時点でのlatest
FROM golang:1.15

WORKDIR /go/src

ENV GO111MODULE=on
ENV GOPATH /go

RUN go get -v \
        golang.org/x/tools/gopls \
        github.com/ramya-rao-a/go-outline \
        github.com/sqs/goreturns
```

# 4. リモート用のコンテナ設定ファイルを作成

## devcontainer.json

（本記事通りに作る場合、"go-proj/.devcontainer"下）

```:devcontainer.json
{
    "name": "go",

    "dockerComposeFile": [
        "../docker-compose.yml"
    ],

    "service": "app",
    "workspaceFolder": "/go/src",

    "settings": { 
        "terminal.integrated.shell.linux": null,
        "go.gopath": "/go"
    },

    "extensions": [
		"golang.go",
    ],

    "shutdownAction": "stopCompose"
}
```

# 5. コンテナの起動

VSCodeでプロジェクトフォルダを開き、コマンドパレットその他から`Remote-Containers: Reopen in Container`を実行。

# X. 参考記事

[Go + echo + Docker + VSCode + Remote Containers で開発環境の構築 (ホットリロードとステップ実行対応)](https://qiita.com/f_sugar/items/49871913fb4baf1ad8d2)：途中までを参考にした（realizeのメンテ絡みでこの手順通りの進行は記事現在使用不可）。余談だが、筆者はrealize→air（とecho→gin）で構築している。
デザイナーがプロダクトチームに貢献するコツ

## はじめに
株式会社ACCESS AdventCalender24日目を担当します。

ACCESSに入社してから1年は主に受託案件のデザインを担当し、
2年目から自社プロダクトチームにデザイナーとして加わりました。

最初は立ち回り方がわからず、みんなが忙しいのに手が空いてしまうこともありましたが、最近はそこそこうまく関われるようになったかも・・？？と思えてきたのでそのコツをまとめてみます。

## デザイナーがプロダクトチームに貢献するコツ

### コツ①　仕様検討を一緒にやる

仕様検討の際は要件を元にFigmaでたたき台を作り、エンジニア・テスター・サポートのメンバーと一緒にそれぞれの目線を持って仕様を詰めていく、という方法をとりました。

「仕様検討完了→デザイン完了→実装」と分業にしてしまうと「ここの意図は？」「ここちょっと認識が違うんだけど」という認識齟齬や手戻りが発生しがちですが、検討から一緒にやることでより早く実装まで持っていくことができます。「実装を最小限にするにはどうすれば良い？」というようなやり取りも出来るため、デザイナー以外の専門分野への理解も深まりました。


### コツ②　数字を見るようにする
Google Analyticsを使い、サービスがどういった使い方をされているのか、どこで離脱をしてしまうのか、という数字を追うことを習慣にしました。
最初は何を読み取ったらよいのかわかりませんでしたが、データを定点観測して気になる変化をメモしたり、リリース後の反応を見て次の展開を考えたり、少しずつですが慣れていきました。
初回登録の離脱や新機能の使い勝手についてなど、数字を元に議論したり提案したりすることができるようになったかなと思います。


### コツ③　エンジニアが稼働しなくて良いことは何でもやる

・公式サイトを充実させる
ユーザーに必要な情報を揃え、より多くの人にサービスを知ってもらえるように公式サイトの改善を行いました。
公式サイトはエンジニアを通さなくてもリリースできる唯一のものなので、スピード感を持ったトライを繰り返すことができました。

・ユーザーインタビューをやる
新機能リリースにあたり、登録プロセスのユーザーインタビューを行いました。
シナリオ作成からインタビュー環境の準備まで手探りでしたが、実際に操作をしてもらう様子を見られる機会が今までなかったので大きな学びがありました。

## プロセスを共有してメンバーに頼る
デザインの際に大事にしていたのは「プロセスを共有する」ということです。
Slackなどを活用し、未完成の状態でメンバーの目に触れる機会を増やすことを意識しました。
認識のすり合わせを頻繁に行えますし、悩んでいたことがメンバーの意見であっさり解決することも多々あります。
「1人で完璧にデザインしなきゃ！」と変に気負わなくなったことで、フットワークが軽くなった気がします。

また、デザインデータをSketch→Figmaに移行することでみんながアクセスしやすい状態にしてみました。
まだFigmaのポテンシャルを活かしきれているとはいえず、もう少し頑張りたいところ...



## まとめ
全体を通し「デザイナー以外のメンバーと共通言語を持てるように努めること」「目的を意識して自走すること」が大事だなと思います。

「デザイナーの仕事じゃなくない？」と思う箇所もあるかもしれませんが、
見た目を作るだけでなく「ユーザーとサービスの関係を作る」こと全てがデザイナーの仕事だと捉えた方が、できることが増えて楽しいと思っています。

まだまだ反省ばかりの毎日ですが、より多くの人にサービスを使ってもらえるように頑張っていきたいです。
CodeDeployでデプロイ時にApplicationStopでエラーが出る件

# 解決方法

パブリックIPの自動割り当てを有効にしたらなおりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103853/aec31d8e-798f-74e9-dbe9-248a392a2240.png)

こんなところいじったかな😭
他のインスタンスと見比べてパブリックIPが割り当てられていないことにもっと早く気づくべきでした😭

デーモンを再起動することで解決するケースもあるらしいです。
[CodeDeployで、EC2へのデプロイ時にApplicationStopが0秒間でエラーになる問題の対処方法](https://zenn.dev/snicmakino/articles/b8523ca8aef37c403b45)
Gitでローカルブランチを削除

# はじめに
学習用のメモになります。

## ローカルブランチを削除する手順

### ローカルブランチの確認
```
$ git branch
```

### 削除コマンド
```
# どちらも同じ
$ git branch --delete [ブランチ名]
$ git branch -d [ブランチ名]
```
* マージ済みのブランチのみ削除ができる
  マージされていないブランチを削除しようとすると下記のようなエラーがでます
  error: Cannot delete the branch 'ブランチ名' which you are currently on）
* マージされていないブランチを削除したいときは削除コマンド2を


### 削除コマンド２
```
$ git branch -D [ブランチ名]
```

* どんなローカルブランチでも削除できる
homebrewのcaskコマンドはオプションになりました。

homebrewでGUIをもつアプリをインストールしたい時はcaskを使いますよね。
mac入れ替えで初期セットアップ中に下記のようなエラーに遭遇しました。

```
hori$ brew cask install google-cloud-sdk
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).
==> New Formulae
libvdpau                                                           xcb-util-cursor
==> Updated Formulae
Updated 107 formulae.
==> Updated Casks
Updated 319 casks.
==> Deleted Casks
gfortran                                                           openxcom

Error: Calling brew cask install is disabled! Use brew install [--cask] instead.
```

# 解決策
`brew cask install ~` ではなく `brew install --cask ~` を使えばOKでした。

```
hori$ brew install --cask google-cloud-sdk
==> Caveats
google-cloud-sdk is installed at /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk. Add your profile:

  for bash users
    source "/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/path.bash.inc"
    source "/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/completion.bash.inc"

  for zsh users
    source "/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/path.zsh.inc"
    source "/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/completion.zsh.inc"

  for fish users
    source "/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/path.fish.inc"

==> Downloading https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz
######################################################################## 100.0%
Warning: No checksum defined for cask 'google-cloud-sdk', skipping verification.
==> Installing Cask google-cloud-sdk
Beginning update. This process may take several minutes.
```

# 補足
`Error: Calling brew cask install is disabled! Use brew install [--cask] instead.`

よく読めば書いてありましたね。
`brew cask install` は無効になったよ！ `--cask` を使ってね！

こちらのissueを参考にしました。
https://github.com/ansible-collections/community.general/issues/1524
(ansibleのissueですが・・・^^;)

`brew cask` コマンドは2.6から非推奨になり、2.7から無効化されたようです。
2.8からはエラーメッセージも表示されなくなるそうです。
https://github.com/Homebrew/brew/pull/9247
ここで対応されてました。

私の環境はちょうど2.7でした。

```
hori$ brew --version
Homebrew 2.7.0
Homebrew/homebrew-core (git revision fd7c4; last commit 2020-12-24)
Homebrew/homebrew-cask (git revision 2fd68; last commit 2020-12-24)
```
【VBA】なんとなく理解していたものを丁寧に復習する①用語編

#はじめに
VBAを始めるきっかけはなんでしょうか。
VBAの仕事をするためにしっかり講座を受けるという人もいれば、
業務で必要になったから、独学で始める人もいるのかなと思います。
私はどちらかというと後者なのですが、
独学だと「なんとなくわかっている」という状態で流している知識は意外と少なくないと思います。
なんとなくわかってはいるけど、いざ説明してと言われるとうまくできないみたいな経験ありませんか？
そんなわけで一回基礎に立ち返って、最初から丁寧に復習してみようと思います。

あ、ここではExcelのVBAを取り扱います。

#どの層にあてた記事か
前述の通り復習がメインですので、これからVBAを学んでいく全くの初心者よりは、
VBAを少しかじった人向けになるかと思います。

#そもそもVBAって何？よく使う用語をまとめてみる。
VBAとかマクロとか、普段会話でよく使ってるけどその定義ってそもそも何なのか？
なんとなくその言葉を使ってるけど、使い方あっているのかな？
ということで、そもそものVBAの定義とかよく使う用語について、一回まとめてみます。

ただ定義をつらつらと並べてもあまりよくわからない気がするので、
要するに何なのかという、私なりにかみ砕いた解釈も一緒に載せたいと思います。

###～よく使われる用語一覧～

| 用語 | 定義 | 要するに |
|:---|:---|:---|
| マクロ | macro・・・「大きい」「長い」<br>アプリケーションやソフトウェアでの複数の操作や命令などを一つにまとめて、自動化する機能のこと。 | 処理を自動化する機能 |
| VBA | 「Visual Basic for Application」の略<br>主にMicrosoft Office製品に搭載されているプログラミング言語。<br>マクロを動かす一手段です。 | Microsoft Office製品でマクロを実行できるプログラミング言語 |
| VBE | 「Visual Basic Editor」の略<br>VBAの統合開発環境（IDE）のこと | VBAの開発ツール |
| 関数 | プログラム中で与えられた値（引数）を使用して計算や処理を行い、その結果を呼び出し元に返すもののこと。 | VBAではFunctionで定義される処理を行うコードのまとまり。<br>処理のもととなる値（引数）を渡して、処理結果を戻り値として取得できる。 |
| プロシージャ | procedure・・・「手続き」「手順」<br>プログラム内で複数の命令や処理などを一つにまとめたものをいう。 | 使用される意味としては関数とほぼ同義。<br>こちらは引数を渡せますが、戻り値が取得できないのが特徴。<br>Subで定義される。 |
| オブジェクト | object・・・「物体」「対象」<br>コンピュータ上で操作や処理の対象となるもの | プログラムで操作する対象 |
| クラス | オブジェクトを生成するためのひな形に相当するもの | オブジェクトの設計図 |
| インスタンス | instance・・・「実例」<br>クラスを元に作成したオブジェクトの実体を指す | クラスを実体化したもの |
| プロパティ | property・・・「属性」「性質」<br>オブジェクトが持つ設定や属性などの情報のこと。 | オブジェクトに設定する情報 |
| メソッド | method・・・「方法」「方式」<br>プログラミングでオブジェクトの処理や操作のこと | オブジェクトを動作させる命令 |
| ステートメント | statement・・・「陳述」「声明」<br>プログラムを構成する手続きや命令、宣言などのこと | マクロにおける動作を制御するための構文 |


#参考サイト
・IT用語辞典 e-words・・・http://e-words.jp/
・エクセルの神髄 鵜原パソコンソフト研究所・・・https://excel-ubara.com/
・覚え書き.com・・・http://write-remember.com/archives/697/

#最後に
今回は初歩的な用語をまとめてみました。
初歩的とはいえ、意外とこのあたりの言葉の説明とか難しいなと改めて感じましたし、
普段からちゃんと使い分けて話せているかたまに不安になることもあるので、
リファレンスになればいいなと思います。
[mac] pyenv+Jupyter-Lab環境にRをインストールする

## 目的

* pyenv環境で起動したJupyter Lab上で、Rを利用できるようにする

## 動作確認環境

* macOS Big Sur (version 11.1)
* Jupyter Core : 4.6.3
* Jupyter Lab : 2.2.8
* R : 4.0.3

## 前提条件

* Jupyter, Jupyter Labがインストールされていること

## インストール手順

HomebrewでRをパッケージインストールします。

```
% brew casc install r
```

インストール先のpyenv環境を有効化し、ターミナルからRのコンソールを起動します。

```
% pyenv local testenv
(testenv) % R
---
R version 4.0.3 (2020-10-10) -- "Bunny-Wunnies Freak Out"
Copyright (C) 2020 The R Foundation for Statistical Computing
Platform: x86_64-apple-darwin20.1.0 (64-bit)

(...略...)

> 
```

IRkernelをインストールし、カーネルの登録を行います。

* 参考 : [IRkernel/IRkernel - GitHub](https://github.com/IRkernel/IRkernel)

```
> install.packages('IRkernel')
> IRkernel::installspec()
```

Jupyter Labを起動し、Rカーネルが利用可能になっていることを確認します。

![スクリーンショット 2020-12-24 9.36.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342646/51610542-4cc8-f9a4-4ae5-bea954c886e0.png)

## 関連記事

* [MCMCのためのRStan環境構築 [mac, JupyterLab] - Qiita](https://qiita.com/roki18d/items/ee87044cbe226030c2fc)
PHP 半角カタカナを全角カタカナに変換する

# 目的

- 半角カタカナを全角カタカナに変換する方法をメモする

# 情報

- 下記サービスを用いて動作を確認した。
    - [https://paiza.io/ja](https://paiza.io/ja)
- 本記事は筆者のメモ的要素が強いため簡単にまとめる。

# 方法

- mb_convert_kana()関数を使用する。
- 下記に例を記載する。変数`$str`に格納される半角カタカナ「ﾊﾞﾋﾞﾌﾞﾍﾞﾎﾞ」を「バビブベボ」と変換したい。

    ```php
    <?php

    $str = 'ﾊﾞﾋﾞﾌﾞﾍﾞﾎﾞ';

    $str = mb_convert_kana($str, 'KV');

    print_r($str);
    ```
- 上記を実行すると「バビブベボ」と全角で出力される。
- mb_convert_kana()関数の第二引数で渡している`KV`は変換オプションであり、K→「半角カタカナを全角カタカナに変換する」、V→「濁点付きの文字を一文字に変換する」ことを指定している。Vをつけないと「ハ゛ヒ゛フ゛ヘ゛ホ゛」と変換され濁点も一文字として扱われてしまう。

# 参考文献

- [https://www.php.net/manual/ja/function.mb-convert-kana.php](https://www.php.net/manual/ja/function.mb-convert-kana.php)
discord.jsでembed(埋め込み)を送りたい。

discord.jsで埋め込みを送信したいと思います。
埋め込みのソースはこのような形になっております。

```javascript:main.js
  if (message.content === 'ここのメッセージが送られたら反応する') {
try {
message.channel.send(
  {embed: {
    timestamp: new Date(),
    color: "RANDOM",
    description: `送るメッセージ`
  }}
);//送信
} catch (err) {//エラーが起きたら反応する。
      message.channel.send(
        {embed: {
    timestamp: new Date(),
    color: "RANDOM",
    description: "**エラー : 実行中にエラーが発生しました。**\n```js\n" + err + "```"
  }});//送信
    }}
```
これが埋め込みの基本的な形です。
さらに埋め込みにはメンションを加えることが出来ます。
しかし、通知はされません。

```javascript:main.js
message.channel.send(
  {embed: {
    author: {
      name: "author name <@!496190049872773130>",
    },
    title: "title <@!496190049872773130>",
    description: "description　<@!496190049872773130>",
    footer: {
      text: "footer text　<@!496190049872773130>"
    },
    fields: [
      {
        name: "field name <@!496190049872773130>",
        value: "field value <@!496190049872773130>"
      }
    ]
  }}
);
```
を実行すると
![画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/977112/005ce454-200a-beb4-8553-c3b870e87594.png)
と表示されます。
つまり、descriptionとfield value以外はメンションが送られてません。

あとがき
embedのtestでは[embed-visualizer](https://leovoel.github.io/embed-visualizer/)を利用しましょう。
[WordPress] wp-cli とシェルスクリプトで WordPress の記事リストを作成

公開されている記事のリストを取り出したいだけなら、wp-cli で `wp post list --post_status=publish --format=csv` すればいいだけなんですが、permalink が取れないんですよね..
[wp post list | WP-CLI Command | WordPress Developer Resources](https://developer.wordpress.org/cli/commands/post/list/)

permalink も取り出したい場合は、こんな感じで csv に書き出せます

```
#!/bin/bash
WP_PATH="${1:-./}"
WP="wp --path=${WP_PATH} --skip-plugins --skip-themes"
POSTS=$(${WP} post list --field=ID --post_status=publish)
for POST in ${POSTS} ; do
	${WP} eval "\$post=get_post(${POST}); echo \$post->ID.',\"'.\$post->post_date.'\",\"'.\$post->post_title.'\",'.get_permalink(${POST}).','.\$post->post_type.','.\$post->post_status.\"\\n\";"
done
```
Reactの開発環境を作る

# React の開発環境

ターミナル上で下記のコマンドを実行することで、create-react-app を準備する

## create-react-app とは

React を開発するための環境

## 準備する環境

macbook
node 8.10 以上
npm 5.6 以上

## 開発環境を作るディレクトリに移動する

## homebrew をインストールする

## nodebrew をインストールする

一緒に npm もインストールされる

### インストールコマンド

`brew install nodebrew`

### インストールの確認

`nodebrew -v`

## npm インストールの確認

`npm -v`

## reate-react-app のインストール

`npx create-react-app` [開発環境を作るディレクトリ名]

上記作業により、開発環境は完了

# create-react-app の実行

## npm のビルド

`npm run build`

## npm の開始

`npm start`
自己紹介とよくあるエラーについて

こんにちは！
まず簡単な自己紹介をさせて頂きます。

プログラミング初心者のmizutaniと申します！

メーカー向けの営業を2年ほど経験した後、本格的に学習を始めました。
元々プログラミングは好きで、大学生の頃から簡単なHTML,CSS,Javascriptの書籍を読んで、学習したりしていました。
きっかけは大学2年生の時に参加したインターン。
ビジネスコンテストで優勝したことで、ビジネスアイデアを考えるのは面白いと思い、そこから学習開始。
テックアカデミーで1ヶ月フロントエンドを学んだこともありました。

しかし周りの影響で、大手志向になり、新規ビジネスとは無縁の会社に。
営業は楽しかったし、成績も良かったのですが、思い切ってチャレンジすることにしました笑

ただrubyは触り始めて2ヶ月ほど。
毎日試行錯誤しながら取り組んでいます。

そんな自分が書くテーマは
##「よく初心者が陥るエラー」です。

最近プログラミングを学ぶ人が増えていることは嬉しいことです。
単純に仲間が増えるという意味で励みになるのですが、
エラーで嫌になってしまう人も多いと思います。
（自分も高校生の頃、挫折したことがあります笑）

そこでよくあるエラーを頭に入れておけば、学習への壁が少しでも低くなるのでは？　　と考えました。

では2つ程紹介させて頂きます！

###①no method error

これが恐らく一番多いのではないでしょうか。

原因として多いケースは以下の2つです。

・メソッドの定義ができていない。
・オブジェクトに必要な情報が入っていない。

私は外部キーの値をインスタンス変数に入れ忘れて、no method errorになりました笑
当時は勝手に値が入るものと思い込んでいました。
（外部キーの値がないとアソシエーションができず、メソッドも使用できません。）
ただbinding.pryなどを使えば一発で中身が分かるので、
もし困ったら確認しましょう！
（rails チュートリアルにbinding.pryの事が書かれているので、困ったら確認を）


###②routing error

これもよくあります。
ただこれも　ターミナルでrails routes　のコマンドを使うと大体解決できます。
（今現在設定されているルーティングを確認するコマンド）


・link_to メソッドの引数のミス
・routeの記載ミス
・form_with ヘルパーメソッドの引数ミス

もしリクエストの中身が知りたければ、binding.pryを使用した後に、paramsを入力すれば分かります。

以上で紹介は終わりますが、以下の事が少し分かったのではないかと思います。

##・初心者が陥るエラーはコマンドやデバッグツールを使えば、原因が分かる

勿論難しくなればなるほど、エラーの難度は上がると思います。
しかし始められたばかりの方は一度デバッグツールの使用法を意識して学ぶのが良いのではないでしょうか。

自分も大きな顔して言っていますが、自戒も込めて今回の記事を書かせて頂きました！

お互いに今後も頑張っていきましょう！！
vscodeで.tpl拡張子をhtmlに関連付ける

phpにはsmartyというテンプレートエンジンがありますが、vscodeで.tplファイルを開くと紐付けが出来ておらず、シンタックスハイライトされないと思いますので、関連付け方を記載させて頂きます。

## 1. setting.jsonを開く
macの場合の操作ですが、`Command + ,` で設定画面を開いて下さい。

![setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104359/069428da-d61d-d26d-26b9-aae7a2cc01e2.png)

上記右上のアイコンをクリックすると、setting.jsonが開きます。


## 2. setting.jsonへ記述

setting.jsonへ以下を記述して保存して下さい。

```
    "files.associations":
    {
        "*.tpl": "html",
    }
```

上記で.tplファイルもハイライトされるはずです。
※変わらない場合はvscodeの再起動を試して下さい。
ロボット掃除機について

#はじめに

　普段よく目にするロボット掃除機がどのような仕組みで動いているのか気になったので調べてみました。
今回はロボット掃除機の中でも有名な「ルンバ」について調べました。

#仕組みの簡単な説明

　ルンバの正面にはバンパーが付いており、その中に接触センサーが入っています。バンパーが壁などの障害物に当たると他に方向を変える指示が出るようになっています。また、本体の裏側にも様々なセンサーが付いており階段などの段差を感知し、落下を防いでいます。本体の充電が無くなってくるとセンサーでホームベースを探して自動で充電されます。

#ロボット掃除機の基本的なアルゴリズム

####人工知能＋パターン型（ルンバなど）

　ロボット掃除機は部屋を掃除する際、「螺旋状に掃除する」「壁伝いに掃除する」「障害物や壁などにぶつかったら角度を変えてランダムに移動する」などといくつかの単純な発見的手法を用いて動作しています。しかし、それだと同じ場所を何度も行き来したり、全く通らない箇所が出てくる、ということが起きてしまいます。ですがルンバは、各部に取り付けられたセンサーで収集した情報を人工知能が判断することで、状況に応じた最適なコースを動くことができます。また、走行距離センサーの情報を基に掃除した箇所を判断するため、一般的なパターン型のみの機種に比べて偏りが少なく、複数の部屋や複雑な部屋にも対応することができます。

####人工知能＋マッピング型（その他）
　ルンバ以外のロボット掃除機にはマッピング型を利用したものもあります。マッピング型とは、センサーで収集した情報を基にマッピング(地図作成)を行い最短ルートを導き出します。レーザーや赤外線を照射して障害物や壁などの距離を測る方法や、内蔵カメラで天井や壁を撮影して現在位置と照合する方法などがあります。
　この方法の場合、部屋の形状を地図化するため何度も同じルートを通ることはありません。なのでパターン型と比べると動きが効率的で良く思えますが、ロボット掃除機の弱点として吸引力の弱さが挙げられるので、掃除場所を一度しか通らないこの方法だとゴミを十分に取りきれないことが起きてしまいます。

#最後に

　ロボット掃除機の仕組みやどういったルートを通っているかなど、たくさん知ることが出来ました。また、ロボット掃除機にはまだまだ課題が多いのでこれからの進化が楽しみです。

#####

参考サイト：
https://ja.wikipedia.org/wiki/%E3%83%AB%E3%83%B3%E3%83%90_(%E6%8E%83%E9%99%A4%E6%A9%9F)
https://www.itmedia.co.jp/lifestyle/articles/1411/11/news106.html
Googleフォーム回答後の自動応答メールを自前の文面で送る

# はじめに

Googleフォームには、回答後にメールで自動応答する機能が備わっています。
このメールを標準の文面ではなく、好きな文面で送りたいと思ったので調べてみました。
回答を編集するための URL をメールに含めることもできます。

# 対象の人

* Googleフォームの標準の自動応答メールとは違う内容で送りたい人
  * 好きな文面で送りたい、とか
  * 回答内容はメールに入れたくない、とか
* メール以外の方法で通知したい人
  * 今回は扱っていませんが参考になると思います

# さっそく

任意のGoogleフォームを作ります。
フォームができたら画面右上の歯車を押して、標準機能のメールが送られないようにしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525650/5706d7d8-3d29-f595-f8c4-c688a50ba4c7.png)

次に、画面右上の `︙` から「スクリプトエディタ」を開きます。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525650/07616a75-e7c5-0403-0f6d-af59ae760a8b.png)

続いて、下記のような関数を書いて下さい。
この関数はフォームで回答される度に走る想定です。

* やっていること
  * 回答者のメールアドレスに
  * お礼の文面と回答日時、回答編集用URLを送信

なお、引数 `e` についての詳細は https://developers.google.com/apps-script/guides/triggers/events#form-submit_1 を確認下さい。

```js:Code.gs
function onSubmit(e) {
  
  const resp = e.response;
  
  // 回答者のメールアドレス
  const mailAddress = resp.getRespondentEmail();
  if (!mailAddress) {
    return;
  }
  // 回答日時
  const timestamp = Utilities.formatDate(resp.getTimestamp(), 'JST', 'yyyy-MM-dd HH:mm:ss');
  // 回答編集用URL
  const editRespUrl = resp.getEditResponseUrl();
  
  // 本文
  const body =
    'アンケートにご回答頂きありがとうございました。\n' +
    `${timestamp} に回答を受け付けました。\n` +
    '\n' +
    '回答内容を変更したい場合は下記から行えます。\n' +
    `${editRespUrl}`;

  // メール送信  
  MailApp.sendEmail({
    to: mailAddress,
    subject: 'アンケート御礼',
    body: body
  });
}
```

次に、フォームで回答される度に上記の関数が動くようにトリガーを設定します。
画面の左側のメニューから、トリガーを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525650/a8ed695f-1b34-a7e3-2342-d566f70b61c6.png)

続いて画面右下の「トリガーを追加」を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525650/e00b936b-83cc-e68e-db5e-d9a064042180.png)

トリガーは下の画像のように設定して保存します。

* 実行する関数：`onSubmit`
* イベントの種類を選択：`フォーム送信時`

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525650/e5287649-71e6-4e75-265a-e4c136056500.png)

保存した内容が一覧に出てくれば準備完了です。
これでフォームに回答すると、以下のような自前の応答メールが自動で送られます。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525650/9912bd3d-d6fa-b990-3964-819317d246c9.png)

# 所感

ここに書いた内容を応用すると、メールを送る以外にもたとえば Slack などに投稿することもできそうです。
銀河系の情報を調べようとAzureクラウドを使おうとしたら、面食らった話について

<font color=blue>初めての技術系記事の投稿ですが、よろしくお願いします。</font>

Azureでどこに手を付けたらいいか全くわからないほどであった件


--とりあえず、知っている範囲で使おうと思ったもの--

①Linux　ubuntu系を想像　2020年12月25日時点 
  当方、VMしか知らず。




『PaaSでのサービスのようなものをイメージ』

--理想のやり方--
 DevOps　　　　→　簡単に出来たらいいなと思うこの頃

ローコード開発　→　プログラミングが不得意からによる

ーーーーーーーー実際の所ーーーーーーーーーーー

azureでpower app以外のノーコード・ローコードツールが使えるかわからず。

それで、とりあえず Power Apps Community Plan　の利用を考える。
↓
それで　検索で『個人で無料で始める Power Apps 2020年最新版【8月】』
を見つけたので、開発者プログラムに参加する　
をやってみることに。

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

そして記事の通りにやると、無事PowerAppsに入ることができた。

そしてアプリの開発へ繋がることとなった。

powerappsでアプリ開発へと繋がる。

----------------------------------------------------
続いてアプリ開発で気になるのが、要件定義
実は私、要件定義の時間を取ったことがほとんど無い。
今回が初であろう。
そしてweb業界用の要件定義書を作ろうとする

ここでDevOpsの話を思い出す。要件定義の話からアジャイル型でリリースして効率化させようとする。

そして道具としての開発者の開発ツールを軸に考えるようになる(2021/01/19時点)

再び時間が経過して、OSSの思考でやろうと考える。(2021/03/16時点)
----------------------------------------------------
しかしここでやはりプログラミング言語のPythonを使う事に変更してしまい、ノーコードは取りやめることに(2021/06/04時点)

そして本当にPythonを使う事に移行へ。そして通信に関するアプリが作りたいという希望で、Twilioを使う事を考える

Twilioを使い通信アプリみたいなものを作りたいと考えていたが、だがしかし OSSのChromium OSに出会ってしまう。

そしてChromium OSの研究を始めようと考えるのであった。

この記事の内容は、今回はここまでです。　長い間　ありがとうございました。
「依存関係逆転の原則(DIP)」を学んだ

## はじめに

Javaの学習を初めてしばらく経ったので、設計力を上げるため、SOLID原則を学んでいる。

学んだ内容について自分の中で咀嚼するため記事を書いてみた。

## 依存関係逆転の原則(Dependency Inversion Principle)とは何か

SOLID原則の一つであり、ソフトウェアモジュールを疎結合に保つための原則、方法論のこと。

下記のような原則が述べられている。

> A. 上位レベルのモジュールは下位レベルのモジュールに依存すべきではない。両方とも抽象（abstractions)に依存すべきである。

> B. 抽象は詳細に依存してはならない。詳細が抽象に依存すべきである。

引用 : [https://ja.wikipedia.org/wiki/依存性逆転の原則](https://ja.wikipedia.org/wiki/%E4%BE%9D%E5%AD%98%E6%80%A7%E9%80%86%E8%BB%A2%E3%81%AE%E5%8E%9F%E5%89%87)

## そもそも依存関係とは何か

一言で表すと、クラス間の結びつきのことである。

簡単なコードで例を表してみる。

```java
public class Customer {

    public void pay(){
        BankingPayment payment = new BankingPayment();
        payment.execute();
    }

}
```

```java
public class BankingPayment{

    public void execute() {
       //銀行支払い処理
    }
    
}
```

CustomerとBankingPaymentの２つのクラスがあり、Customerクラス内部でBankingPaymentインスタンスを生成している。この状態はCustomerクラスがBankingPaymentクラスに依存している状態だと言える。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566253/c2e009aa-a910-2e56-8c93-ca399f707010.png)



この状態では、BankingPaymentクラスの変更時にCustomerクラスまで変更しなければならない。(executeメソッドの返り値や引数の変更されるケース)

つまりBankingPaymentクラス(=下位レベルモジュール)が変更された時、Customerクラス(=上位レベルモジュール)までも変更の影響を受けているということになる。

また仕様や機能追加により別の決済方式が必要になった場合、先の例ではCustomerクラスで呼び出されているBankingPaymentクラスの部分すべてを変更する必要がある。

## 変更の影響を受けないためにはどうすべきか

変更されやすいものには依存せず、安定したものに依存すればよい

## 安定した抽象と変化しやすい具象

インターフェイスは変化しにくいが、実装クラスは変化しやすい。

そのため、変化しやすい具象(=実装クラス)には依存せず、安定しているインターフェイス(=抽象)に依存させる。


```java
interface Payment{
    void execute();
}
```

```java
public class Customer {
    public void pay(){
        Payment payment = new BankingPayment();
        payment.execute();
    }
}
```

```java
public class BankingPayment implements Payment{

    @Override
    public void execute() {
        //銀行支払い処理
    }
}
```

この状態では、CustomerクラスはPaymentインターフェイスに依存しているが、BankingPaymentクラスには依存しなくなった。そしてPaymentインターフェイスをBankingPaymentクラスが実装している。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566253/a481bf39-0f35-e1a2-3aa9-15b554273c44.png)

つまり、上位レベルモジュール(Custmer)が所有するPaymentインターフェイスにBankingPaymentクラスが依存することになり、依存関係が先の例と比べて逆転していることがわかる。

また先の例で決済方法が銀行支払いからクレジット支払いに変更された場合でも、新たにPaymentインターフェイスからCreditPaymentクラスを実装すればよいため、Customerクラスでの変更範囲は最小限に抑えることができる。

## まとめ

変化しやすい具象モジュールには依存させず、インターフェイスを作成し、依存関係を逆転させることで柔軟にシステムの変化に対応できるようになる。