OmniAICreator/Qiita-1.07M huggingface dataset:
iOSのバッググラウンドアップロード処理の重複制御と並行処理制御

この記事は[千 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/sen)の17日目の記事です。

弊社では開発しているiOSアプリではバッググラウンドでファイルのアップロード処理を行う機能があります。
本記事ではその実装で得られた開発Tipsを2つ紹介します。

# 環境

- Xcode10.1
- iOS12.1

# 重複実行の制御

弊社のアプリでは重複してアップロードを行うと期待した動作にならないため、次の制御を行っています。

- `URLSessionConfiguration` にアップロード処理毎にidを設定
- アップロード処理の実行前に `URLSession` の tasks を確認し、存在した場合は新たにアップロード処理を実行しない

コードは以下になります。

```swift
// URLSessionConfigurationでidを設定
let id = generate()
let config = URLSessionConfiguration.background(withIdentifier: id)

let session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
session.getAllTasks { [weak self] tasks in
    guard let self = self else { return }

    // 重複実行を避けるためにtasksに存在ないことを確認してから新しいtaskを実行します。
    guard tasks.isEmpty else { return　}

    // taskの実行処理をここで実装。
}

```

# 並行処理数の制御

弊社のアプリでは一度に数百枚から数千枚のファイルのアップロードを行うため、並行処理数の制御を行う必要がありますが、検証したところ `URLSession` は自動で並行処理数の制御を行ってくれていました。
また、私が検証した環境では、ネットワーク環境によって並行処理数が変わっていたため、自前で制御するよりも効率的に実行されていると思います。

検証には `URLSessionTaskDelegate` を実装し、進捗を見て行いました。
コードは以下になります。

```swift
    func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
        guard let id = session.configuration.identifier else {
                return
        }
        print(id)
        print(totalBytesSent)
        print(totalBytesExpectedToSend)
    }
```
Glideで画像のExif情報による自動回転をさせなくする

## 前提

- Glideのバージョンは4.xです。

## Uri / File

- URIやFileなどのローカルファイルをGlideで表示する場合は以下のやり方で自動回転を防ぐことができます。

```
Glide.with(binding.image)
        .load(uri)
        .apply(RequestOptions().dontTransform())
        .into(binding.image)
```
Vue CLI 3でHello-Worldする

## Vue CLI 3をインストール

npmで3.0以上のvueをインストールします。

```
$ npm install -g @vue/cli
```

バージョン確認

```
$ vue --version
```

## プロジェクト作成(コマンドライン編)

```
$ vue create hello-world
```

最初に雛形を作るにあたり、そのまま「Enter」を押せばdafaultでインストールされます。

```
$ cd hello-world
$ yarn serve
```

ブラウザで http://localhost:8080/ をアクセスするとサンプルが表示されます。

##ソースを編集する

src/App.vueの<template>を編集する

``` App.vue
<template>
  <div>
    <p>
      Hello World
    </p>
  </div>
</template>
...
```

もう一度http://localhost:8080/
にアクセスすればHello Worldに変更されています。

実際に動いているソースを確認するには下記コマンドで、ソースが生成されます。

```
$ yarn build
```

## プロジェクト作成(Vue CLI UI編)
Vue CLI UIは結局、ソースコードはブラウザではなくエディタで編集するのであくまでも補助的なツールなのだろうか...。とりあえず、プロジェクトの作成まで。
###Vueプロジェクトマネジャー
ディレクトリを選択してプロジェクトを作成します
<img width="1148" alt="スクリーンショット 2018-11-26 19.29.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/258049/2b8e97c0-83c0-43ad-b6f4-5d6d60291d79.png">

###新しいプロジェクトを作成する
プロジェクトフォルダ名を入力して次へ
<img width="1091" alt="スクリーンショット 2018-11-26 19.30.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/258049/52809442-61b2-fb2f-4c65-d9321a56d61d.png">

デフォルトプリセットを選択します。
<img width="1141" alt="スクリーンショット 2018-11-26 19.31.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/258049/2eecac3f-27f4-2834-e705-8517199acc8a.png">

プロジェクトが作成されました。
画面右上にある[DevTools　インストール]からDevToolsをインストールすると捗ります。
<img width="1344" alt="スクリーンショット 2018-11-26 19.35.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/258049/7c5500c1-797c-ba66-6d71-b082e1a73fdd.png">

Google Chromeの場合、F12でデバッグコンソール(Vue DevTools)起動。
<img width="1571" alt="スクリーンショット 2018-11-26 19.38.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/258049/40829fac-ef3d-e6de-58e6-1c5d144e3279.png">

Hello-Worldをするためにはエディタで上記のようにApp.vueを編集し、画面左の[タスク]→[serve]→[タスクの実行]ボタンを押します。
画面右上の出力ボタンを押せば、Appが走っているアドレスが表示されるので、クリックすればHello-Worldが表示されます。
<img width="1428" alt="スクリーンショット 2018-12-17 22.12.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/258049/06a96ece-2f41-e9a1-f136-8610df09ab47.png">

以上です。

##その他はじめにやったことメモ
###App.vueではなくindex.vueにしたい
src/main.jsを開き2行目を下記のように変更すればindex.vueを読み込めます。
Vueというディレクトリを作成し、

```main.js
2: // import App from './App.vue'
3: import App from './index.vue'
```

###読み込むvueファイル(ローカルコンポーネント)を追加したい

scriptタグ内で以下のように記述を追加すれば読み込めます。

```
<script>
import MyComponent from './MyComponent.vue'
export default {
  components: {
    MyComponent
  },
  hoge() {
    return {
      ○○: xxx
    }
  }
}
</script>

```

##

