OmniAICreator/Qiita-1.07M huggingface dataset:
【4層目：トランスポート層】TCPとUDPの違いについて

##TCP/IPにおける2つのプロトコル
TCP/IPには、2つのトランスポートプロトコルがある。OSI参照モデルのトランスポート層にあたる役割をこなす。
アプリケーションプログラム間の通信を実現すること。

##何の略か　What do these stand for?

UDP　User Datagram Protocol
ユーザーとは、ここではプログラマにあたる。
Datagramとは、
A datagram is a basic transfer unit associated with a packet-switched network.(wiki引用)
つまり、パケット通信における単位のこと。

TCP  Transmission Control Protocol
読んで字のごとく、転送をコントロールするプロトコル。

##違いは？
違いをざっくり言えば、
TCPは転送を制御するプロトコル
UDPは複雑な制御をしないプロトコル
それぞれによって利点が異なる。なので、優劣があるわけではない。

||UDP|TCP|
|---|---|---|
|通信方式|コネクションレス型|コネクション型|
|信頼性|低い|高い|
|速度|高速|低速|
|データの到達|保証しない|保証する|
|パケットの少ない通信|◎|×|
|主な用途|ビデオ、音声のマルチメディア通信|メールの送受信|
||ﾌﾞﾛｰﾄﾞ/ﾏﾙﾁｷｬｽﾄの通信|ファイルの転送、共有|


#通信方式
**コネクション**(TCPにおける)とは、各種機種や回線、通信を行う2つのアプリケーションが、情報伝達のために占有して使用できる通信路を仮想的に提供するもの（バーチャルサーキットとも呼ばれる）

ＩＰの通信自体が、コネクションレス型なので、そのような中で仮想的にコネクションを確立することで信頼性を高めている。

**コネクション型**とは、そのコネクションを確立してデータを送る。TCPでは、そのコネクションの確立、終了、維持といった管理を行っている。
例えるなら電話のようなもの。
電話番号を入力して、相手が出てから話す。終わったら切る。
相手が通信不可能な場合は、無駄なパケットを送らなくてすむ。
コネクションの確立・切断にパケットを使用することになるので、転送するデータの総量が少ない場合は、無駄が多くなる。


**コネクションレス型**とは、コネクションを確立せず送信要求のあったタイミングでデータをネットワークに流す。郵便のようなもの。一方的に送り、受け取ったかどうかは確認しない。




##信頼性・到達性
*TCP*は、データが到達することを保証する。
・ネットワークの途中で失ったデータがあれば、再送する。
・パケットのデータが入れ替わった場合の制御を行い正しく解決する。
・パケットの到達を確認する確認応答などTCPの中で行っている。

その分、TCPは、複雑な仕組みになっており、ビデオの通信など、一定間隔での一定量のデータの通信が必要な場合向かない。（ビデオなどに使うと、データが途中で失われた場合、再送処理が行われその間音や画像が止まる、また急にパケットが届くと早送り状態になる。）


UDPは、パケットの喪失、順番が入れ替わっても複雑な制御は一切せずデータを送るだけで到達したかどうか確認はしない。パケット量の制御などもせず、トランスポート層として最低限の役割をこなす。
ビデオなどの通信中にパケットを失なっても、再送処理をせずデータを流し続けるので、一瞬ビデオが固まる程度である。そのようなパケットが失われても問題にならないような通信や、リアルタイム性が重要な時において使う。

##ソケットとは（追記21/10/20）
アプリケーションからTCPやUDPを利用するときは、OSが用意しているライブラリを使う。このようなライブラリは、APIと一般的に呼ばれている。
TCP,IPなどの通信では、**ソケットと呼ばれるAPI**(ソケット=APIの名前)が使われている。
元は、UNIXで開発され、windowsやwinsock、組み込み機器のOSなどに移植された。
アプリケーションはソケットを利用して、通信相手のIPアドレスやポート番号を設定したり、データの送受信を行っている。

##まとめ
TCPは、信頼性があるので、信頼性のある通信が必要な時に使われる。
UDPは、リアルタイム性や、高速性が必要な時に使われる。
信頼性が高いから優れているわけでなく、適材適所、適した状況が存在する。

######参考
マスタリングTCP/IP
エンジニアの僕がデザインをする時に参考にするサイト

# はじめに
やや技術的な投稿から外れてしまって恐縮ですが、ユーザーとのインターフェース部分はソフトウェアの一番外側という解釈で記事を投稿します。

実際にサイトを作成するときは、類似サイトをベンチマークしてユーザにとってサービス内容とデザイン(特にアイコンの意味合いなど)のギャップが発生しにくいような設計をします。今回はベンチマークは一通りしたうえで、そこに自分なりのオリジナリティを加える時に参考にしているサイトを厳選して紹介します。

デザインに困っている個人開発者さんの役に立てれば幸いです。

# 画面サイズやブラウザシェアなどを調査するとき
[statcounter](https://gs.statcounter.com/)
サイトを訪問してくれるユーザが利用しているデバイスやブラウザ、画面サイズのイメージをある程度つかんでおくことで、どのようなテストを実施すればいいのかが明瞭になります。すべてのユーザをカバーすることは難しいですが、シェア率の高い順からテストを行うことで、CSS/JSの対応漏れをリリース前に防ぐことができます。

# 色を探したり配色を決める時
[WEB色見本](https://www.colordic.org/)
[イソラボ](https://iso-labo.com/labo/web_color_mix.html)
色に関しては、色彩検定など体系的に学ぶ環境が整っているので理想はそれらの理論を学ぶことですが、いますぐに配色に取り掛からないといけない場合には先人が利用していた配色のルールを拝借することで大外れを防ぐことができます。

# フォントを選ぶ時
[Google Font](https://fonts.google.com/)
[伝わるデザイン(フォントの選び方)](https://tsutawarudesign.com/yomiyasuku2.html)
フォントに関しても一冊の本が書けてしまうくらい奥が深い領域ですが、こちらも先人の知恵を借りましょう。
【M1ソフトウェア導入】Homebrew-node.js-npm

#早速

###●homebrew

M1 Macでのhomebrewは 公式のドキュメント で /opt/homebrew にインストールすることが推奨されている為、以下のような工程でインストールを行う。

https://docs.brew.sh/Installation#untar-anywhere


```bash:install.homebrew
sudo mkdir /opt/homebrew
sudo chown -R $(whoami) /opt/homebrew
curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C /opt/homebrew
//パスを通す
export PATH="/opt/homebrew/bin:$PATH"
//brew installの確認
brew doctor
//バージョンの確認
brew --version
```

###●node.js
https://nodejs.org/ja/download/package-manager/#macos

```bash:install.nodejs
brew install node

//installの確認
node -v
```


###●npm

https://docs.npmjs.com/downloading-and-installing-node-js-and-npm

```bash:install.nodejs
npm install -g npm

//installの確認
npm -v
```


### json-server install and --watch

```bash:install.jason-server
npm install -g json-server

//--watch
json-server --watch xxxxx.json

```
JSのスプレッド構文(...)の使い方について

#スプレッド構文とは？
スプレッド構文とは``...``を３つ繋げることによって配列やオブジェクトを一気に展開出来る構文。
実例を見ていきましょう。
##配列の展開

例えば配列を展開する時に使用できます。

```JavaScript

//定数を指定
const arr1 = [1,2,3]

//スプレッド構文を使ってない場合
console.log(arr1);// => [1,2,3],

//スプレッド構文を使った場合
console.log(...arr1);// => 1 2 3,
```

使い方

```JavaScript


//定数を指定
const sumFunc = (num1,num2) => console.log(num1 + num2);
//出力
sunFunc(arr1[0],arr1[1]);// => 3
//スプレッド構文で書く場合
sunFunc(...arr1);// => 3
```
##まとめる
スプレッド構文を使ってオブジェクトをまとめてみましょう。

```JavaScript

//定数を定義
const arr2 = [1,2,3,4,5];
const [num1,num2,...arr3] = arr2;

//出力
console.log(num1);// =>1
console.log(num2);// =>2
console.log(arr3);// =>[3,4,5]
```

##結合とコピー
配列同士を結合させることも可能です。

```JavaScript

//定数を定義
const arr4 = [10,20];
const arr5 = [30,40];

//スプレッド構文を使用して定数定義・出力
const arr6 = [...arr4];
console.log(arr6); //=>[10,20]

//スプレッド構文を使用して結合
const.arr7 = [...arr4, ...arr5];
console.log(arr7); //=>[10,20,30,40] 

// 定数を定義し、出力
const arr8 = arr4;
arr8[0] = 100;
console.log(arr4);//=>[100,20]

```
##最後に
簡単にスプレッド構文の使い方をまとめてみました。
色々な使い方があるので、一つずつ覚えていきましょう。
CSVファイルでPythonからC++への行列データの受け渡し

#はじめに
Pythonで計算した結果の4×3の行列を,C++から読みたいと思い、その方法をまとめました。

#書き込み(Python)

```Python:write.py
import csv

data = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]

with open('test.csv', 'w') as file:
    writer = csv.writer(file, lineterminator='\n')
    writer.writerows(data)

```

#読み込み(Python)

```python:read.py
import csv
import pprint

with open('test.csv') as f:
    reader = csv.reader(f, quoting=csv.QUOTE_NONNUMERIC)
    l_f = [row for row in reader]

print(l_f) 
```

#読み込み(C++)

```c++:read.cpp
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <iostream>

std::vector<std::string> split(std::string& input, char delimiter)
{
  std::istringstream stream(input);
  std::string field;
  std::vector<std::string> result;
  while (getline(stream, field, delimiter)) {
    result.push_back(field);
  }
  return result;
}

int main(){

  std::string file("test.csv");

  std::ifstream ifs(file);

  std::string line;
  std::vector<std::string> strvec = split(line, ',');

  float m11,m12,m13,m14;
  float m21,m22,m23,m24;
  float m31,m32,m33,m34;

  getline(ifs, line);
  strvec = split(line, ',');
  m11 = std::stof(strvec.at(0));
  m12 = std::stof(strvec.at(1));
  m13 = std::stof(strvec.at(2));
  m14 = std::stof(strvec.at(3));

  getline(ifs, line);
  strvec = split(line, ',');
  m21 = std::stof(strvec.at(0));
  m22 = std::stof(strvec.at(1));
  m23 = std::stof(strvec.at(2));
  m24 = std::stof(strvec.at(3));

  getline(ifs, line);
  strvec = split(line, ',');
  m31 = std::stof(strvec.at(0));
  m32 = std::stof(strvec.at(1));
  m33 = std::stof(strvec.at(2));
  m34 = std::stof(strvec.at(3));

  std::cout << m11 << " " << m12 << " " << m13 << " " << m14 << std::endl;
  std::cout << m21 << " " << m22 << " " << m23 << " " << m24 << std::endl;
  std::cout << m31 << " " << m32 << " " << m33 << " " << m34 << std::endl;

return 0;
}

```
AWS ALB環境下のlaravel-adminにてRequest::ip()が正しく取得出来ずにハマった

PHP7.4系 Laravel5.8 laravel-admin1.8.11の環境において、で正しくクライアントIPが取得出来ず、IP制限やSSL関連挙動が変わってしまった。laravel-admin1.7系では問題無かった為、試行錯誤のメモを残す。

```php5
Request::ip();
```

## TrustProxiesが正しく動かない！？

本来、AWS Elastic Load Balancingを使用している場合、
$headersの値はRequest::HEADER_X_FORWARDED_AWS_ELBに設定する必要があると公式ドキュメントに記載あり。
https://readouble.com/laravel/5.8/ja/requests.html

```php:app/Http/Middleware/TrustProxies.php

<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;

class TrustProxies extends Middleware
{
    /**
     * このアプリケーションで信用するプロキシ
     *
     * @var array
     */
    protected $proxies = '*';

    /**
     * プロキシを検出するために使用するヘッダ
     *
     * @var string
     */
    protected $headers = Request::HEADER_X_FORWARDED_AWS_ELB;
}
```
TrustProxies周りをあれこれ（HEADER_X_FORWARDED_AWS_ELBなど）見てみるが解消しない。

## 原因
コード辿ってdebug_backtraceなどしてみると、どうやらLogOperation関連の挙動がおかしいことに気がつく。

https://github.com/z-song/laravel-admin/compare/v1.8.4...master
laravel-admin 1.8.4リリース時にプッシュされたコードが原因と判明。

（この箇所）
https://github.com/z-song/laravel-admin/commit/95d2cacd46a1429780cc58272d14f8709db3be98


## 解消方法（暫定）

```php:vendor/encore/laravel-admin/src/Middleware/LogOperation.php
    public function handle(Request $request, \Closure $next)
    {
        if ($this->shouldLogOperation($request)) {
            //$setProxy = $request->setTrustedProxies(request()->getClientIps(), \Illuminate\Http\Request::HEADER_X_FORWARDED_FOR); 
            // ↑ここをコメントアウト
            $log = [
                'user_id' => Admin::user()->id,
                'path'    => substr($request->path(), 0, 255),
                'method'  => $request->method(),
                'ip'      => $request->getClientIp(),
                'input'   => json_encode($request->input()),
```

25行目をコメントアウトする事で解消。 
setTrustedProxies が TrustProxies側と重複していると思われる。

取り急ぎGitHubにコメント残しつつ、当該箇所をオーバライドして暫定回避で対応する事とする。


## 環境
PHP: 7.4.14
Laravel: 5.8.38
laravel-admin: 1.8.11
途中の引数のみ取得したい (JavaScript)

# 可読性悪いので利用おすすめしないです

引数が複数あり、どうしても一時変数を使いたくない場合

### 2番目と4番目の引数だけ取得
```js
const getter1 = (...[, getters, , rootGetters]) => { ... }
const getter2 = (...{1: getters, 3: rootGetters}) => { ... }
```

<!--
Chrome 89 DevToolでの実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/973/3ff151c1-b770-b9c5-3941-fdea7ed7a34c.png)

node v10.23.2 での実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/973/e31e185e-d81b-7668-7eaf-7d1c2cbf01b3.png)
-->

# 参考
- [Vuex getters](https://vuex.vuejs.org/ja/api/#getters)
Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう　の環境構築において発生したエラーとその解決法について

#初めに
本記事は、フロントエンドに Vue.js + Vue Router + Vuex とサーバーサイドに Laravel を使用したSPAの開発方法を学べる教材である[Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう](https://www.hypertextcandy.com/vue-laravel-tutorial-introduction/)の環境構築において発生したエラーとその解決方法について述べたものです。
#環境構築
OS：Mac
構築方法：教材にそってDockerを使用

#npm run watch にて画面が表示されない

私の場合`npm run watch`をしても`http://localhost:3000/`になにも表示されなかったのは、バックエンド(Laravel）にて事前にlocalhostを立てていない事が原因でした。そのため別ターミナルを起動してコンテナ上で

```
php artisan serve --host 0.0.0.0 --port 8081
```
とした上で`npm run watch`を行いましょう。

またこの教材はLaravel6までしか対応が保証されていないため、Laravel7 ||  Laravel8の場合にもエラーが発生する可能性があります。そのため、Laravelのプロジェクトを作成する際に教材通りに

```
 composer create-project --prefer-dist laravel/laravel .
```

とするのではなく

```
composer create-project --prefer-dist laravel/laravel .6.*
```
とバージョンを指定することで、エラーをなくす事ができるかもしれません。

#最後に
二つとも超初歩的なことでしたが、環境構築にまだ慣れていないが、Laravelとvueを使ったアプリケーションを作りたい人自分のような人に向けて自分の体験を共有しました。
また、Laravelとvueを使ったSPAの開発の教材として
[【Laravel x Vue.js】SPAクイズアプリケーションを作ってみよう！](https://www.techpit.jp/courses/8)
こちらの教材も素晴らしい教材ですのでぜひ
PHP7.4 - openssl のエラーでハマった件

PHP7.3.11で動いていた Laravle6 のプログラムが、PHPを7.4にアップグレードしたところ、下記のエラーが出た。
Symfony\Component\Debug\Exception\FatalThrowableError
Call to undefined function Illuminate\Encryption\openssl_cipher_iv_length()

内容的には難しくて理解できませんが、openssl とあるので、openssl関連のエラーだろうと思い、phpinfo()で調べてみると、openssl拡張機能そのものが組み込まれていない。

そもそも、公式サイト（https://https://windows.php.net/download#php-7.4）
からダウンロードした Windows パッケージでは、openssl はコンパイル時に組み込まれていないことも判明。

自分でコンパイルするほどの芸はないので、php.ini で extension_openssl を有効化するしかありません。
php.ini-developnent をコピーしてphp.iniを作り、中を見ると、はいはい、ちゃんと無効になっていました。
;extension_openssl
コメントを外して有効化。
extension_openssl

ついでに、extension_dir もコメントアウトされていたので、
;extension_dir = "ext"
外しました。
extension_dir = "ext"

さて Apache2.4を再起動して、phpinfo()で確認すると、、、入っていない！

おかしいな、拡張機能のフォルダは "ext" じゃないのか、そんなはずはないとか、あちこちググった挙句、StackOverflow の次の記事で同じ問題が出ているのを発見しました。
How to enable openSSL in PHP 7.4 with Apache Server 2.4?
https://stackoverflow.com/questions/61919440/how-to-enable-openssl-in-php-7-4-with-apache-server-2-4

この質問者の方は、どうやら自分で解決策を見つけて自己レスされています。
それによると、extension_dir の指定を絶対パスで指定してやるというなんとも単純な話でした。
そこで私も、下記のように変更。
extension_dir = "C:\php-7.4.16\ext"

半信半疑で Apacheを再起動すると、「！」、、正解でした。
mmhmmをWebex desktop appで使う方法

## 課題
以下は Mac での話。Windowsは知らん。

[mmhmm](https://www.mmhmm.app/)というアプリがあって、いい感じにWebカメラに映ったプレゼンターとパワポとかビデオと合成してくれる。これを毎日のWeb会議で使いたい。どうしても使いたい。

mmhmmは合成した映像を、仮想カメラとして出力するので、仮想カメラに対応しているWeb会議ソフト ([Zoom](https://zoom.us/)とか[Google Meet](https://workspace.google.com/products/meet/)とか)は、仮想カメラを物理カメラの代わりに選択すれば目的を達成できる。っていうか、mmhmmは、そのために作られたソフトだ。

しかし、[Cisco Webex](https://www.webex.com/ja/index.html)って奴は、セキュリティー上の問題[^1]とやらで仮想カメラを断固として受け付けない[^2]。

[^1]: 多分だけど、https://help.webex.com/ja-jp/WBX9000032849/Virtual-Camera-Driver-Stopped-Working-After-a-Site-Upgrade なのかな。
[^2]: 正確には、Webexのクライアントには２種類あって、ブラウザのプラグインとして動く web app とネイティブアプリの desktop app があって、web app では仮想カメラが使える。じゃあ問題ない・・・ことはなくて、Webexの会議の種類によっては、desktop appしか使えないことがある。なんでなんだ！ I hate Webex!!

じゃあ Zoom を使えばいいじゃなイカ・・・ところが、会社やお客が Webexを指定してくるんで、どうしても Webex を使わなければならないのだ。

そのうち mmhmm が Webex に対応してくれるかな・・・と気長に待っていたのだが、待てど暮らせど治らない。2021年の頭だったかに、一瞬使えるようになって喜んでいたら、Webexがアップデートされて、また使えなくなっちまったようだ[^3]。

[^3]: [Googleのキャッシュ](https://webcache.googleusercontent.com/search?q=cache:5fMbM7y7QMcJ:https://www.mmhmm.app/jp/blog/mmhmm-now-works-with-the-mac-os-webex-desktop-app+&cd=2&hl=en&ct=clnk&gl=jp)に、mmhmmから2021年２月20日付で出されたBlog記事が残っていた。その記事によると mmhmm が webex desktop app に対応したとあるが、その後、このBlogは消去されている。

痺れを切らして、ついにガジェットを一つ足すことで、dual display の Mac 1台で、安易な解決策を実装した。まあ、金で解決ってやつかな。自明な解だけど、もしかして気がつかない人もいるかと思い、以下に紹介します。

## 解決方法
### ソフトウェア
使いたいアプリ mmhmm は https://www.mmhmm.app/ からダウンロードしてインストールしておく。
さらに、Open Broadcaster Software (OBS) を https://obsproject.com/ からダウンロードしてインストールしておく。

### ハードウェア
まず HDMI capture device を手に入れる。私が使ったのは [I-O DATA HDMIキャプチャーボード GV-US2C/HD](https://amzn.to/3vvn9hD)。Amazonで 17,050円でした。安い方 [I-O DATA HDMIキャプチャーボード GV-USB3HD/E](https://amzn.to/3cSNCgX)でも、[こういう](https://amzn.to/3f4PHZI)ような、もっと安いやつでも良かったかも。

Macと外部ディスプレイとHDMIキャプチャボードを、次の図のように接続する。

![スクリーンショット 2021-03-17 2.18.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223481/2d0ce5a2-ce53-811b-a614-d5fe3e8f49fb.png)

つまり、外部ディスプレイへの出力をHDMIキャプチャボードを通してディスプレイに繋ぎ、それをUSBに変換してMacに戻す。

### 設定&使い方。
1. mmhmm を起動して、好きなように設定する。カメラはホントの物理カメラを選んでおこう。
2. OBSを起動して、ソースの＋ボタンを押して、mmhmmの仮想カメラを映像キャプチャデバイスとして追加する。すると、OBSのモニタウィンドウにmmhmmの出力が出てくる。
3. そのOBSのモニタウィンドウを副ボタンでクリックしてメニューを出し、全画面プロジェクター > 外部ディスプレイ を選ぶ。すると、外部ディスプレイ全面に mmhmm の出力が表示される。
4. この外部ディスプレイへのHDMI出力は、HDMIキャプチャボードによって、物理カメラ入力としてUSBに送られているんだった。
5. その物理カメラをWebex appでカメラに選べば良い。

論理的な接続関係を図示すると、次のような感じ。

![スクリーンショット 2021-03-19 9.43.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223481/ba4c5250-0d9e-d50f-6ccd-2ac7392ac0b3.png)

ついでに、Webexの画面シェアで、外部ディスプレイの画面をシェアすると、ビデオスクリーンにもシェア画面にも同じスクリーンが映るんで、あとはmmhmmで好きにプレゼンすれば良い。

MacのCPU cycleを結構使うので、遅いマシンだと映像の遅れが激しくて使い物にならないので、スペック高めのMacを使ってください。

## 結論
mmhmmってOBSみたいなソフトを使わずに、気軽にかっこいいWebプレゼンを行うツールだったはずなのに、たかがWebexを使うために、ハードを買った上に、OBSまで使ってて、何やってんだかわからないな。とほほ
【輪読会】Javaでもう一度学び直すオブジェクト指向プログラミング vo.1

# 第1章 オブジェクト指向への再入門

# オブジェクト指向プログラミングの特徴

- 小さいプログラムを作る時は別にどのような書き方をしても構わない
	- 小さいサービスと大きいサービスの違いは？
	 - 大体、最初作る時は全て小さいだろう。そんな時はあまりオブジェクト指向を意識しすぎないでも良い。
	機能追加などを経て大きくなっていく時にリファクタリングしながらオブジェクト指向の設計にして行けば良い。
	最初は手続き型で初めて行く形で良いと思う。

## クラスとインスタンスで「似て非なるもの」を簡単に作る

- よく似ているが少し違うものとは？
　商品クラスというものがあったとしたら、お客さんによって商品は異なるので商品A、商品Bと異なるインスタンスができる

- クラスとインスタンスというのが初学者はイメージがしづらい
　そもそも抽象的なものだから「これ」と定義づけるのが難しい。ここではクラスからインスタンスができるくらいに考えておいてまた後のコードで掴んで行くのが良いと思う。


### クラスとインスタンスがない場合

- 手続き型プログラミングとなる
- サブルーチンとは？
　関数。

- モジュールとは？
　単純にいうと部品。クラスとよく似たもの。
　でもイメージしにくい。別途、調べる。



## 異なるクラスを同じように扱う
異なるクラスを同じ種別のクラスとして扱う。

例、じゃんけんの「戦略」をクラス化した場合

- 同じ手しか出さないクラス　
    - クラス名「同じ手クラス」
- 順番な手にするクラス
    - クラス名「順番手クラス」
- ランダムな手にするクラス
    - クラス名「ランダム手クラス」
- 上記を統括するじゃんけんの手を出すクラス
    - クラス名「手を出すクラス」
があったとする。

それぞれのクラスは異なるが、共通しているのはじゃんけんの「手」というところである。
「手を出すクラス」としてはじゃんけんの「手」を出すことが出来れば良いので、「手」を返してくれる振る舞いを持つクラスであれば、どんなクラスでも問題はない。

ただ、この時点ではなぜ「戦略」をそれぞれ異なるクラスとして持つのか、メリットなどがまだ見えてこない。
この後の章でカプセル化、ポリモーフィズム、継承が出てくるのでそこでまた議論をしていく。


# ps.弊社、輪読会を始めました。
昨年末から@fumiya-uehara @yamauchi_kkk と輪読会をしたいねと話をしていたのですが、緊急事態宣言でリモートになり一時中断。
解除後に運用ルールや第一回のテーマ選定などをしながら進めていき、本テーマで参加者を募集したところ4人のメンバーが集まり計7人でスタートを切りました。
輪読会をしたことがないメンバーなので手探りで進めていますが、読み終えると言うことよりも議論に重点を置いて進めてます。
週二回で進める予定ですが、水曜は既にランチ勉強会を行っているので、週の半分はお昼休みに集まって何かしらやってますw
できるなら毎日やりたいところですが、まずは定常的に運用していくことを目標として進めていきます。
docker statsが終わらない

<h2>docker stats

すごいスピードでログが出力されていく。Ctl+Cで出力を止める事ができる。数分でも放置すれば、以前の操作を確認するために、スクロールをずーとし続ける目に遭う。

<h2>解決策

これで一度だけ出力するようになります。

```
docker stats --no-stream
```
Flutter AlertDialogの幅を画面いっぱいに引き伸ばす


### AlertDialogの幅を画面いっぱいに引き伸ばしたい
もともとは通常の画面だったものを、ダイアログ化してほしいと言われ、
ダイアログ化したのだけど、どうにも窮屈な感じになってしまっていたので、
ダイアログのパディングを減らしてほしといわれたが、ちょっと詰まった話。

### 通常のAlertDialog
通常Dialogを表示する場合は下記のようなコードになると思います。

~~~ dart
showDialog(
  context: context,
  builder: (context) {
    return AlertDialog(
      title: Text('タイトル'),
      content: Text('メッセージ'),
      actions: [
        ElevatedButton(
          onPressed: () => Navigator.pop(context),
          child: Text('キャンセル'),
        ),
        ElevatedButton(
          onPressed: () => Navigator.pop(context, 'OK'),
          child: Text('OK'),
        ),
      ],
    );
  },
);
~~~

実行時の画像
<img width="250" alt="通常のAlertDialog" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106405/f78b989e-35a8-5da7-7d98-28f44f021b76.jpeg">


上記コードの `content`部分を次のように変更

~~~ dart
content: Container(
  width: 400,
  child: Text('メッセージ'),
),
~~~

実行時の画像
<img width="250" alt="content,width400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106405/ce8184bb-ebe1-2440-7c31-42baa4d83bd4.jpeg">

何も変わっていない！！
原因はでAlertDialogにはデフォルトでマージンが設定されていることだった。
下記のように`insetPadding`を設定することで問題なく幅を広げることができた。


~~~ dart
showDialog(
  context: context,
  builder: (context) {
    return AlertDialog(
      insetPadding: EdgeInsets.all(8),
      title: Text('タイトル'),
      content: Container(
        width: 400,
        child: Text('メッセージ'),
      ),
      actions: [
        ElevatedButton(
          onPressed: () => Navigator.pop(context),
          child: Text('キャンセル'),
        ),
        ElevatedButton(
          onPressed: () => Navigator.pop(context, 'OK'),
          child: Text('OK'),
        ),
      ],
    );
  },
);
~~~


実行時の画像
<img width="250" alt="insetPadding_override" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106405/6a951487-28db-bd93-aa8e-4ac8a2078fab.jpeg">

無事ダイアログの幅を広げることができた。
DartサーバをDockerで実行するときはdistrolessイメージを使う

## distrolessを使う理由

理由は2つ。

- サイズが16.86MB[^1]程度と大きくない
- Dartバイナリの実行に必要なglibcが入っている

## Dockerfileの記述例

```dockerfile
FROM google/dart:2.12 as builder
WORKDIR /app
ADD pubspec.* /app/
RUN pub get
ADD . /app
RUN pub get --offline
RUN dart compile exe bin/server.dart -o bin/server

FROM gcr.io/distroless/base
WORKDIR /app
COPY --from=builder /app/bin/server .
CMD []
ENTRYPOINT ["./server"]
```

distrolessイメージではDartのコンパイルはできないので、マルチステージビルドにする。google/dartイメージでDartファイルをバイナリにコンパイルし、distrolessイメージにバイナリをコピーして実行する。

"bin/server.dart"は、Dartサーバのmainエントリを含むファイル。

### 補足

shellを使いたいのであればベースイメージを"gcr.io/distroless/base:debug"にする。このイメージには、BusyBoxが入っている。これでもlddコマンドは入っていないので、使いたければgoogle/dartイメージの/usr/bin/lddをCOPYする。

## 他のDockerベースイメージについて

| ベースイメージ | 説明 | サイズ[^1] | 不採用の理由 |
| ---- | ---- | ---- | ---- |
| google/dart | Dartのビルドツールが入っている。 | 682.73MB | サイズが大きい。 |
| frolvlad/alpine-glibc | glibc入りalpine。　| 17.92MB | 実行はできるが、lddでDartをコンパイルしたバイナリをチェックするとエラーがある。 |
| subfuzion/dart:slim | scratchベース。dartの実行に必要なsoファイルをgoogle/dartからscratchイメージにコピーしたもの。　| 4.3MB | それほどテストはしていないらしい[^2]。 |

## サンプルアプリ

https://github.com/KamikazeZirou/dart-server-sample?w=1&ts=4

[^1]: Docker Hub上の圧縮されたサイズでなく、pullしたあとのサイズ。イメージのバージョンによりサイズは異なる。ここに示した値は目安程度。
[^2]: https://github.com/dart-lang/dart_docker/issues/50?w=1&ts=4#issuecomment-719106313
【Docker】mysql学習用環境をローカルに爆速で構築する

# はじめに
MYSQLを学習するための環境をdockerで構築する。
データを自前で用意するのは非常に面倒だが、公式で
サンプルデータとして、[worldデータベース](https://dev.mysql.com/doc/index-other.html)が提供されているので
そのデータを使用してデータベースを構築する。

# 環境構築
以下のファイルを作成

```Dockerfile:Dockerfile
FROM mysql:5.7

RUN apt-get update && apt-get install -y \
    curl unzip

RUN curl -OL https://downloads.mysql.com/docs/world-db.zip

RUN unzip world-db.zip

RUN mv world-db/world.sql docker-entrypoint-initdb.d/world.sql 
```

```yml:docker-compose.yml
version: '2'
services:
  mysql:
    build: .
    tty: true
    working_dir: /mnt
    volumes:
      - ./:/mnt/
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: test
```

## 起動コマンド(~コンテナログイン)
```bash
docker-compose up -d
docker-compose exec mysql bash
```
## mysqlログイン~テーブル確認
```bash

mysql -uroot -proot
```
```sql
use world;
select * from city;
```
以下のように出力されていれば構築完了です。

```
+------+-----------------------------------+-------------+----------------------+------------+
| ID   | Name                              | CountryCode | District             | Population |
+------+-----------------------------------+-------------+----------------------+------------+
|    1 | Kabul                             | AFG         | Kabol                |    1780000 |
|    2 | Qandahar                          | AFG         | Qandahar             |     237500 |
|    3 | Herat                             | AFG         | Herat                |     186800 |
|    4 | Mazar-e-Sharif                    | AFG         | Balkh                |     127800 |
|    5 | Amsterdam                         | NLD         | Noord-Holland        |     731200 |
|    6 | Rotterdam                         | NLD         | Zuid-Holland         |     593321 |
|    7 | Haag                              | NLD         | Zuid-Holland         |     440900 |
```


# 最後に
mysqlを学習するための環境をdockerを用いて構築してみました。
わからないことなどあれば気軽にコメントお願いいたします。
CUDA, Python対応したdlibを入れる

# 概要
下記の良記事とやってる内容はほぼ同じですが、pip で少しだけ手順を簡略化。

https://qiita.com/FXsimone/items/4864ff695d7599491ca8

違いとしては

+ CUDA のインストールは、ubuntuの場合 ```apt``` でやる
+ dlib のコンパイルは ```pip``` でやる
+ gcc-8 を使う （cuDNN8 が gcc-9 以上に対応してなかったため）

# 依存パッケージのインストール
まずは CUDA などをインストールする。Ubuntuでは

```
sudo apt install nvidia-cuda-toolkit cmake gcc-8
```

次に、cuDNN をインストールする。```apt``` で導入できないので、[公式サイト](https://developer.nvidia.com/rdp/cudnn-archive)から入手する。上で入れた nvidia-cuda-toolkit のバージョンを確認し、それに対応した deb パッケージをダウンロードしてインストールする。例:

```
sudo dpkg -i libcudnn8_8.0.5.39-1+cuda10.1_amd64.deb libcudnn8-dev_8.0.5.39-1+cuda10.1_amd64.deb
```

（Ubuntu以外では別の方法に適宜変えてください。）

# dlib のコンパイルとインストール
Python の ```pip``` でやる。

```
CC=gcc-8 python3 -m pip install --verbose --force-reinstall --no-binary :all: dlib
```

（verbose は無くても良いけど、ログ確認用に一応付けた。）

# 確認
python を起動して以下を入力する。

```
>>> import dlib
>>> dlib.DLIB_USE_CUDA
```
```True``` が返るはずだが、もし何か失敗して cuda が無効なら ```False``` が返る。

# 余談
+ Ubuntu の libdlib-dev とかと両方入れたらどうなるかは確認してない
+ メインで使っている Arch Linux 向けの手順も書こうと思ってたけど、既に [python-dlib-cuda]( https://aur.archlinux.org/packages/python-dlib-cuda/) パッケージがあった
brew caskコマンドの変更

# はじめに
brew cask install xxxでGUI Applicationをインストールしようとしたら，Unknown commandと表示されてしまいました．原因として，コマンドの変更があったようなのでメモしました．

# brew caskコマンドによるインストール
以前のコマンド

```

brew cask install xxx 

```

変更後のコマンド

```

brew install xxx --cask

```
S3 select とは

## 勉強前イメージ

s3のデータをselect出来るっぽい名前してる。
でもそれだったらAthenaとの違いは？

## 調査

### s3 select とは

S3バケット内に保存したオブジェクトに対し
SQL文を用いてデータの一部分を取り出すことができるサービスです。

### 使い方

- 事前準備

s3バケットに以下のCSVファイルをアップロードしておきます。

```text:test.csv
"Name", "Birthday", "Score"
"Sato", "02/03", 24
"Suzuki", "05/12", 29
"Takahashi", "10/06", 14
"tanaka", "5/2", 19
```

- S3 Select に進む

s3バケットからselectしたいファイルを選んで、
アクション > S3 Selectを使用したクエリ に進みます

![1S3 Management Console - Google Chrome 2021-03-16 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/98c01be6-df05-3718-4ec0-55b7b5d7efcb.png)


- select の詳細を記載

![2S3 Management Console - Google Chrome 2021-03-16 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/50ba84da-4537-e92a-84f9-810a6edde172.png)


![3S3 Management Console - Google Chrome 2021-03-16 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/fb53a12c-faed-77ea-8d6c-236e588401de.png)


- 実行(デフォルト)

SQLクエリには、まずデフォルトで入っていた以下のクエリを実行します。
`SELECT * FROM s3object s LIMIT 5`

するとすぐ下にクエリ結果が出てきます。

![4S3 Management Console - Google Chrome 2021-03-16 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/3dc44c05-c7a1-75ce-fe70-d7e6dd28bfed.png)


- 実行(select文記載)

それでは次に、以下にデフォルト以外のselect文を記載して実行してみます。
`SELECT Name FROM s3object s LIMIT 2`

簡単なクエリであればこれで実行することが出来ます。

![5S3 Management Console - Google Chrome 2021-03-16 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/51d6d118-c5e2-dc0b-aecc-cd28620b07b5.png)

### Athenaとの違い

同じs3のオブジェクトの中身を実行することが出来るサービスとして、Athenaがあります。
Athenaとの違いとしては以下です。

- S3 Select
	- 単一ファイルのみ実施可能(複数ファイルは不可)
	- 機能が少ない

- Athena
	- 複数ファイルを対象(ディレクトリごと)
	- クエリ機能も充実

大規模なログとかselectするなら、Athenaで
ちょっとしたファイルを検索したいなーくらいだったらS3 Selectを使うって選択肢になりそう。

## 勉強後イメージ

今までAthenaしかないと思ってたけど、s3でもselect出来るのか・・・
正直あまりユースケースが思い浮かばないけど、どんなときなんだろう

## 参考

- [Amazon S3 Select を使用して、サーバーまたはデータベースなしでデータをクエリする](https://aws.amazon.com/jp/blogs/news/querying-data-without-servers-or-databases-using-amazon-s3-select/)
- [Amazon S3 Select と S3 Glacier Select の SQL リファレンス](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/s3-glacier-select-sql-reference.html)
- [AWSコンソールからS3 Selectを使ってみた](https://dev.classmethod.jp/articles/s3-select-with-console/)
【レガシー用語】「ZIPファイル解凍しておいて」が通じない世界

# はじめに
この記事は30代以上をターゲットにしています。
一緒にレガシー用語から脱却しましょう！

# 「ZIPファイル解凍しておいて」が通じない世界
エンジニア仲間のたじーゆから**「会社の後輩にZIPファイル解凍して～って言ったら何言ってんのみたいな顔されて伝わらなかった」**というエピソードを聞きました。

ん？最近の若い子はZIPファイルもまともに使ったことないのか！これだから最近の若者は・・・などと思っていたら違いました。

なんと今の若い子は**「解凍」**のことを**「展開」**と言うそうです。
それどころか**「解凍」**なんて言葉を冷凍食品以外に使わないとか。
確かに**「展開」**とも言うよなーと思ってネット検索してみたら

https://forest.watch.impress.co.jp/docs/serial/yajiuma/759537.html

こんな穏やかじゃない記事を見つけました。

今の若い子は**「解凍」**のことを**「展開」**と言う

ではなく

おじさんおばさんは**「展開」**のことを**「解凍」**と言う

上記の可能性が出てきました。
真偽を確かめるべく急いでGoogle検索

まずは**「ZIP　解凍」**で検索っと・・・

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/174aa4c9-5f7e-956e-497e-bfb8c7df1ba5.png)

約 7,220,000 件！！ かなりの件数がヒットしますね。ちょっと安心しました。

一応念のため**「ZIP　展開」**でも検索っと・・・

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/945f4d2d-85ea-23c0-a30d-63a0f55fdb9f.png)

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/46c3493f-e80d-2720-1769-c31b2fd1a235.png)

![onepiece14_enel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/37e61560-b2e1-ce25-e53b-d5e423897ba4.png)
（[いらすとや×ONE PIECE](https://www.irasutoya.com/2021/01/onepiece.html)）

|ZIP 解凍  |ZIP 展開  |
|---|---|
|7,220,000|23,300,000|

7百万件と2千3百万件・・・桁が違いました。3倍です。

ここ最近の傾向としてはどうかとGoogle検索で**「1年以内」**として再検索

|ZIP 解凍  |ZIP 展開  |
|---|---|
|132,000| 5,790,000|

よ、43倍！！

圧倒的に時代は**「展開」**を支持しています。
少し調べてみるとWindowsXPの時代から既に**「展開」**らしいです。
（それ以前は調べていません）

ということでみなさんZIPファイルは**「展開」**しましょう！
くれぐれも**「解凍」**と言わないように！
※圧縮展開ソフトの**「Lhaplus」**を右クリックしたら出てくる**「解凍」**の選択肢も気合で**「展開」**に見えるようになってください。

あ、ついでにスマホの写真のことも**「写メ」**とか言っちゃダメですよ？
逆に「大丈夫オレはナウでヤングだから」ってオラついている人も若い子相手に**「ぴえん」**とか使わないでくださいね！
両方おじさん認定されちゃいます。

# 余談
念のため自分のWindowsPCでZIPファイルを右クリックしてみたら

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/0e333201-abaf-2a5a-ef5b-348dc29f0405.png)

となってました。
私はALZip派だから間違えていたんですね。良かったおじさんだからじゃない。

ぴえん
MySQL8のバックアップ

# はじめに
開発環境側のmysqlデータ消しちゃって、あー、たしかにダンプまとめとかないとなぁ～って思って

# ダンプファイル作成
[パスワードを入れてmysqlコマンドを実行すると「Warning: Using a password on the command line interface can be insecure」が表示される](https://resource-sharing.co.jp/mysql-command-password-warning/)

```console:Console
# cd ~
# vi mysql-dbaccess.cnf
```
```vim:mysql-dbaccess.cnf
[client]
user = root
password = MYPASSWORD
```
```console:Console（ぜんぶdump）
# mysqldump --defaults-extra-file=mysql-dbaccess.cnf -h localhost portfolio_db > ~/mysql_dump.sql
mv mysql_dump.sql /home/ubuntu
```

## 自動化
https://leben.mobi/blog/mysql_auto_backup/linux/
```console:console
# mkdir -p /var/backup/mysql-dump
# cd /var/backup/mysql-dump
# vi mysql-backup.sh
```
```shell:mysql-backup.sh
#!/bin/sh

# -------------------------------------------------------
#
# [環境設定]
#

# バックアップファイルを保存するディレクトリパス
dirpath='/var/backup/mysql-dump'

# バックアップを保存する日数
period=14
# -------------------------------------------------------

#
# [バックアップ取得処理]
#
# ファイル名を定義  ※「mysql-dump-yyyymmdd.sql」となるようにします
fileprefix="mysql-dump-"
filedate=`date +%Y%m%d`
filename=$fileprefix$filedate

# mysqldumpを実行しdumpファイルを出力
mysqldump --defaults-extra-file=~/mysql-dbaccess.cnf -h localhost portfolio_db > $dirpath/$filename.sql --no-create-
info --skip-add-drop-table --ignore-table portfolio_db.register_user

# 出力されたdumpファイルのパーミション変更
chmod 700 $dirpath/$filename.sql

#
# [ローテーション処理]
#
# 削除対象年月日を取得
olddate=`date --date="$period days ago" +%y%m%d`

# 削除対象ファイル名を生成
oldfile=$fileprefix$olddate

# 削除実行
rm -f $dirpath/$oldfile.sql
```
```console:シェルスクリプト実行
# cd /var/backup/mysql-dump
# sh mysql-backup.sh
```

## crontab
```console:console
# export EDITOR=vi
# crontab -e
  0 2 * * * /var/backup/mysql-dump/mysql-backup.sh

# chown -R ubuntu:ubuntu /var/backup/mysql-dump
# ls -l
  total 37476
  -rw-r--r-- 1 ubuntu ubuntu     1076 May 31 23:56 mysql-backup.sh
  -rwx------ 1 ubuntu ubuntu 38368295 Jun  5 12:08 mysql-dump-20220605.sql
```

# ローカルへ転送
/home/ubuntu にあるダンプファイルをFTPかなんかでローカルに引っ張ってください。いまは自動化は考える余裕ないわ

# MySQLにインポート
[powershellでmysqlコマンドでsqlをインポート](http://blog.livedoor.jp/kmiwa_project/archives/1076293743.html)

```console:console(CentOS,Windows)
dev\Portfolio> mysql -u root -p portfolio_db
mysql> source mysql_dump.sql
```
```console:console(Ubuntu)違いがよくわからん
# mysql portfolio_db < mysql_dump.sql
```

point
dumpはSQLを実行するだけなので、例えば「サーバーよりも開発環境のほうがテーブルが追加されている」状態でdumpをインポートしても、新しいテーブルがあるままドスッと過去データが入る（あ、だめっぽい。ダンプファイルのCreate文調整してくれ）
Java言語について調べてみた

今回は、一番人気と言っても過言ではない言語(1991年〜現在にわたり非常に人気な言語)**「Java」**について調べてみた。


#Javaについて
・Java仮想マシン(JVM)で動くため、どのような環境でも動かすことができる。
・オブジェクト指向言語である。
・Androidアプリやゲーム開発、WebアプリやWebサイトまで万能にこなす。
・有名なゲームの「マインクラフト」もJavaで作られている。
・セキュリティ面も優れている。
・みずほ銀行や三菱UFJ銀行などのシステムを開発できるくらい優れている。



##メリット
**実行速度の速さ**。理由はJavaがコンパイラ型言語であること。
**ライブラリがとても充実している**。よって開発もしやすい。
**プラットフォームに依存しない**。これは非常に大きなメリット。
**言語として高性能**。その反面、学習難易度が高め。

　
　

##デメリット
**JVM**が入っていないパソコンだと機能しない。
**マイコン**にはJavaは組み込めない。(マイクロコンピュータの略で主に家電に使われている。)
**習得にはかなりの時間と労力が必要**。

　

##Javaの資格
**Oracle認定Javaプログラマ**
この資格を取得できれば、どこでも通用する。
その他数々の資格有り。


###まとめ
非常に万能な言語なだけあって習得には大変時間がかかるそうで..。
実際に触れる事は恐らくないと思うが、取得できればすごく可能性の幅が広がって楽しそうだと思った。
学生の頃に戻りたい！そしてJavaを勉強したかったと思った今日この頃。
【Vue.js】Vue.jsをはじめて学びました

Vue.js について、社内ではじめて学ぶ機会がありました。
そこで学んだことの振り返りとまとめです。

# 学んだ事いろいろ
　参考文献：動かして学ぶ！Vue.js開発入門  翔泳社
![スクリーンショット 2021-03-17 21.56.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594740/465638fc-ed4a-e970-2986-23d722562857.png)


## 用語関連

### MVVM

Model-View-ViewModelの略。
「Model（Vue内に用意したデータ）」と「View
（HTMLで表示している要素）」と「ViewModel（それらをどのようにつなぐか）」
で考えていく方法

### SPA（シングルページアプリケーション）
1枚のWebページにいろいろな機能を用意して、
1枚のページだけで動くWebアプリケーションのこと

### システム修飾子キー 
イベントにシステム修飾子キーを追加すると、システム修飾子キーを押しながら
キーが押されたとき（またはクリックされたとき）にだけメソッドが呼ばれるようになる

### 双方向データバインディング
VueインスタンスのデータがWebページ上に表示され、Webページ上から入力さ
れた値がVueインスタンスのデータに反映されること

### ディレクティブ
「要素に対して Vueがどんなことを行うかを指示する命令」のこと


### マスタッシュ
マスタッシュ（Mustache）とは、口ひげという意味　
`{}` をマスタッシュタグと言う


## 便利な機能

### 論理演算子

`myAgree==false`を`!myAgree`と書くことができる

```html
<button v-bind:disabled="myAgree==false">送信</button>
OR
<button v-bind:disabled="!myAgree">送信</button>
```

### `v-if`と`v-show`

- `v-if` :HTMLから要素が削除される
- `v-show` :CSSスタイルのdisplay: noneで見えなくしている

### 配列操作

- 配列の末尾にデータを追加する

```javascript
var myArray = [1,2,3,4,5];

myArray.push(100);

// myArray = [1,2,3,4,5,100]
```
- 配列の途中にデータを追加する

```javascript
var myArray = [1,2,3,4,5];

myArray.splice(1, 0, 100);
// myArray = [1,100,2,3,4,5]
```

- 配列の途中にデータを削除する

```javascript
var myArray = [1,2,3,4,5];

myArray.splice(1, 1);
// myArray = [1,3,4,5]
```

### アニメーション
- transitionタグを使う  

Enter/Leave とトランジション一覧

  https://jp.vuejs.org/v2/guide/transitions.html
マイ記事まとめ　〜Notionの使い方

#はじめに
Notionについての記事をいくつか書いてきたので、
ここでまとめようと思います。

##ショートカット

[Notionでもショートカットを使って、効率爆上がりを目指す](https://qiita.com/TerToEer_sho/items/6e4902c0d755bb18db3a)

[ちょっとニッチなNotionのショートカット
](https://qiita.com/TerToEer_sho/items/5d65da0affc0cce72909)
[ちょっとニッチなNotionのショートカット②
](https://qiita.com/TerToEer_sho/items/69fc3680fdf43431189e)
[ちょっとニッチなNotionのショートカット③
](https://qiita.com/TerToEer_sho/items/152bc7104b5c20e79aef)
[使ってる？Notionのリマインダー機能！](https://qiita.com/TerToEer_sho/items/22665f0ebe2a4557b807)

[Notionで＠を使ったショートカット](https://qiita.com/TerToEer_sho/items/344f568c6eebd03cbe79)


##エンジニア向け、コードのストック

[コードのストックはNotionが最適解！？](https://qiita.com/TerToEer_sho/items/0256ec5289c7f169454b)

[プログラミングの学習初期からNotionでコードをストックしていたら、その軌跡で成長を感じられただろうな（後悔）](https://qiita.com/TerToEer_sho/items/d423f7add7d07875e48d)

[NotionにQiitaのストックをストック、かつ、様々なWebページも一元管理](https://qiita.com/TerToEer_sho/items/a33366b09fdba72fc12e)

##日常使い
[Notion使って、日々の支出を記録](https://qiita.com/TerToEer_sho/items/aa278efaf8fd3535bc22)

[Notionでレイアウトするときに必須のテクニック](https://qiita.com/TerToEer_sho/items/68d977cef6ac02664792)

[Fast Notionで簡単にメモを取る方法](https://qiita.com/TerToEer_sho/items/fb196005c88811128394)

[Notionで日記をつけよう](https://qiita.com/TerToEer_sho/items/4963a568fd0faf0b5a6b)
【注意！】Rubyの全角スペースが原因のエラー


## 概要

Ruby課題を解いていたときに、`syntax error`が出て解決するのに数時間かかった。
結論から言うと、全角スペースが原因だった話。


##書いたコード

さて、どこが原因でしょうか？！
(エディタではなく、Qiitaで見ると分かりやすいですね。）

```ruby:trip_main.rb
# 旅行プラン
plans = [
  { place: "沖縄", price: 10000 },
  { place: "北海道", price: 20000 },
  { place: "九州", price: 15000 }
]

disp_plans(plans) #プランの表示
chosen_plan = choose_plan(plans)　#プランの番号を選択
person_num = num_of_people(chosen_plan) #予約人数を入力
calculate_price(chosen_plan, person_num) #合計料金を表示
```


## エラー文

```ruby:error.rb
trip_main.rb:11: syntax error, unexpected local variable or method, expecting end-of-input
...en_plan = choose_plan(plans)　#プランの番号を選択
```
はい、よく出るエラー文ですね。
`syntax error, unexpected local variable or method, expecting end-of-input`
これに悩まされた人も多いでしょう。



11行目で、構文エラーが出ており、予期していないローカル変数やメソッドがありますよ。
endをください、と言ってます。
ただ、ここでエラー内容を見るのを止めないでください。むしろその次が重要です。

私は、`chosen_plan`のスペルミスか？
`choose_plan(plans)`のメソッド処理内容があかんのか？
必死になって見てましたが、

```ruby:error.rb
...en_plan = choose_plan(plans)　#プランの番号を選択
```
はい。`choose_plan(plans)`とコメントアウトの間に、全角スペースがありますね。
これが原因だったわけです。


## 同じ過ちをしないために

全角スペースが知らぬ間に紛れないように、可視化する方法があります。
`VSCode`を使用している人は、拡張機能の検索画面から`「zenkaku」`を検索して、インストールしましょう。
詳しくは[こちら](https://parottoblog.com/vscode-look-space)を参考にしてください。

全角スペースは、灰色の四角のハイライトで表示されるようになるので、これでOK！

## まとめ

後々、冷静になってエラー内容確認したら全角のところに`＿`（アンダーバー）が書かれてた。
エラー文から逃げずに、しっかり向き合いましょう。


## 参考記事
[VSCodeで半角スペースと全角スペースを可視化する方法【インストールしたら必ず設定】](https://parottoblog.com/vscode-look-space)
[【Tips】Rubyソースコード内の全角スペースについて](https://qiita.com/GandT/items/75c346680177d21d6d15)
【合格後の追記有】Java Silver 覚えられんやつメモ

2021/4/13 追記
71％で受かりました。

受験に用いたのはeclipse、黒本、紫本です。
勉強法は、
・紫本を半分くらい読む
・(紫本読むのがつまらなさ過ぎて)黒本をわからないなりに、答えを参照しながら1周解く(模擬試験除く)
・黒本2周目は1章ずつ解いてから答えを参照、プラスで紫本も参照。適宜コードを書いてデバッグモードも使いながら動作確認。
・紫本模試第1回、黒本模試第1回、紫本模試第2回、黒本模試第2回、黒本模試第1回、黒本模試第2回の順で解く
・試験前日に苦手なとこだけ再確認

という感じです。黒本模試は84%ぐらい取れてたと思います。

試験当日は80分ぐらいで一通り解き終わり、手応え的には60%前後は確実に取れてて、多分見直ししても変わらんなぁという印象だったのでそのまま解答終了しました。

感想としては黒本で見たことある問題がたくさん出てマジか　と思ったので、これから受験する方は黒本模試をベースに考えるといいかと思います。

以下のメモも参考になれば幸いです。

---

試験6日前に、2か月前にキックオフしたプロジェクトの基本設計フェーズに突然ぶち込まれ、試験前日の土曜日の出勤が確定して勉強時間の確保ができないこと間違いなしな状態になってしまったので、今まで勉強してきて見たことあるけどイマイチ頭に入ってきてなかった部分をざっと見返せるものを作って直前に詰め込もうと思いました。

Java SE11 Silverの受験を控えている方の参考にもなれば幸いです。
(黒本のまとめ問題を参考にしている&自分用なので、順番とか整理してません。)

## String型の同値判定
- ==はインスタンスの参照が同じかどうかを判定している。
- リテラルとして記述した文字列は、基本的に使いまわされる。
- `intern`メソッドはすでにメモリ上にあるString型オブジェクトへの参照を戻す。

```java
public class Main {
	public static void main(String[] args) {
		String s1 = new String("java"); //新規オブジェクト
		String s2 = "java"; //リテラル(コンパイル時に定数となる)
		String s3 = s2.intern(); //s2の参照と同じもの
		System.out.println((s1 == s2) + ", "); //false
		System.out.println((s2 == s3) + ", "); //true
		System.out.println((s3 == s1) + " "); //false
	}
}
```
```java
public class Main {
	public static void main(String[] args) {
		String s1 = "java";
		String s2 = new String("java");
		String s3 = s2.intern(); //"java"というリテラルの参照を戻す
		System.out.println((s1 == s2) + ", "); //false
		System.out.println((s2 == s3) + ", "); //false
		System.out.println((s3 == s1) + " "); //true
	}
}
```

## varによる変数宣言
- ローカル変数の初期化時
- 拡張for文内のインデックス
- 通常for文内で宣言されたローカル変数
- try-with-resourse文内のローカル変数(問題で見たことない)
上記4つに限定されている。

- メソッドの引数
- コンストラクタの引数
- メソッド戻り型
- フィールド(メンバ変数)

などでは使用できない(コンパイルエラー)

## 配列の初期化と宣言
(変な宣言のしかたするなよ・・・)

- 1次元目の要素数の宣言は省略できない。`int[] ary = {}`は1次元目に要素0の配列を作成しているのでOK


- 要素数の指定と初期化の両方を使用した配列の作成はコンパイルエラー
こういうやつ→`int[] ary = new int[2] {10,20}`

## アクセス修飾子
| 修飾子 | 同クラス内 | 同パッケージ内 | サブクラス内 | どこでもok |
|:-:|:-:|:-:|:-:|:-:|
|  private | 〇  |   |   |   |
|  (なし) |  〇 | 〇  |   |   |
|  protected |  〇 | 〇  |  〇 |   |
|  public | 〇  | 〇  | 〇  |  〇 |

- インターフェースは公開を前提としているため、publicのみ。修飾子をつけなかった場合は暗黙で付与される。
- 抽象メソッドはインターフェースを実現したクラスやそのサブクラス内で実装されるため、privateは不可。


## finalの挙動
- 変数につくと変更を禁止する
- メソッドにつくとオーバーライドを禁止する
- インターフェースは実現されることが目的なのでfinalはつけられない。

## mismatchとcompareの挙動
- mismatch
    - 2つの配列を先頭から比較し、最初に一致しなかったインデックスを探す
- compare
    -2つの配列を辞書順に並べたときの順番を比較。第一引数が第二引数よりも前なら負、同じなら0、第二引数のほうが前なら正を返す。

## 変数の型について
- charとshort
    - キャストすれば変換できる(文字番号と数値の変換を行う)


## モジュールオプションについてのキーワード
- セキュリティと保守性の向上
- 堅牢性の向上
- コマンドラインからモジュールのエクスポート設定ができるが、module-info.javaに記述すべきなので望ましくない。
- Javaの基本APIはjava.baseモジュールにある
- -classpassに含まれるクラスは無名モジュールの一部
- mojule-info.javaのファイル名は変更できない。(空になっているのはOK)
- public,privateという単語は出てこない。requires, exportsになる。

## 捨て問(にする予定)
- コマンドラインオプションはなんかそれっぽいオプション(-d とか -cpとか)がついてるやつ選べば当たる
- ラムダ式はよくわからんけどコード見てそれっぽいのを選ぶ


受験料高いから一発で受かりてえ・・・
RailsでParameterの確認

#内容
送られてきたParameterをサクッと確認したい際には、コントローラのcreateアクションなどに以下を記述

```ruby
def create
  render plain: params.inspect
end
```
#コードの理解
renderで:plainオプションを使うことで、平文テキストをマークアップせずにブラウザに送信が可能

```ruby
def create
  render plain: "！！！"
end
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1106668/2d6a99d6-e4ef-d610-7c1b-703ca161ff00.png)

上記を用いてparamsを表示している。
.inspectをすることで、文字列オブジェクトの内容を、
出力したときに人間が読みやすいような適当な形式に変換することが可能

```ruby
params.inspect
```
M5StickC Plus (ESP32) とTinyGoでLチカ

# はじめに
最近、仕事でGO使ってて、趣味ではESP32を使ってるので、TinyGoでESP32をプログラミングしたくなってきた。ということで、Lチカすることにした。

# 環境
macOS Big Sur Ver 11.1

# インストール
## TinyGo
tinygoは、ここを参考にして、インストールした。
[macOS :: TinyGo - Go on Microcontrollers and WASM](https://tinygo.org/getting-started/macos/)

いろいろ書かれてるけど、これだけで動くはず。

```zsh
brew tap tinygo-org/tools
brew install tinygo
```

## ESP32のためのツール群
これにしたがって下記ツールを入れた。

[ESP32 - mini32 :: TinyGo - Go on Microcontrollers and WASM](https://tinygo.org/microcontrollers/esp32-mini32/)

- pyserial
- Espressif toolchain
- esptool

コマンド的にはここらを実行した。pipとかpyserialはすでに入ってた気がする。

```
sudo easy_install pip
sudo pip install pyserial
mkdir -p ~/esp
cd ~/esp
tar -xzf ~/Downloads/xtensa-esp32-elf-osx-1.22.0-80-g6c4433a-5.2.0.tar.gz
```

PATHも追加した。

```zsh:.zshrc
export PATH="$PATH:$HOME/esp/xtensa-esp32-elf/bin"
```

# Lチカ
みんな大好きLチカ

## コード
これを真似させてもらった。
[GitHub - tinygo-org/tinygo: Go compiler for small places. Microcontrollers, WebAssembly, and command-line tools. Based on LLVM.](https://github.com/tinygo-org/tinygo)

M5StickC Plusの組み込みLEDのPINが10なので、そこだけ修正した。

```go:blink.go
package main

import (
	"machine"
	"time"
)

func main() {
	led := machine.Pin(10)
	led.Configure(machine.PinConfig{Mode: machine.PinOutput})

	for {
		led.Low()
		time.Sleep(time.Millisecond * 1000)
		led.High()
		time.Sleep(time.Millisecond * 1000)
	}
}
```

## 書き込み
こんな感じでコンパイルして書き込めた。USBのポートを指定しなくても探してくれるみたい。
終わるのがむちゃくちゃ速い。ちゃんと書き込めたか不安になる。かかったの4秒くらい。Arduino環境だと、3倍くらいはかかってる気がする。

ちなみに、複数あったらどうなるんやろう？

```zsh
~/p/tinygo ❯❯❯ tinygo flash -target=esp32-mini32 blink.go
esptool.py v3.0
Serial port /dev/cu.usbserial-xxx
Connecting....
Chip is ESP32-PICO-D4 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, Embedded Flash, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: xxxx
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Flash params set to 0x030f
Compressed 3072 bytes to 2396...
Wrote 3072 bytes (2396 compressed) at 0x00001000 in 0.2 seconds (effective 111.7 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
```

指定するときはこんな感じ。

```
# tinygo flash -target=esp32-mini32 -port=/dev/tty.usbserial-E9526A3192 blink.go
```

## 動き
特に何の変哲もないLチカだけども。

https://twitter.com/optimisuke/status/1372186775662161922?s=20

# シリアル通信（UART）
シリアル通信（UART）もできるみたい。`println()`で送信。ついでに確かめた。

## コード

```go
package main

import "time"

func main() {
	for {
		println("hello world!")
		time.Sleep(time.Second)
	}
}
```

## 動作
下記コマンドで接続。
デフォルト115200bpsで接続してるみたい。

```
~ ❯❯❯ screen /dev/tty.usbserial-E9526A3192 115200
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/940587c2-3aeb-1193-b261-f722fe3ecb55.png)


# おわりに
Lチカすんなりできてよかった。
コンパイルと書き込み速度がとんでもなく速い。Lチカだけやから？にしても速い。衝撃。

# APPENDIX
## ESP32の対応（2021/03/17現在）
ちょっとしか対応できてないみたい。。。もっと使うには、自分も貢献すべきか。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/108c7038-f26c-f3d7-cc4f-cf06d7f09c0f.png)

ここ参照。
[ESP32 - mini32 :: TinyGo - Go on Microcontrollers and WASM](https://tinygo.org/microcontrollers/esp32-mini32/)
SQLのインサート文の書き方まとめ

#概要
仕事で数十万件のバッチ処理を書くことがあって
INSERTを書くときに書き方次第でパフォーマンスが何倍も変わることを知ったので、備忘録として残す

例として"hoge_table"のcol1,col2,col3カラムに値を入れ、１０レコード追加することを考える


#その１ 逐次実行

```sql
INSERT INTO hoge_table (col1,col2,col3) VALUES (100,200,300)
INSERT INTO hoge_table (col1,col2,col3) VALUES (100,200,300)
INSERT INTO hoge_table (col1,col2,col3) VALUES (100,200,300)
INSERT INTO hoge_table (col1,col2,col3) VALUES (100,200,300)
INSERT INTO hoge_table (col1,col2,col3) VALUES (100,200,300)
INSERT INTO hoge_table (col1,col2,col3) VALUES (100,200,300)
INSERT INTO hoge_table (col1,col2,col3) VALUES (100,200,300)
INSERT INTO hoge_table (col1,col2,col3) VALUES (100,200,300)
INSERT INTO hoge_table (col1,col2,col3) VALUES (100,200,300)
INSERT INTO hoge_table (col1,col2,col3) VALUES (100,200,300)
```

この書き方は単純にINSERTを10回繰り返して生成する方法。
今回のように少ない件数の時には問題ないが１０００件以上生成するような場合など
早々にパフォーマンスが悪くなる。

なぜならINSERT１件ごとにコミット（DBへの反映）しているから

#その２　バルクインサート

```sql
INSERT INTO hoge_table (col1,col2,col3) VALUES 
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300)
```

この書き方でもその１同様に１０件のデータを追加することができる
<strong>※挿入するデータのどこか１つでもエラーがあるとINSERTされない点に注意（INTカラムにSTRING値など）</strong>
バルクインサートを用いることでDBへのコミットが１回ですむためパフォーマンスはかなり改善される。

しかしこの書き方でも数十万件のレコードになるとパフォーマンスが悪くなってしまう。

#その３　INSERT SELECT

```sql
INSERT INTO hoge_table (col1,col2,col3) #VALUESは書かない
SELECT col1,col2,col3
FUGA fuga_table
```

この書き方ではhoge_tableに入れたいVALUEの値を持つテーブル"fuga_table"をあらかじめ定義しておき
fuga_tableでSELECTしたcol1,col2,col3をhoge_tableのcol1,col2,col3に
INSERTするという方法。

ちなみに今回の３手法全てを試した大まかな実行時間は
逐次コミット: 6時間半(推定)
バルクインサート: 15分以上(計測停止)
INSERT SELECT: 10秒

桁が違う。。。


#まとめ
用途によって使い分けるが吉
1件なら逐次、複数件ならバルクインサート、大量データのバッチはINSERT SELECTのような感じで

今回はこの３パターンを実際に試してみたが
他にもCOPY,LOADなど外部ファイル読み込みなどの方法もあって
どれが最適かはその時々なのでSQLの沼に浸かって覚えていくしかない
tqdmでメモリリークにハマった話（機械学習）

# 事件

PytorchのResNetモデルを使って画像の訓練をしていたら、エポックのループ毎に、CPU / GPUメモリ両方の使用率がガンガン上がっていく事件に遭遇した。

# 解決方法（tqdmの使い方）

tqdmは、進捗をプログレスバーで表示してくれる便利なライブラリだが、そこに落とし穴があった。

``` python
import tqdm

# 訓練画像の data loader をループを回す
for x in tqdm(loader):
    y = model(x)
```

このような書き方をすると、tqdmがloaderを参照したままになり、メモリが解放されない。


正解はこれ。

``` python
tqdm(loader)             # ダメ
enumerate(tqdm(loader))  # ダメ
tqdm(enumerate(loader))  # OK
```

enumerateでラッパーしてからtqdmを噛ませるのが正解。

更にイテレータの長さを渡して、

``` python
tqdm(enumerate(loader), total=len(loader))
```

とすれば、完璧。

こちらの記事が参考になった。
https://github.com/tqdm/tqdm/issues/746

# 束縛されている変数を発見しよう

参照が残ったままで、メモリから解放されない変数がないかと、疑問を持ったときは、

``` python
sys.getrefcount()
```

を試して見よう。

``` python
import sys

a = "aiueo"

# getrefcount 自体も a を参照するため、
# 参照数は常に+1で表示されることに注意。

print(sys.getrefcount(a))
>> 2 

b = a
print(sys.getrefcount(a))
>> 3

del b
print(sys.getrefcount(a))
>> 2
```

このように、参照されている変数が存在しない場合は「2」、参照が残っている場合は「2」より大きい値を返す。

参照を残さずに関数などのスコープを抜けると、Pythonはガベージコレクションの機能で、自動的にオブジェクト自体もメモリから掃除してくれる。

メモリリークを疑ったときは参照数カウントを試してみては。
【Kotlin 初心者】DataPikerで日時表示する

## イメージ
Kotlinで簡単にiPhoneみたいな表示で日時を表示することができます

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320838/a56ce107-f95d-c280-0093-6ff565c887f8.png" width="400">

## 実装
コードはいけてないとこありますが、ご容赦を、、、

```MainActivity.kt

package com.example.datapicker

import android.app.AlertDialog
import android.app.DatePickerDialog
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val dataPiker = findViewById<TextView>(R.id.date_picker)
        dataPiker.setOnClickListener {
            showDataPicker()
        }

    }

    private fun showDataPicker() {

        val dataPiker = findViewById<TextView>(R.id.date_picker)
        val datePickerDialog = DatePickerDialog(this,
                AlertDialog.THEME_HOLO_DARK,
                DatePickerDialog.OnDateSetListener() { view, year, month, dayOfMonth->
                    dataPiker.text = "${year}/${month + 1}/${dayOfMonth}"
                }, 2020, 12, 1)
        datePickerDialog.show()
    }
}
```

```ActivityMain.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/date_picker"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="ここをタップして"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
```

## 終わりに
Githubにもあげているので困っている方いたらぜひ！
https://github.com/naoyukitsuruo/dataPickerSample
Goでnslookupする


```golang
package main

import (
    "fmt"
    "log"
    "net"
)

func main() {
    addr, err := net.LookupHost("vamdemicsystem.black")
    if err != nil {
        log.Fatal(err)
        return
    }
    fmt.Println(addr)
}
```

```
⋊> /t/golang go run main.go                                                   23:06:26
[183.181.88.32]
```
マイクロサービスにおけるロギングについて

#マイクロサービスにおけるロギングMEMO

- https://rarejob-tech-dept.hatenablog.com/entry/2020/03/19/190000

## リクエストにユニークなIDを付与し、紐付けができるようにする

>マイクロサービスでは、あるサービスAがサービスBを呼びさらにサービスCを呼ぶといった形になるので、呼び出しチェーンにユニークなIDを与えることで調査の見通しが良くなります。

なるほど。

## ログは一箇所に集める

>各サービスが出力するユニークID付きのログを横断的に調査するために、各サービスのログを一箇所に集中させることが次に重要になります。

こんな感じらしい

<img width = 600 src = "https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochataro/20200316/20200316183408.png">

## ログデータを構造化する

- jsonがおすすめ

## ログに有益な情報を持たせる

どのサービスでも共通で持つのが望ましいフィールド

- 日時(タイムスタンプ)
- 対象のサービス名
- スタックトレース
- エラー発生源である外部サービス名やミドルウェア名

リクエストのエントリーポイントとなるサービスで持つのが望ましいフィールド

- リクエスト元のIPアドレス
- ユーザが利用したブラウザ名またはモバイルのOS名
- HTTPレスポンスコード

```
{
   "level":"error",
   "msg":"SearchSample panic!",
   "request-id":"00A-abcdef-99B",
   "service-name":"MicroService01",
   "stack":"goroutine 6 [running]...スタックトレースが続く...",
   "time":"2020-03-15T23:39:58+09:00"
}
```

## 例
```
package logger

import (
    "github.com/sirupsen/logrus"
)

const (
    // XTransactionID はユニークIDのためのHTTPヘッダーのキー名です。
    XTransactionID = "X-Transaction-ID"
)

var (
    // Log は本パッケージのグローバルインスタンスです。
    Log = defaultLogger()

    // ServiceName は各アプリケーションのビルド時に ldflags を利用して埋め込まれます。
    // 下記はビルドの例です。
    // go build -ldflags "-X path/microservice-logging/logger.ServiceName=MicroService01"
    ServiceName = "not-set"
)

// Logger は公開インターフェースです。
type Logger interface {
    Debug(xTxID interface{}, msg string, fields ...Field)
    Info(xTxID interface{}, msg string, fields ...Field)
    Error(xTxID interface{}, msg string, fields ...Field)
}

// NewLogger は Logger インターフェースのコンストラクタです。
// 基本として、マイクロサービスのアプリケーションはこれを利用せずに Log インスタンスを利用することがルールです。
// 開発をする場合や調査をする場合などで Config を設定しこのメソッドを呼び出す。
func NewLogger(conf *Config) Logger {
    return newLogger(conf)
}

func defaultLogger() Logger {
    return newLogger(NewConfig()) //NewConfig() で共通ルールに基づくデフォルト設定がされる。
}

type logger struct {
    *logrus.Logger
    config *Config
}

func newLogger(config *Config) Logger {
    var l = logrus.New()
    {
        l.Level, _ = logrus.ParseLevel(config.minLevel.String())
        l.Formatter = config.formatter
        l.Out = config.out
    }
    return &logger{
        Logger: l,
        config: config,
    }
}

func (l *logger) Debug(xTxID interface{}, msg string, fields ...Field) {
    ...
}

func (l *logger) Info(xTxID interface{}, msg string, fields ...Field) {
    ...
}

func (l *logger) Error(xTxID interface{}, msg string, fields ...Field) {
    ...
}
```