###ワンクリックで起動したい
html5とjavascriptで作成したコンテンツはindex.htmlをクリックすれば起動されますが、
vueで作成した場合index.htmlをクリックしても何も表示されません。
いちいちyarn serveしてローカルアクセスするのがめんどくさいので、
electronを導入しました。
[Vue Cli 3 plugin for Electronの導入](https://qiita.com/nullpo24/items/f3f299f1f8cdc82af0c3)
RailsのTransactions、Lock　初心者→中級者へのSTEP17/25

#RailsのTransactions、Lock
##はじめに
[前回の`Transactions`](https://qiita.com/kamohicokamo/items/2a923529144926dffa04)の応用で今回はデータの**ロック**についてです


##データのロック？
DBにおけるロックとはトランザクションが対象データにロックをかけて占有することです。
これはデータの競合を防ぐためです。
二つのトランザクションが同時に起きると、データに一貫性が持てないことがあります。
例としては[こちら](https://www.teradata-jp.com/single-post/col05i)のページがわかりやすかったので、参考にしてください。

##Railsでロックするには
実装方法は2つ、`lock`と`with_lock`があります。

```rb
    User.transaction do
      user = User.lock.find(1)
      user.update!(name: 'taro')
    end
```
最初に`lock`メソッドです。チェインして使います。これでトランザクション中はロックされます。処理中は**読み取りは可能です。**更新処理等は待たされます。

次に、`with_lock`メソッドです。こちらはトランザクションとロックが同時にできます。

```rb
  user = User.first
  user.with_lock do
    user.update!(name: 'taro')
  end
```

##注意点
今回のロックの仕方は悲観的ロックと呼ばれ、ロックしないとデータは競合するだろうという推測の元するロックのやり方で、厳格なロックとなります。利用できるDBMSはPostgresかMySQLとなりますのでご注意を。

##試してみる。
参考記事でもコンソール２つ使ってデータがロックされているか試してたので確認してみます。

```console
irb(main):028:0> user = User.first
irb(main):032:0>    user.with_lock do
irb(main):033:1*       sleep 30      
irb(main):034:1>    end              
   (0.1ms)  begin transaction
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?   [["id", 1], ["LIMIT", 1]]

~~~~~~~~~~30秒後~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   (0.2ms)  commit transaction
=> 30
```
この間に他のコンソールでuserを更新してみます。

```console
irb(main):026:0> user.update(name: 'locking')
   (0.1ms)  begin transaction
  SQL (0.8ms)  UPDATE "users" SET "updated_at" = ?, "name" = ? WHERE "users"."id" = ?  [["updated_at", "2018-12-17 13:16:12.614654"], ["name", "locking"], ["id", 1]]
   (5045.1ms)  commit transaction
   (2.0ms)  rollback transaction
ActiveRecord::StatementInvalid: SQLite3::BusyException: database is locked: commit transaction
```
ちゃんとロックされてます。待ち時間が長いので戻されてます。




##まとめ
データベースも学び直したくなってきた今日この頃。


##参考にしたの

Railsのデータロック
https://qiita.com/merrill/items/d9d41d64df292bd6432a

Active Record Transactions
https://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

トランザクションの一貫性を保証するロック
http://www.atmarkit.co.jp/ait/articles/0212/21/news003.html

ActiveRecord::Locking::Pessimistic
https://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html

Railsで悲観的ロック（PostgreSQLの行レベルロック）
https://qiita.com/upinetree/items/b3329501561268f7678a
フロントエンド嫌いを克服した話

こんにちは、とよへいです。
最近はrailsを書いたり、ちょろっとJSを書いたりしているエンジニアです。
この記事は、[技術的ポエム Advent Calendar 2018](https://qiita.com/advent-calendar/2018/poem) 18日目の記事です。
少し前までフロントエンドが嫌いだった私が、なぜフロントエンド嫌いを克服できたのかって話をしようと思います。
※ 注意: この記事は、事実ではなく解釈に基づいて書かれています。

# なぜフロントエンドが嫌いだったのか
簡単に言うとなんかよくわからなかった。詳しく言うと、次のような感じでした。

## 何がわからなかったのか
- HTMLよくわからん
    - HTMLってそもそも何なの？何のためにあるの？
- ブラウザよくわからん
    - ネットサーフィンする時に使う便利な道具だけど、ブラウザってそもそも一体何なの？
- JavaScriptを使うことで、ブラウザに表示しているものが操作できる原理がわからん
    - JavaScript、お前は一体何者だ

その結果、自分にとってフロントエンドの世界は、

- 論理的じゃなく丸暗記の世界でつまらない
- 丸暗記とかはそれが好きな人達が頑張ってくれ！俺は論理的なサーバーサイドの世界で頑張るから！

と言う感じになってました。(フロントエンドエンジニアの皆様本当にごめんなさい)
そんな感じでずっと忌避していたフロントエンドだったのですが、仕事で使う必要が出てきたので、どうにかフロントエンド嫌いを克服することに。


# 解決した方法
解決した方法はシンプルで、**わからないものを一つずつ理解していく**ことでした。
自分がわからなかったのは

- HTMLとは何か
- ブラウザとは何か
- JavaScriptを使うことで、ブラウザに表示しているものが操作できるのはなぜか

と言うことだったので、一つずつ調べていくことにしました。

## そもそもHTMLとは何か
- Hyper Text Markup Language の略称で、インターネットを通じて文書共有をする際に、使用するフォーマット。
- メモ帳とかで作成するプレーンテキストだと、リンクとかが実現できないから作られた。
  - [参考: Webの歴史](https://www.internetacademy.jp/special/history.html)
- もっと別の方法で文書構造を綺麗に表現することはできないのかって思うけど、今尚デファクトとなっているので、色々考えてもこうするのがいいのだろう。

## そもそもブラウザとは何か
- HTMLで作成されたドキュメントを、人間にとって見やすいように綺麗に整形して表示するGUIソフトウェア。
- マウスのクリック操作などを感知することができる。
- 感知した操作を元に、サーバーに対してリクエストを送ったり、レスポンスを受け取ったりできる。
- ブラウザに搭載されているレンダリングエンジンが、htmlやcssの構文解析を頑張って我々のPC画面などに描画している。
  - [参考: ブラウザの仕組み: 最新ウェブブラウザの内部構造](https://www.html5rocks.com/ja/tutorials/internals/howbrowserswork/)

## JavaScriptを使うことで、ブラウザに表示しているものが操作できるのはなぜか
- JavaScriptでブラウザの表示を操作できるように、ブラウザが実装されているから(元も子もない言い方になるが)。
- 具体的には、DOMを実装しているから。

### DOMとは何か
- 仕様の名前。正式にはDocument Object Modelという。
- HTMLをJSとかで、こうやっていじれるようにしたいから、ブラウザを作るお前らは、これができるように作れよ！！(JSとかのこう書いた時に、こういう値を返すように作れよ！)って書いてる。
- 具体的に言うと、例えば次のようなコードで、 `hoge` と言うIDを持つ要素を取得できる。これは `document.getElementById()` と言うJavaScriptで `hoge` が取得できるように、ブラウザが実装されているから。

```javascript

var hoge = document.getElementById('hoge');
```
- そこら辺の仕様については、W3Cと言う団体が仕様書を作成していて、その仕様書を元にChromeやFirefoxなどの各ブラウザは実装されている。
  - [参考: 文書オブジェクトモデル(DOM)第1水準 仕様書](http://www.doraneko.org/misc/dom10/19981001/cover.html)

## 結局フロントエンド技術とは何か
- ブラウザで遊ぶ技術、もとい、ブラウザで表示するHTMLを操作したりする技術。操作にはJSとかを使う。
- (今のフロントエンド技術はもっと広範囲を指すものだと思うけれど、初歩的なものとしての理解を書いています。)

# まとめ
個人的には、ここら辺まで理解できたところで、フロントエンド嫌いは結構克服されていました。
根本的には、わからないものをある程度ちゃんと理解したら怖くないよ！って話だと思います。
過去の自分と同じく、フロントエンドなんて嫌い！って方の、理解の助けになれば嬉しいです。


## 余談
ちなみにフロントエンドについて調べていて一番大変だったのは、DOMのことを理解する部分で、そこらへんの調査の軌跡は、以前の記事で雑にまとめてみています。
[フロントエンド初心者がW3C勧告に出会うまで](https://qiita.com/t0yohei/items/23cd66dcc46edbc07a10)

終わり。
ヒストグラム(度数分布表)

# ヒストグラム(度数分布表)

* 問題提起
   * ヒストグラム(度数分布表)とは何だろうか。
   * 何に使うものか。

* ヒストグラムの用途
   * データの分布を可視化したいときに用いる。
      * 可視化することで、各種統計値(平均や分散など)よりも詳しくデータの分布を知ることができる。

* ヒストグラムの仕様例(データは仮のもの)
   * データの説明
      * 20個のポットで同じ種類の花を育てた。
      * 咲いた花の数のデータを取った。
      * 花の数の分布をヒストグラムで可視化すると、何がわかるだろうか。

   * データ

|ポットNo|花の数|
|---|---|
|1|10|
|2|9|
|3|12|
|4|10|
|5|10|
|6|9|
|7|7|
|8|14|
|9|11|
|10|12|
|11|18|
|12|17|
|13|15|
|14|15|
|15|16|
|16|16|
|17|15|
|18|14|
|19|13|
|20|15|

   * 上記データから作成したヒストグラム
      * 横軸: 咲いた花の数
      * 縦軸: 咲いた花の数の度数
      ![sample_histogram.png](https://qiita-image-store.s3.amazonaws.com/0/321994/d7e50466-8b38-fc21-7a60-76c4849142db.png)

         * 10個の花が咲いたポットは3つあり、15個の花が咲いたポットは4つある。

   * pythonでヒストグラムを作成するコードの例

      ```python
      import matplotlib.pyplot as plt
      x = [10, 9, 12, 10, 10, 9, 7, 14, 11, 12, 18, 17, 15, 15, 16, 16, 15, 14, 13, 15]
      fig = plt.figure()
      ax = fig.add_subplot(1, 1, 1)
      ax.hist(x)
      fig.show()
      plt.savefig('sample_histogram.png')
      ```

      * たくさんのヒストグラムを作成するときなど、pythonは便利。

   * ヒストグラムから読み取れること
      * 同じ種類の花を育てたのに、ヒストグラムには2つの山が存在する。
         * 10個くらいの花が咲いたポットと、15個くらいの花が咲いたポットが多い
      * なぜだろうか？
         * もしかして、生育環境など、条件が異なっていたのではないか？
      * 統計量との違い
         * 平均値や標準偏差からでは、こういった疑問を持つことができない。
         * 可視化することで初めて分かる。
      * 調査の結果、分布の差の理由がわかるかもしれない。
         * 例えば、この20のポットは、異なる栽培条件の元で育てられたものだった。
            * ポット1~10はひなたに置いて育てた。
            * ポット1~10は日陰に置いて育てた。

* まとめ
   * ヒストグラムは、データの分布を可視化することに使える。
   * 可視化することで、平均や標準偏差よりも詳しくデータについて知ることができる。
NumWorks の MicroPython

# NumWorksについて

１２月はじめにカシオの [fx-CG50](https://web.casio.jp/dentaku/fxcg50/) が MicroPython をサポートしたことで話題になりましたが、この背景には NumWorks の存在が大きかったのではないかと思っています。

[NumWorks](https://www.numworks.com/) は、いわゆる[グラフ電卓](https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%A9%E3%83%95%E9%9B%BB%E5%8D%93)というもので、教育市場で使われている電卓が [TI-84](https://ja.wikipedia.org/wiki/TI-84_Plus_%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA) に支配されている状況を打破しようと、フランスの NumWorks 社が2017年の夏に殴り込みをかけてきたものです。そのデザイン性と内部情報が公開、利用者(主に教育関係者)からのフィードバックをとりいれてファームウェアを更新していくことから人気が出ています。もちろん MicroPython をサポートしているところも人気の要因の一つです。

もの好きな私は今年の４月に注文して５月に届きました。

![IMG_4787.jpg](https://qiita-image-store.s3.amazonaws.com/0/106817/204833bd-1a01-2bee-fd80-5d104429b5ef.jpeg)

中身は本体とカバー、USBケーブル、SAFETY GUIDE(安全のしおり)だけです。[マニュアル](https://www.numworks.com/resources/manual/)はオンラインで参照することになります(PDF版のダウンロードも可能です)。電卓には珍しく乾電池式ではなくて充電バッテリー内蔵で、USBケーブルを使って充電します。

![IMG_4788.jpg](https://qiita-image-store.s3.amazonaws.com/0/106817/63411174-7b0a-7f6a-1868-aae3bb04770c.jpeg)

# NumWorks の MicroPython

メニューにはきちんと "Python" があります。

![IMG_4789.jpg](https://qiita-image-store.s3.amazonaws.com/0/106817/fda5b94a-b566-5bac-be01-f4d607f35504.jpeg)

NumWorks は[ハードウェア](https://www.numworks.com/resources/engineering/hardware/)も[ソフトウェア](https://www.numworks.com/resources/engineering/software/)も情報公開していることから、一部マニアがハードウェア改造(裏に Raspberry Pi Zero くっつけて、NumWorks の画面で DOOM やってるビデオを見たことがあります)やカスタムファームウェアを作成したり(シリアル接続可能にしたり)しています。

現在の最新ファームウェア 1.8.1 では MicroPython 1.9.4 をサポートしています。マニュアルによれば、MicroPython でサポートされているモジュールは math, cmath, random, kandinsky だけです。カシオの fx-CG50 よりはマシなものの、やはりちょっと物足りなさを感じます。NumWorks社の現在の方針としては学校教育、大学入学試験で必要ないものは優先度低くなっているようです(下手に高機能だと試験に持ち込み不可になってしまいますしね)。fx-CG50 と違って、いちおう kandinsky でグラフィック描画できますが、サポートしているのはドットと文字を描画することぐらいです。以下はデフォルトで入っている mandelbrot.py で画面にマンデルブロ集合を描いてみたものです。

![IMG_4790.jpg](https://qiita-image-store.s3.amazonaws.com/0/106817/fcea2fdb-0182-915d-cf91-041d9df1617c.jpeg)

この他、[workshop.numworks.comのサイト](https://workshop.numworks.com/python)には NumWorks社や利用者によって作成された MicroPython スクリプトがあり、自分の NumWorks にダウンロード可能です。

![スクリーンショット 2018-12-17 21.52.30.png](https://qiita-image-store.s3.amazonaws.com/0/106817/2c35527f-dfe4-6e28-4731-7babb67b2478.png)

電卓キーボードでプログラミングは苦痛きわまりないのですが、NumWorks では Web 上でシミュレータで確認しながらプログラムして、実機にダウンロードする環境があります。これは便利(ただし、他のスクリプトと組み合わせてシミュレートする方法が未だにわかりません)。

![スクリーンショット 2018-12-17 21.54.46.png](https://qiita-image-store.s3.amazonaws.com/0/106817/1ee7fd7f-20af-171b-b59d-3f22e5b44842.png)

興味持たれた方は実際に購入してしまうまえに[オンラインシミュレータ]( https://www.numworks.com/simulator/)で使い勝手を確認するのがよいでしょう。あくまで海外の教育市場向けの電卓ですので過度の期待をしてはいけません。

では、本日はここまで。
メモリーの確保・解放

# C言語：メモリー管理
仕事でC言語を使うので、その備忘録として記事をあげていきます。

なぜメモリーを確保する必要があるのか。
→プログラム内で使用するデータ数は**未知な**ことが多い。
　事前に必要なデータ数が不明な場合、実行時にライブラリ経由で
　OSから<font color="Blue">必要となった分のメモリー</font>を取得する。
　不要となったメモリーはライブラリ経由でOSへ返却する。

◾️Cのライブラリ関数
① malloc関数
　void *malloc(size_t size);
→sizeで指定したバイト数のメモリーを取得する
　返り値は取得したメモリーへのポインタ
　メモリーの確保ができなかった場合は<font color="DeepPink">NULL</font>が返ってくる

② free関数
　void free(void *ptr);
→mallocで確保したメモリー領域を解放する
　ptrには<font color="DeepPink">mallocが返したポインター</font> or <font color="DeepPink">NULL</font>でなくてはならない

③　memset関数
 void *memset(void *s, int c, size_t n);
→nバイト分のサイズのデータをsがポイントする領域に対して、cでデータを書き込む。

＊malloc + memset
malloc関数で確保した領域は**不定値**(値が決まっていない)ので、
memsetを使用してデータを初期化すると良い

＊mallocがNULLを返してきた場合
この場合、通常は**メモリ不足**が原因なため、プログラムを終了させる必要がある。
そんな時はexit関数を使用する。
 _Noreturn void exit(int status);
→exit関数はstatusで指定した値をコマンとの返り値とする。
　*main以外*の関数内で実行を終了する際に使用する。

④ realloc関数
 void *realloc(void *ptr, size_t size);
→mallocで取得したポインタの内容をコピーし、size分の領域を新たに確保し直す。
いつの間にか追加してた長いワンライナーとその時のテク

アドベントカレンダー企画で、いつの間にか追加していたワンライナーを載せます。
あと、便利な覚え書き程度のテクを載せます。

#gitのrootディレクトリに戻る。
標準のように多用している。

```
function cdg() { builtin cd `git rev-parse --show-toplevel`; return 0;}
```

#議事録から日付を抜き出す。

```
find /path/議事録/`date "+%Y_%m_%d"`*.html -type f -print0 | xargs -0 grep '.\{1,2\}月.\{1,2\}日' | pup "text{}" | grep -v '^\s*$' | tail -1 | cut -c 1-20
```

#議事録の最後の行を見る。
```
find . -type f -name "*議事録*" -not -name "trashed*" | tail -1 | xargs -I% cat '%'
```

#今日の天気
livedoor天気を利用している。。APIにやさしい版はこちらhttps://qiita.com/benridane/items/6ebfe45d8abcc497d09d

```
curl -s http://weather.livedoor.com/forecast/webservice/json/v1\?city\=270000 | jq -r '.forecasts[0].telop'
```

#簡単なテク解説

- pup: go製のhtmlパーサ。https://github.com/ericchiang/pup
    - パーサーはxmllintなどあるが、いろんな環境で動くものとしておススメしたい。
- jq: 高機能パーサ。JSONパーサ。https://stedolan.github.io/jq/
    - ```pup "json{}"```でjsonに変換してjqで処理することもできる。
- find:  ファイル検索。
    - ```-not -name "trashed*" ```でファイルを除外できる。
- xargs: -0を付けるとヌル文字対応になる。
    - ```xargs -I% cat '%'```で確かスペース対策で出力できる。
- grep: ```grep -v '^\s*$'```で空行除外ができる。

以上、ちょっとしたテクでした。
WildFly のインストール

やってみたのでメモ

# 前提条件
CentOS7
Javaインストール済み

# 手順
1. tarファイルをダウンロードする ファイルは[Downloads](http://www.wildfly.org/downloads/)から取得できる

    ```
    # curl -LkvOf https://download.jboss.org/wildfly/15.0.0.Final/wildfly-15.0.0.Final.tar.gz
    ```

2. 展開する

    ```
    # tar zxf wildfly-15.0.0.Final.tar.gz
    ```

3. `/opt`配下に移動させる

    ```
    # mv wildfly-15.0.0.Final /opt/wildfly
    ```

4. 起動する

    ```
    # ./standalone.sh -b=0.0.0.0
    ```

5. 次のURLにアクセスする

    ```
    http://<IPアドレス>:8080
    ```

# 参考
- [Getting Started with WildFly 15 - 1.3. Installation](http://docs.wildfly.org/15/Getting_Started_Guide.html#installation)
- [WildFly Admin Guide](http://docs.wildfly.org/15/Admin_Guide.html)
Rails API mode+deviseなSPAでtokenによるCSRF対策をする

こんにちは、 @mshibuya です。
RailsをバックエンドとしたSPAを開発するにあたり、tokenベースのCSRF保護をどう作り込むかの知見があまり見つからなかったので自分で作っちゃいました、という記録です。。

なおこの記事は[オプトテクノロジーズアドベントカレンダー](https://qiita.com/advent-calendar/2018/opt-technologies)17日目のエントリーです。

# 動機
通常のWebアプリケーションと同様、SPAにおいてもCSRF脆弱性は大いに問題になるわけですが、とはいえ対策方法についてまだ「これで決まり！」というレベルの定番の手法がないように感じています。

「SPA CSRF」で検索して上位に出てくる弊社エンジニア @uryyyyyyy による[SPAでのセッション管理とセキュリティ](https://qiita.com/uryyyyyyy/items/9a8276f7241b650f1c15)のエントリにおいても、CSRF Tokenを利用する方法について

> しかしSPAでは、フロントのコードがサーバーを経由せずに送られてきたり、Formが後から動的に作られうるので、仕込むタイミングが少し難しいかもしれません。

とだけ触れており、具体的な手法への言及はありません。

とはいえ、OWASPによる[Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet)においては

> We recommend token based CSRF defense (either stateful/stateless) as a primary defense to mitigate CSRF in your applications.

とされており、tokenベースの対策が第一選択となるのは確かです。

そこで、SPAにおいてできるだけ透過的な（＝保護漏れのリスクを最小限にできる）CSRF保護をRails APIをバックエンドとして実装してみます。

# 検討したこと

## Json Web Token(JWT)等の利用
[JWT（JSON Web Token）でCSRF脆弱性を回避できるワケを調べてみた話](https://qiita.com/mejileben/items/ae7b346f0fc4a59101b5)

上記エントリにあるよう、CSRF対策みたいなことを考えずに済むのは魅力的な話ではあったのですが、とはいえ

[JSON Web Token(JWT)って結局使っていいの？](https://qiita.com/take4s5i/items/009b0b6797b752921a78)

のような話から、セキュリティに係る技術としてはまだ十分に成熟していないと判断しました。

## Originチェックのみで誤魔化す

これは、上述OWASP資料において明確に

> These defense-in-depth mitigation techniques are not recommended to be used by themselves (without token based mitigation) for mitigating CSRF in your applications.

と挙げられている中にOriginチェック等が該当しているため、この対策のみ行うことをCSRF対策として十分とは判断しませんでした。

# 実現方法
OWASP資料中の[同期トークンパターン](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Synchronizer_Token_Pattern)を採用しました。サンプルリポジトリを公開してありますのでご覧ください。
https://github.com/mshibuya/rails-api-csrf-protection

要点については[このコミット](https://github.com/mshibuya/rails-api-csrf-protection/commit/1daf359720db3e90f58bafdf4c6e71a89fc41c14)を見るのが手っ取り早いと思います。コンセプトとしては単純で、

- レスポンスに `X-CSRF-Token` ヘッダを乗せて返す処理をafter_actionで引っ掛けておく
- フロント側ではレスポンスにある `X-CSRF-Token` ヘッダを毎回チェックし、ローカルストレージに保存する
- フロント側からPOSTする際には `X-CSRF-Token` ヘッダにローカルストレージから取り出したtokenをセットしてリクエスト
- ログイン時は送るべきtokenがないのでCSRFチェックをスキップ
    - 厳密には[これはまずい](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Login_CSRF)んですが、インパクトが大きくないのは確かなので宿題ということで…

という感じです。特に複雑なところはないですね。。

フロントエンドは雑にvue.jsで作っています。ページ内にログインボタンとかtokenクリアボタンとかついてるので、tokenなしでリクエストしたらどうなるかとか確かめられるはずです（実装が適当なのは急ごしらえなので勘弁を…）。

# まとめ

Rails API modeをバックエンドとしたSPAにおいて同期トークンパターンによりCSRF保護する方法を紹介しました。

なにか不備やツッコミ等ありましたらお寄せいただければと…。わりとちゃんとしている（と思っている）わりには手軽にできるので、皆様もお試しくださいー
Google Blocklyを使って円周率を求める

この記事はニフティグループ Advent Calendar 2018の12日目の記事です。

先日社内の新入社員研修で、プログラミング教育教材について企画・プレゼンを行いました。
その過程で知ったGoogle Blocklyで円周率を求めてみます。

#Google Blocklyについて
Google Blocklyとは、Googleが提供しているGUI操作でプログラミングを行えるOSSです。
図のようにマウス操作で図形を組み合わせることによってプログラミングが行えます。
プログラミングの知識がなくてもアルゴリズムを作ることができ、とても教育に役立ちそうです。

![スクリーンショット 2018-12-17 21.21.34.png](https://qiita-image-store.s3.amazonaws.com/0/215784/086093ad-1e06-c81c-6b5b-f62152e9662e.png)

#円周率の計算について
円周率を求める方法は以下のとおりです。

1. 面積が1の正方形内のランダムな位置にM回点を打つ
2. 原点からの距離が1以下になった回数をNとする
3. 最終的に $ \frac{4N}{M} $ が求める円周率になる

細かい理論は割愛しますが、四分円の面積と正方形の面積の比が、四分円の内外に打たれる点の数の比と一致することを利用しています。
試行回数は多ければ多いほど精度は向上します。ちなみに、このように乱数を使って近似値を求める手法をモンテカルロ法と言います。

#実践
以下の様にブロックを組みました。
![スクリーンショット 2018-12-17 21.34.42.png](https://qiita-image-store.s3.amazonaws.com/0/215784/79f1f218-6714-19c2-d777-69dc44e9fefb.png)

試行回数 $M$ は100万回としています。
右上の実行ボタンを押して結果を見てみましょう。

![スクリーンショット 2018-12-17 21.36.56.png](https://qiita-image-store.s3.amazonaws.com/0/215784/d5899a25-7f03-0e72-7cc3-f2a05a8f43cf.png)

$\pi = 3.14264$ と計算できましたね。100万回の試行ではこの程度の精度になるようです。

ちなみに、組み合わせた図形を実際のプログラミング言語に変換することもできます。
Pythonの場合、以下のように出力されました。

```
import random

m = None
n = None
x = None
y = None


m = 1000000
n = 0
for count in range(int(m)):
  x = random.random()
  y = random.random()
  if x * x + y * y < 1:
    n = n + 1
print((n / m) * 4)
```

#最後に
Google Blocklyを初めて使ってみましたが、想像よりもだいぶすんなりと実装することができました。
実際にコーディングをしなくても、アルゴリズムやプログラミング的な考え方の学習は可能だと思います。
オープンソースなのでこれを使って何か作ってみたいですね。
windows、xampp、cakephp3.7のphpunitインストールではまった話

#windows、xampp、cakephp3.7のphpunitインストールではまった話

##症状
cakephp3.7でunitテストをすると、エラーが発生して実行できない。

##原因 
phpunitの最新は7.5なのに、xamppのphpunitのバージョンが、3.\*だ。
cakephp3はphpunit7.\*に対応していない。
cakephp3.7は、5.\*に対応していない？
コマンドでバージョン指定してもxamppのphpunitのバージョンが優先される。

##解決方法
１．下記をダウンロード
https://phar.phpunit.de/phpunit-6.phar

２．ダウンロードファイルをxamppにコピー
xampp\php\ フォルダにphpunit-6.pharをコピーし、ファイル名をphpunit.pharに変更。

３．xampp\php\phpunit.batの編集
phpunit.batをエディタで開き、一番下の記述を変更。
▽修正前
"%PHPBIN%" "C:\xampp\php\phpunit" %\*
▽修正後
"%PHPBIN%" "C:\xampp\php\phpunit.phar" %\*

４．~~通常~~バージョンを指定してインストール
~~composer require  --dev phpunit/phpunit~~
composer require --dev phpunit/phpunit:"^5.7|^6.0"

以上です。

###下記を参考にしました。
https://qiita.com/mosaxiv/items/c714af921961bc898ec2
https://npg-web.com/2017/05/11/phpunit_install/
@ponkotuy さん の「アカウント削除機能に意味はない」の要約。

[アカウント削除機能に意味はない - Qiita](https://qiita.com/ponkotuy/items/6049388d564fb4385f4e)

[ponkotuy - Qiita](https://qiita.com/ponkotuy)

>本骨システムという屋号でフリーランスしてます。Scalaとか好きです。でもゲームとかもっと好きです


# 技術的、データベース的な問題

- 「1ユーザーの関連データの全削除」は難しい場合がほとんど
- 対策は「データが完全削除されたこと」にしておく。
- 運営者、開発者であれば確認できるが、他ユーザーからは見えない状態にする。

# 法律の問題、運営の問題

- 完全にデータ削除してしまうと、犯罪があったときなどにログ保存ができておらず、国に怒られることになってやばい
- データ完全削除すると「アカウント削除したユーザの傾向を知りたい」とかいう調査ができなくなる
- 現実的な対策としては、コンプライアンス的に要求度の高い個人情報は完全に消去するなど、局所的解決をする

# お金の話、コストの話

- 重たい重たい「アカウント削除機能」を作るだけで工数がかかる、お金がかかる、時間がかかる

# ユーザーの本当の気持ちは？

- 「自分に関する痕跡を残らず消して欲しい」 -> でも技術的に不可能
- メール連絡や課金とかを全部お手軽に止めたい -> アカウント削除ではなく、それぞれ全停止ボタンみたいなのを付けておけば良い

# ということで

アカウント削除機能は技術的に不可能、運営的に無理、法律的にデンジャー、ユーザー要望的にも本当は要らないという話。

# ところで

- @ponkotuy さんの読み方って「ポンコツワイ」さん‥？








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
【AWSメモ④】aws-cli セットアップ（Amazon Linux 2）

## 環境

・Amazon Linux 2
・Python2.7.14（デフォルト）

## pip のインストール

Amazon Linux 2 には、pip が入っていないので、以下のコマンドを実行してインストールする。

```shell
$ curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
$ sudo python get-pip.py
```



## aws-cli のインストール

pip コマンドで aws-cli をインストール



```shell
$ sudo pip install awscli
```



## aws-cli の設定

aws-cli の設定を行う。  

AWS アクセスキー ID 、 AWS シークレットアクセスキー（アカウントの認証情報）とデフォルトに指定するリージョン（どこでも良い）、aws-cli を使用した際に画面上に表示される出力結果のフォーマットを指定（JSON、text、table のいずれか）する。  

※ アクセスキーが不明な場合は、マネジメントコンソールのIAM設定から認証情報を確認すること。



```shell
$ aws configure
AWS Access Key ID [None]: ABCDEFGXXXXXXXXXXX
AWS Secret Access Key [None]: hogehogehoge/DEDEDEDE/XXXXXXXXXXXXX
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

以上で、セットアップは完了。
[](https://qiita.com/Kento75/items/3a84db0f55bef73eec6d)
[](https://qiita.com/Kento75/items/ca53d4266bc132cc13c6)
[](https://qiita.com/Kento75/items/bf8f7c91ee9dfb973d56)
【初心者向け】RailsでAPI開発 Part.3

# これは何？
[【初心者向け】RailsでAPI開発 Part.2](https://qiita.com/jiggaman0412/items/76e69083594bde06961b)の続きです。

今回は認可編になります。

# 概要
## ▼ 仕組み
前回認証をやりましたが、それは下記の2番目にあたる箇所です。
実際にクライアントからリクエストが来て複雑なアプリケーションを作っていくには下記のような順番で判別します。

1. ヘッダーにトークンが含まれてるかどうか
2. トークンが正しいものかどうか <- 認証
3. 認証したユーザーがアクセスできるリソースかどうか <- 認可

## ▼ 使用するもの
- Pundit

# 手順
## ① Punditの準備
まず、PunditをGemに追加してインストールしてください。

```text:terminal
bundle exec rails g pundit:install
```

## ② ApplicationControllerの準備
ここで、ヘッダーにトークンが含まれているかどうかの判定や、
含まれている場合に認証できるのかどうかの判定などを行います。

認可については、アクセス不可の場合の記述をこちらで行います。

```ruby:app/controllers/application_controller.rb
include ActionController::HttpAuthentication::Token::ControllerMethods
include Pundit

rescue_from ActiveRecord::RecordNotFound, with: :no_record
rescue_from Pundit::NotAuthorizedError, with: :no_authorization

def authenticate
 if request.headers[:HTTP_AUTHORIZATION] != nil
  current_user || no_authentication
 else
  no_header
 end
end

def current_user
 authenticate_with_http_token do |token, options|
  @current_user = User.find_by(token: token)
 end
end

def no_header
 render json: { error: 'No Header' }, status: 400
end

def no_authentication
 render json: { error: 'No Authentication' }, status: 401
end

def no_authorization
 render json: { error: 'No Authorization' }, status: 403
end

def no_record
 render json: { error: 'No Record' }, status: 404
end
```

## ③ 認可の設計
認証を突破したユーザーの中で、
ユーザー編集や削除は自分だけ（認証したユーザー自身）がアクセスできるように認可を設計します。

つまり、
`index`や`show`アクションは認証を突破した人誰もがアクセス可能ですが、
`update`や`destroy`アクションは認証を突破した人の中でも、
アクセスするリソースに入れる権限を持つ自分自身だけにPunditで制御します。

## ④ UserPolicyの作成
```ruby:app/policies/user_policy.rb
class UserPolicy < ApplicationPolicy
 def show?
  true
 end

 def update?
  record == user
 end

 def destroy?
  record == user
 end
end
```

`show`メソッドは誰でもアクセスできるようにしてますが、
`update`と`destroy`は認証ユーザーと合致しない限りはアクセスできないようにしてます。

## ⑤ Policyの呼び出し
```ruby:app/controllers/v1/user_controller.rb
before_action :authenticate, except: [:create]
before_action :set_user, only: [:show, :update, :destroy]

..

private
def set_user
 @user = User.find(params[:id])
 authorize @user
end

..
```

`show``update``destroy`を呼び出す、`set_user`で`authorize @user`とすれば、
アクセスしようとしているリソースのユーザーと認証ユーザーが合致しているかの判断ができます。

## ⑥ 確認
### `show`メソッド（認可なし）
1. トークンなしでアクセス
    2. `No Header`エラー
2. トークンあるけど、存在しないトークン
    3. `No Authentication`エラー
3. 存在するトークンだけど、アクセスするリソースのユーザーが保有しないトークン
    4. 成功
4. 存在するトークンかつ、アクセスするリソースのユーザーが保有するトークン
    5. 成功

`show`メソッドの場合は、認可は全て許可しているので認証ユーザーであれば値を返す。

### `destroy`メソッド（認可あり）
1. トークンなしでアクセス
    2. `No Header`エラー
2. トークンあるけど、存在しないトークン
    3. `No Authentication`エラー
3. 存在するトークンだけど、アクセスするリソースのユーザーが保有しないトークン
    4. `No Authorization`エラー
4. 存在するトークンかつ、アクセスするリソースのユーザーが保有するトークン
    5. 成功

`destroy`メソッドの場合は、認証ユーザーとリソースのユーザーが同一でないとアクセスできないので、
3の場合は`No Authorization`エラーが発生していればOK。

# まとめ
今回はPunditを使って認可を設定してみました。
僕は以前Gemを使わず自前で認可を設計していたことがあるのですが、
Controllerの中身が結構ごちゃごちゃになってしまうので困っていました。

Punditを使うとごちゃごちゃにならずPolicyファイルに綺麗にまとめられるため非常に利便性を感じました。

これで、認証・認可周りはかなりスッキリしたのではないかなと思います。

次回は外部からの攻撃など、セキュリティ周りをしっかりとみていきたいと思います。
プレゼンが苦手なエンジニアが参考にするべき3つの作成術

プレゼン資料を作る際に、僕がいつも参考にしているおすすめ資料を3つ紹介します。

## エンジニアのためのスライドデザイン実践講座 
https://speakerdeck.com/ken_c_lo/how-to-design-presentations-for-engineers

esaのデザイナーさんが、他の人が作ったスライドをいい感じにアレンジしていて、before/afterが見れます。

## 良質なデザインを作るため揃えるべき日本語フリーフォント10種類
https://www.baconjapan.com/entry/free_font_best

フォントから受ける印象は想像より大きく、普段意識しにくいところなので、改善する余地は大いにありそう。

## あなたの推しテクをもっと伝えるプレゼンテーション術
https://speakerdeck.com/tnagasawa/anatafalsetui-sitekuwomotutochuan-erupurezentesiyonshu-number-awsdevday

「3」をキーワードに**伝わるプレゼンテーション**の構成の仕方を学べます。

## おまけ
エンジニアも自分の考えをわかりやすく伝えるために、少しでもきれいなスライドを作りましょう。他にも参考になる資料があれば、教えてください。

計画・企画を多様な人から意見を聞けるサービス「[Renttle](https://renttle.jp)」を開発中です。ぜひ、使ってみて、レビューをください。
wgrib2 を macOS Mojave (v10.14) にインストールする

`wgrib2` というツールを macOS Mojave (v10.14) にインストールする手順を紹介します．

# wgrib2 とは?

`wgrib2` は気象データのフォーマットとして世界的に使われている [GRIB2形式（バイナリ）をテキストへ変換するツール](https://qiita.com/ShingoOikawa/items/77c837374721a2b945ba) です．アメリカ海洋大気庁(NOAA)が公開しています．

# 準備

[この記事](https://qiita.com/ysomei/items/12d6622bed030f6ac793)を参考に macOS Mojave 用にアレンジし直します．

アップル純正のデベロッパツールを使う関係で [Apple Developer Connection (ADC)](https://developer.apple.com) のアカウントを作っておく必要があります．無料で作れるので，まだ作っていない人は作っておいてください．

## Command Line Tools のインストール

macOS での開発用の純正コマンドラインツールをインストールしておく必要があります．コマンドラインツールは [アップルのデベロッパサイト](https://developer.apple.com/download/more/) にありますので，ダウンロードしてインストールしてください．macOS Mojave 用のコマンドラインツールは **Command Line Tools (macOS 10.14 for Xcode 10.1)** です．（for 以下は今後のアップデートで変化するかもしれません．）

これを機にXcodeもインストールしてしまっても良いと思います． [Xcode は Mac App Store からインストールできます．](https://itunes.apple.com/jp/app/xcode/id497799835?l=en&mt=12)

## Homebrew のインストール

`wgrib2` をインストールするにはFORTRANコンパイラが必要です．GCC (GNU Compiler Collection) を使うのが一番簡単なのでGCCを使いましょう．GCCを macOS にインストールするには [Homebrew](brew.sh) を使うのが近道なので，まずは Homebrew をインストールします．

```sh
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

もし既に Homebrew をインストール済みであれば，以下の手順でアップデートしておきましょう．

Homebrew のアップデート

```sh
$ brew update
```

インストールされたパッケージのアップデート

```sh
$ brew upgrade
```

## GCC のインストール

GCC (GNU Compiler Collection) をインストールします．

```sh
$ brew install gcc
```

これで `/usr/local/bin/gcc-8` と `/usr/local/bin/gfortran` がインストールされます．

# wgrib2 のインストール

GitHub で検索すると wgrib2 というリポジトリが見つかりますが，見向きもせずに以下の手順に従ってください．

## wgrib2 のダウンロード

次の手順でダウンロードしてください．

```sh
$ curl -o wgrib2_2.0.7.tgz http://www.ftp.cpc.ncep.noaa.gov/wd51we/wgrib2/wgrib2.tgz.v2.0.7
$ tar zxvf wgrib2_2.0.7.tgz
$ cd grib2
```

`wgrib2` のアーカイブを展開すると何故か `grib2` というディレクトリが現れますが，深く考えないことにします．

## makefile の書き換え

GNUツールに慣れた皆さんは `./configure` とやりたくなるところですが，ぐっと我慢して `makefile` を書き換えます．書き換えるのは以下の2行です．

### 書き換え前

```sh:makefile（書き換え前）
# can uncomment following two lines to use gcc/gfortran
# export CC=gcc
# export FC=gfortran
```

### 書き換え後

```sh:makefile（書き換え後）
# can uncomment following two lines to use gcc/gfortran
export CC=gcc-8
export FC=gfortran
```

`makefile` の他の箇所，また他のファイルを変更する必要はありません．環境変数の設定も必要ありません．

## make

`configure` スクリプトは**無い**ので，いきなりmakeします．

`wgrib2` のドキュメントには（BSD make ではなく）GNU make を使えと書いてありますが，macOS Mojave の `/usr/bin/make` は GNU make なので気にせずmakeしましょう．（macOS の `/usr/bin` には `awk` や `install` のようなFreeBSD由来のものとGNUプロジェクトのものが混在しています．）

```sh
$ make
```

`configure` スクリプトが走ったかのようなメッセージが出力されますが `makefile` は書き換えられません．待っていれば `wgrib2` がビルドされます．

最後に

```sh
$ ./wgrib2/wgrib2 --version
v0.2.0.7 12/2017  Wesley Ebisuzaki, Reinoud Bokhorst, John Howard, Jaakko Hyvätti, Dusan Jovic, Daniel Lee, Kristian Nilssen, Karl Pfeiffer, Pablo Romero, Manfred Schwarb, Gregor Schee, Arlindo da Silva, Niklas Sondell, Sam Trahan, Sergey Varlamov
```

というふうに実行できれば完了です．
PATHを通すの意味と通し方　.bash_profile

macにbrewなどで新しいアプリ（rbenv等）をインストールする時、あまり良く考えずにそのアプリの**コマンド**の**PATH**を通していましたが、「そもそもコマンドのPATHを通すってどういうことか」を調べてみました。
#PATHとは?

以下、開発環境はMacです。
PATHとは環境変数のひとつ。
環境変数とは、マシンの中のメモ帳みたいなもの。
コンソール(ターミナル)のどこからでも参照することができるメモ帳。

その中でも**PATH(環境変数)は実行ファイル(アプリケーション)の格納場所をメモしたもの。**


#コマンドとは?
実行ファイル（アプリケーション）のこと。 


```
/bin/ls
ls
上記は同じ効果を持つ。
```

例えば`ls`というコマンドの実行ファイルは/binディレクトリに格納されており、`/bin/ls`と入力するとアプリケーションが実行される。`/bin`をPATHに設定(通して)いれば、上記のようにフルパス`/bin/ls`を指定せずとも`ls`だけ入力しすれば`/bin/ls`と同じ実行がされる。
このように、コマンド(lsなどの実行ファイル)入力時にシェル(bashやzsh等)が実際に実行ファイルを探しに行く際に参照するところを**PATH**と言う。

#どんなPATHが設定されているか確認する方法
PATHは環境変数$PATHに設定されており、`echo $PATH`で確認できる。

```
$echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/sbin... #実行結果
```
縦に並べると、、

```
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
/usr/local/sbin
...
```
上記だと、`usr/local/bin`や`usr/bin`以下にあるアプリは省略コマンド(`ls`等)でコマンドを実行できる（PATHが通っている状態）


#実行ファイル(アプリケーション)の場所の確認方法
`which`で、指定したコマンドの実行ファイルがどこに格納されているのか確認できる。
たとえば`ls`はどこのパスにあるかというと、

```
$which ls
/bin/ls #実行結果
```
`/bin/`以下にあることがわかる。
そして`/bin/`はPATHに登録してあるので、`bin/ls`は`ls`で動く。
#目的とする実行ファイルが複数の違う場所にある場合
**先に見つかった方を実行する。**
PATHには優先度があり、`echo $PATH`で出力された左が優先される。
そのため、`/usr/local/bin/ls`と`/usr/bin/ls`のような同じ名前の実行ファイルが
存在する場合、`/usr/local/bin/ls`が実行される。

#PATHの通し方
PATHを通すにはホームディレクトリ直下にある設定ファイル.bash_profileに通したいPATHを記入する必要がある。
###.bash_profileを作成してvim等で編集する。

```
vi ~/.bash_profile
```


###もしくは、下記のコマンドを実行する
```
解説）$echo 'export PATH=/通したい/パス:$PATH' >> .bash_profile
例）$echo 'export PATH=/usr/hoge:$PATH' >> .bash_profile
```

#環境変数PATHを書き換えた後、有効にする
shellを更新する。

```
$source ~/.bash_profile
```
※うまくいかない場合があるのでその時はターミナルを再起動してください

PATHが通っているか確認。

```
$echo $PATH
```

```
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/sbin.../user/hoge#追加されていればOK
```
##以上です。
winコマンドでの文字化けを防止するラッパー

winコマンドと同名のラッパースクリプトを作る。中身はどれも同じ。
winコマンドと同じ要領で実行する。

```bash:ping
#!/bin/sh
$(basename $0).exe $@ 2>&1 | iconv -f CP932 -t UTF-8
```

```bash:ipconfig
#!/bin/sh
$(basename $0).exe $@ 2>&1 | iconv -f CP932 -t UTF-8
```

```bash:arp
#!/bin/sh
$(basename $0).exe $@ 2>&1 | iconv -f CP932 -t UTF-8
```

---
対話モードのあるものはwinptyが必要。ただしパイプでつなげなくなる。

```bash:
#!/bin/sh
winpty $(basename $0).exe
```


参考記事：http://takuya-1st.hatenablog.jp/entry/20110811/1313045543
個人的によく使うS3バケットのアクセス制限備忘

S3バケットのアクセス制限はいつも同じような感じの設定しか使わないのですが、毎回忘れて調べている状況なので、備忘としてテンプレートを残しておきます。


```:アクセス制限テンプレート
{
    "Version": "2012-10-17",
    "Statement": [
        {
【１】       "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
【２】　         "arn:aws:s3:::＜バケット名＞",
【２】           "arn:aws:s3:::＜バケット名＞/*"
            ],
            "Condition": {
                "StringNotLike": {
【３】               "aws:userid": "＜ロールID＞:*"
                },
                "StringNotEquals": {
【４】               "aws:username": "＜ユーザ名＞"
                },
                "NotIpAddress": {
                    "aws:SourceIp": [
【５】                   "＜IPアドレス＞/＜CIDR＞"
                    ]
                },
                "StringNotEqualsIgnoreCase": {
【６】               "aws:sourceVpce": "＜VPCエンドポイントID＞"
                }
            }
        }
    ]
}

```

### 【１】　基本ポリシーは拒否。以降、「Condition」で例外許可条件を指定します。


### 【２】　バケットの指定をします。

１つのバケットに対してバケット名のみ設定と「/*」付きの2つを設定します。


### 【３】　指定ロールのみを許可。

ロールで許可したい場合は[userid」にロールIDを指定します。
ロールIDはコマンド「aws iam get-role --role-name ＜ロール名＞」 で取得可能です。


### 【４】　指定ユーザのみを許可。


### 【５】　指定IPアドレスのみを許可。


### 【６】　指定VPCエンドポイントのみを許可。

「StringNotEquals」でも良いのですが、ユーザのみ許可で使用しているので、「StringNotEqualsIgnoreCase」を使用しています。
1つの条件で複数の要素を指定する方法は無さそうです。


### ※　上記各要素でユーザ名やIPアドレスを複数と設定したい場合は、カンマ区切りで指定します。
Magento2のDockerサンプルをCE2.3.0に対応させました

この記事は[Magento Advent Calendar 2018 - Adventar](https://adventar.org/calendars/3176)の17日目の記事です。

年に一度のアドベントカレンダーでMagento開発環境のサンプルを更新する習慣がついてきました。
昨年12月時点のバージョンは`2.2.3`でした。
今年は先月リリースされPWAとGraphQL API対応が気になる`2.3.0`です。

一昨年はVagrantで作成した環境を紹介していましたが、昨年はDocker環境を利用し準備までの時間を大幅に短縮できたのが記憶にあります。開発環境の基盤には変わりはなく今年もDockerでの紹介になります。

以下、参考にご利用ください。

- [kzkick2nd/magento2-on-docker](https://github.com/kzkick2nd/magento2-on-docker)

※実は同アドベントカレンダーでネタ被りをし、構成内容もほぼ同一でした。各設定の詳細内容は以下の記事を参考にされるのをオススメします。

- [ブログ - Magento2をDockerで動かすには？【Apache編】 | Magentoと越境ECの総合サポート Principleworks](https://principle-works.jp/blog/how2runm2ondocker-apache/)
- [ブログ - Magento2をDockerで動かすには？【docker-compose編】 | Magentoと越境ECの総合サポート Principleworks](https://principle-works.jp/blog/how2runm2ondocker-compose/)

## 更新内容
- ベースイメージを`php:7.0-apache`から`php:7.2-apache`に変更。
- ベースイメージ変更に伴って`libmcrypt-dev`を削除。
- 同、`libpng12-dev`を`libpng-dev`に変更。
- 必須要件`bcmath`を追加。
x-particleのライセンス開放方法

# はじめに
クラウドライセンスのX-Particleでライセンスをオーダーする場合
1オーダにつき、複数ライセンス分が入ったプロダクトIDが発行されます。

面倒なことに、C4Dはプラグイン起動時にライセンスと共に勝手に読み込まれるので、複数人で利用する場合に支障をきたす場合が多く、手法としては
①プラグインフォルダから除く
②ライセンスマネージャからライセンスを開放する
の２択になると思います。

今回はこの内②のオーソドックスなやり方を解説します。

・環境
　　Windows10 Pro
　　Cinema4D R19
　　X-Particle 4.0

# ライセンスマネージャの使い方
## ライセンス開放方法
1. Cinema4Dを起動する
2. ツールバーの「X-Particle」＞「Help and Support」＞「X-Particle License Manager」を開きます。　![image.png](https://qiita-image-store.s3.amazonaws.com/0/166400/122455eb-9043-ab9a-6205-a870b7610831.png)
3. License Managerの画面が次のように自分のユーザ情報等が出てくるまで待つ。　![C4D_02.PNG](https://qiita-image-store.s3.amazonaws.com/0/166400/911a44f7-1c9c-f5ac-8408-171c73e252dc.png)
4. 最下部の「Release License」を選択してライセンスを開放する。　![image.png](https://qiita-image-store.s3.amazonaws.com/0/166400/571359a0-61d9-ef7d-98d9-89c3334dc93d.png)
5. License Manager　で自分の情報がでなくなるのを待つ。![C4D_03.PNG](https://qiita-image-store.s3.amazonaws.com/0/166400/3d0bc406-c79e-356a-11ee-6ac0092d22d7.png)


## ライセンス取得方法
1. Cinema4Dを起動する
2. ツールバーの「X-Particle」＞「Help and Support」＞「X-Particle License Manager」を開きます。　![image.png](https://qiita-image-store.s3.amazonaws.com/0/166400/122455eb-9043-ab9a-6205-a870b7610831.png)
3. License Manager　で自分の情報が出ていないのを確認する。![C4D_03.PNG](https://qiita-image-store.s3.amazonaws.com/0/166400/3d0bc406-c79e-356a-11ee-6ac0092d22d7.png)
4. 最下部の「Allocate License」を選択してライセンスを取得する。![image.png](https://qiita-image-store.s3.amazonaws.com/0/166400/25710a6c-c5f5-964a-4456-b3b4d815c16a.png)
5. License Managerの画面が次のように自分のユーザ情報等が出てくるまで待つ。　![C4D_02.PNG](https://qiita-image-store.s3.amazonaws.com/0/166400/911a44f7-1c9c-f5ac-8408-171c73e252dc.png)

#さいごに
今後、Cinema4Dライセンスサーバ側でライセンスコントロールのテストをしていきたいと思う
gnuplotで線を徐々に描く

#環境

OS:Ubuntu 18.10
gnuplot: 5.2 patchlevel 2(Qt)

#ファイルからデータを読み込んでアニメーションで表示

$y = 2x$をアニメーションで表示

```:gnuplot
gnuplot> do for[i=0:100]{
more> plot [0:10] [0:20] "sample" using 1:2 every ::0::i with lines
more> pause 0.05
more> }
```

```:sample
0.000000 0.000000
0.100000 0.200000
0.200000 0.400000
略
9.800000 19.600000
9.900000 19.800000
10.000000 20.000000
```

![sample.gif](https://qiita-image-store.s3.amazonaws.com/0/265796/c0b25cf9-a687-469c-e649-7c19639a7c13.gif)



sampleの中に表示したい線の座標データがあれば簡単にアニメーション表示できる。
わざわざ座標データのファイルを読み込むのは面倒

#媒介変数を使った方法

gnuplotには媒介変数モードがあるのでそれを使います(他の方法があればコメントお願いします)

```:gnuplot
gnuplot> set param

	dummy variable is t for curves, u/v for surfaces
gnuplot> set xrange[0:10]
gnuplot> set yrange[0:20]
gnuplot> do for[i=0:100]{
more> set trange[0:i*0.1]
more> plot t,2*t with lines
more> pause 0.05
more> }
```

`set trange`で媒介変数の描画範囲を決めて`do for`でループしている。


![a.gif](https://qiita-image-store.s3.amazonaws.com/0/265796/2f41fec6-8319-8d17-68bf-a3220ae4737a.gif)


さっきのやつと見た目は変わらないけど座標データがいらないから便利

#C言語サンプル

```c:main.c
#define _GNU_SOURCE
#include<stdio.h>
#include<stdlib.h>

int main(){
    
    FILE *pipe = popen("gnuplot -persist\n", "w");

    if(pipe == NULL){
        fprintf(stderr, "popen error\n");
        exit(1);
    }

    fprintf(pipe, "set xrange [0:10]\n"
                  "set yrange [0:20]\n"
                  "set param\n"
                  "do for[i=0:100]{\n"
                  "set trange [0:i*0.1]\n"
                  "plot t,2*t with lines\n"
                  "pause 0.05\n"
                  "}\n");

    pclose(pipe);
    
    return 0;
}
```
GitHub 上の Jupyter Notebook 形式のファイルを Google Colaboratory で開くリンクを作成

GitHub 上で公開する **Jupyter Notebook 形式のファイルを Google Colaboratory で開くためのリンクを設置する方法** を解説します。


## サンプル

- [emoji-ime-dictionary/generate.ipynb](https://github.com/peaceiris/emoji-ime-dictionary/blob/master/generate.ipynb)

上のリンク先の Jupyter Notebook 形式のファイルの上部に、

> [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/peaceiris/emoji-ime-dictionary/blob/master/generate.ipynb)

というリンクがあり、クリックすることで Notebook を Google Colaboratory で開くことができます。

Google Colaboratory の方から GitHub 上の Notebook を指定して開くこともできますが、このようなリンクを設置しておくことでユーザーの手間を減らすことができます。もちろん自分のために用意しても便利です。

GitHub は Jupyter Notebook 形式のファイルのプレビューが可能なので Notebook の中にリンクを設置してもよいですし、README.md とかに書いておいても便利でしょう。


## リンクの作り方

```md
- [Open with Colab](https://colab.research.google.com/github/GITHUB_ID/REPO_NAME/blob/master/NOTEBOOK.ipynb)
```

- GITHUB_ID
- REPO_NAME
- NOTEBOOK

の3点を対象の Notebook に合わせて変更すればオッケーです。

Open in colab の SVG 画像は以下のようにして表示できます。

```md
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/peaceiris/emoji-ime-dictionary/blob/master/generate.ipynb)
```

[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/peaceiris/emoji-ime-dictionary/blob/master/generate.ipynb)



## Colaboratory なら開発環境の配布に困らない

Google Colaboratory でソースを開いてもらえば開発環境もセットで配布したようなものなので、ユーザーが手軽に Python script などを実行することができます。Docker や conda で用意するよりも手軽で多くの人が使えるので、Python のコードを共有したい時には Colaboratory 配布を考えてみてはどうでしょうか。
Springについて③

##この記事の目的
[Springについて②](https://qiita.com/haseesah/items/7ba212646733c0ccdc6f)の続きです。
今回はBeanの紐づけについて簡単にまとめます。

###Beanの紐づけとは？
前章、前々章ではどのオブジェクトがBeanとして振る舞うか？の指定とそれを保存しておくDIコンテナの振る舞いについてまとめました。
基本となるBeanの注入方法では、ContextConfigurationクラスに対して、Beanのクラスを引数にしてgetBeanメソッドを呼び出していましたが、＠Autowiredを用いたオートワイヤリングではどのようにBeanを特定しているのでしょうか？

###①型による解決
概要→利用する際に指定したクラスの型で判別する。


####使用方法
```Java:Config.class
@Congiguration
@ComponentScan
public class Config{
    @Bean
    HogeClass hogeClass(){
        return new HogeClass();
    }

    @Bean
    FugaClass fugaClass(){
        return new FugaClass();
    }
}
```

```Java:Injection.class

public class Injection{
    @Autowired   
    HogeClass hogeClass;

    @Autowired
    FugaClass fugaClass;
}
```

####問題点

指定した型のBeanが存在しない
　　　　　　⇒NoSuchBeanDefinitionExceptionが発生する

指定した型のBeanがコンテナに複数登録されている
　　　　　　⇒NoUniqueBeanDefinitionExceptionが発生する

特に、ある親クラスを継承したクラスが複数ある場合というのはプログラム上で往々にしてあり、その際にいちいちDIをする際にソースコードに子クラスのクラスをべた書きするのはDIの意味がなく、親クラスでBeanをしていするとNoUniqueDefinitionExceptionが発生する、、、といった事態になってしまいます。
これを解決するのが次の手段になります。


###②名前による解決
概要→Beanを定義する際に固有の名前を設定し、取り出すときはその名前で指定する


####使用方法
```Java:Config.class
@Congiguration
@ComponentScan
public class Config{
    @Bean
    HogeClass hogeClass(){
        return new HogeClass();
    }

    @Bean
    HogeClass fugaClass(){
        return new FugaClass();
    }
}
```

```Java:Injection.class

public class Injection{
    @Autowired
    @Qualifer("hogeClass")   
    HogeClass hoge;

    @Autowired
    @Qualifer("fugaClass")
    HogeClass fuga;
}
```

上記の場合、どちらもHogeClassを親に持つクラスの為、Qualiferにより名前で紐づけしないとエラーを生じる
名前を個別に指定したいときは下記のようにする

```Java:Config.class
@Congiguration
@ComponentScan
public class Config{
    @Bean(name = "hoge1")
    HogeClass hogeClass(){
        return new HogeClass();
    }

    @Bean(name = "fuga1")
    HogeClass fugaClass(){
        return new FugaClass();
    }
}

##次回予告
コンポーネントスキャンの中身やBeanのスコープをまとめていったん終了としたいです
WORD VBA テンプレート内の文字列置換マクロ

#ワード内の文章を置換

```vb
Sub mojiretuhenkan()
    
    Dim rbook As Object, rrow As Object
    Set rbook = GetObject(ActiveDocument.Path & "\置換テーブル.xlsx")
    
    With ActiveDocument.Content.Find
        For Each rrow In rbook.Worksheets(1).Range("検索置換セット").Rows
            If rrow.Cells(1).Value = "" Then Exit For
            
            .Text = rrow.Cells(1).Value
            .Replacement.Text = rrow.Cells(2).Value
            .Execute Replace:=wdReplaceAll
            
        Next rrow
    End With 'ActiveDocument.Content.Find
    
    rbook.Application.Quit
    Set rbook = Nothing
    
End Sub
```
ggezでサウンドを鳴らす

# 全文
```rust
extern crate ggez;

use ggez::conf;
use ggez::event;
use ggez::graphics;
use ggez::{Context, GameResult};
use ggez::audio;
use ggez::timer;

use std::env;
use std::path;

struct MainState {
    sound: audio::Source,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let sound = audio::Source::new(ctx, "/sound.ogg").unwrap();
        let _ = sound.play();
        let s = MainState {
            sound,
        };
        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
        if timer::get_ticks(ctx) % 10 == 0 {
            let _ = self.sound.play();
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx);
        graphics::present(ctx);
        Ok(())
    }
}

pub fn main() {
    let c = conf::Conf::new();
    let ctx = &mut Context::load_from_conf("super_simple", "ggez", c).unwrap();

    if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        ctx.filesystem.mount(&path, true);
    }

    let state = &mut MainState::new(ctx).unwrap();
    event::run(ctx, state).unwrap();
}

```

# 簡単な解説

```rust
struct MainState {
    sound: audio::Source,
}
```
定義部分。

```rust
let sound = audio::Source::new(ctx, "/sound.ogg").unwrap();
let _ = sound.play();
```
ggezプロジェクトに含まれている`sound.ogg`を読み込んで再生。

```rust
if timer::get_ticks(ctx) % 10 == 0 {
    let _ = self.sound.play();
}
```
以降、定期的に再生。なお、`timer::get_ticks`はイベントループが再生された数を返す。

# その他

### リピート再生

```rust
let mut sound = audio::Source::new(ctx, "/sound.ogg").unwrap();
sound.set_repeat(true);
let _ = sound.play();
```

### 一時停止・再開

```rust
sound.pause()
sound.resume()
```
### 停止

```rust
sound.stop()
```

### 状態確認
```rust
let is_playing = sound.playing()
let is_stopped = sound.stopped()
let is_paused  = sound.paused()
```
playingは`paused == false`かつ`stopped == false`

### 音量取得・変更

```rust
sound.volume()
sound.set_volume(2.)
```
デフォルトの音量は1.0。
2.0くらいまであげると音割れが発生した。
Apache Syncopeのインストール

やってみたのでメモ

# 前提条件

|OS・ミドルウェア|バージョン|
|:------|:------|
|OS|CentOS7|
|CPU|デュアルコア 2GHz|
|RAM|2GB|
|ディスク容量|100MB|
|Java|JDK 8|
|アプリケーションサーバ|Apache Tomcat 9|
|データベース|PostgreSQL 10.3|

# 手順
Java/PostgreSQL はインストール済みの状態でスタートします。

1. zipファイルをダウンロードします zipファイルは[Downloads](https://syncope.apache.org/downloads)から選択します

    ```
    # curl -LkvOf http://ftp.riken.jp/net/apache/syncope/2.1.2/syncope-standalone-2.1.2-distribution.zip
    ```

2. 破損がないか確認する

    ```
    # sha512sum syncope-standalone-2.1.2-distribution.zip
    dcfc77afb0985a5f51667d7f4f49a565697d15b5b1a0b400d2708ba38845fe85a3a7b24f8c4445488257b1f175d5010147a6fc4b9991df08059e0920cce37bf2  syncope-standalone-2.1.2-distribution.zip
    ```

3. zipファイルを展開する

    ```
    # unzip syncope-standalone-2.1.2-distribution.zip
    ```

4. `/opt`配下に展開したzipファイルを移動させます

    ```
    # mv syncope-standalone-2.1.2 /opt/apache-syncope
    ```

5. Apache Syncope 実行用ユーザを作成します

    ```
    # useradd syncope
    ```

6. 所有者を変更します

    ```
    # chown -R syncope:syncope /opt/apache-syncope
    ```

7. サービスファイルを設定します

    ```
    # vi /usr/lib/systemd/system/syncope.service
    ```
    
    ```syncope.service
    [Unit]
    Description=Apache Syncope Service
    
    [Service]
    Type=forking
    User=syncope
    ExecStart=/opt/apache-syncope/apache-tomcat-9.0.12/bin/startup.sh
    ExecStop=/opt/apache-syncope/apache-tomcat-9.0.12/bin/shutdown.sh
    
    [Install]
    WantedBy=multi-user.target
    ```

8. Apache Syncope サービスを起動します

    ```
    # systemctl start syncope
    ```

9. 管理コンソールのURLにアクセスします

    ```
    http://<IPアドレス>:9080/syncope-console
    ```
    
    |項目|値|
    |:-----|:-----|
    |ユーザ名|admin|
    |パスワード|password|
    
    ![Apache_Syncope_login.png](https://qiita-image-store.s3.amazonaws.com/0/34297/75eeab83-8da5-ddce-e43b-a0cd8f77fde6.png)

10. ログインに成功すると次の画面になります
![Apache_Syncope_Admin_Dashboard.png](https://qiita-image-store.s3.amazonaws.com/0/34297/4d8aa692-ba98-d7e3-93d4-aeb9c5e1a7d2.png)


# 参考
- [Apache Syncope - Getting Started](http://syncope.apache.org/docs/2.1/getting-started.html#system-requirements)
- [Apache Syncope - Paths and Components](http://syncope.apache.org/docs/getting-started.html#paths-and-components)
- [GitHub - syncope/standalone/src/main/resources/
](https://github.com/apache/syncope/tree/master/standalone/src/main/resources)
我々システムエンジニアは心理学に関してはズブの素人だ。エンジニアリング組織論への招待。


「エンジニアリング組織論への招待」を読んでいてそう思う。

- この本には、システムエンジニアにとっては、目の覚めるような心理的な話が書かれている。
- その扉は心理学の奥深い世界につながっていて、本1冊でカバーできるような範囲ではない。
- だんだんと心理学的領域が、人間の根本に関する、とてもとても巨大な関心領域であることに気付き始まる。
- だけど何もしないよりましだ。僕らは心理学者にはなれないけれど、半分心理学者的なシステムエンジニア、マネージャーにはなれるはずだ。
- 「美しすぎる弁護士」みたいな感じで。「魔法使いに転職した戦士」みたいな感じで。
- いやむしろ僕らは、プログラミングができる心理学者になるべきなのかもしれない
。まったく逆の側からのアプローチで。
- それぐらいに「人間」という関心分野は巨大なものである。奥深いものである。生半可に1時間で学べるようなものではない。セミナーに数回通って身につけられるようなものではない。
- エンジニアリング、プログラミングと同じぐらい、いやそ数百倍の奥深いがあると理解しつつ戯れ遊ぶ未来であれ。



[組織論への招待 yumainaura - Google Search](https://www.google.co.jp/search?ei=1oQXXPjGH5OroATJkIfIBA&q=%E7%B5%84%E7%B9%94%E8%AB%96%E3%81%B8%E3%81%AE%E6%8B%9B%E5%BE%85+yumainaura&oq=%E7%B5%84%E7%B9%94%E8%AB%96%E3%81%B8%E3%81%AE%E6%8B%9B%E5%BE%85+yumainaura&gs_l=psy-ab.3...8578.9464..9524...0.0..0.337.1588.0j6j1j1......0....1..gws-wiz.......0i71.3vFqM1h5GpM)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/7978b878-958e-d5e1-99cf-9dec335fa78e.png)



# あわせて読みたい

- [【エンジニアリング組織論への招待】を10~15分で読めるように1万文字程度でまとめてみた - Qiita](https://qiita.com/kamesennin/items/89d479112554a6f9d038)
- [エンジニアリング組織論への招待：リファレンスガイド第１章/第２章 - Qiita](https://qiita.com/hirokidaichi/items/195d42ee056ea85a3150)








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->