OmniAICreator/Qiita-1.07M huggingface dataset:
RubyのCSV処理で気をつけるポイント

[トレタ Advent Calendar 2017](https://qiita.com/advent-calendar/2017/toreta)の7日目記事です。
サービスをスタートして4年がたち、初期のころにつくったCSV処理のコードを最近いくつか修正しました。そのポイントについてまとめようと思います。

こんなコードを

```rb
CSV.parse(NKF.nkf('-w', params[:file].read)).each do |i|
  process(i)
end
```

こういうふうにするようにしました。

```rb
open(params[:file].tempfile, 'rt:UTF-16:UTF-8', undef: :replace, invalid: :replace, replace: '') do |f|
  CSV.new(f, col_sep: "\t").each do |line|
    process(line)
  end
end
```

## ポイント1: 全データをメモリに載せない
- CSV.parse/CSV.read/CSV.tableあたりは全データがメモリにのってしまうので使わないようにします。
- その点ではCSV.foreachもよいですが、ポイント2と3の文字コードや改行コードを考えるとCSV.newのほうが都合がいいです。
- Rails等でファイルアップロードのデータを受け取るとき場合には、params[:file].tempfileを使えばファイルから読みだすことができて全データがメモリに載るのをさけることができます。
- ふつうにファイルからデータを読めばいいケースではたんにファイル名を指定します。


## ポイント2: 文字コード
- NKF.nkfはstringを入力にとるのでポイント1を考えるとつかいにくいので、Encodingで変換します。
- コード上はUTF-16のデータをうけとるようになっていますが、要件に合わせて変更します。この例でUTF-16を使っている理由はポイント4で説明します。
- NKFと違ってEncodingの場合は変換時にundefやinvalidの例外が起こるでその場合の処理を指定します。(UTF-16からUTF-8であれば必要ないかも)


## ポイント3: 改行コード
- CSVライブラリはカラムのなかに複数の改行コードが混じっていると```CSV::MalformedCSVError: Unquoted fields do not allow \r or \n ```がおきます。
- これはrow_sepオプションで区切りの改行文字を指定することで回避できますが、そもそも複数種類の改行のデータを持っていいても困ることのほうが多いので、\nに正規化します。
- Encodingの指定でrtを指定するか、universal_newlineオプションを使うと\nに正規化することができます。

## ポイント4: Excelからデータを想定する
- 残念ながら世の中の表データの大半はExcel取り扱われています。
- Excelを使っているひとにCSVでくださいというと、たいていの場合Shift_JIS(CP932)のデータきてしまいます。
- これはExcelでCSV書き出しをするとそうなるからで、UTF-8のCSVでほしい思っていてもなかなかそういうわけにはいきません。
- また、Shift_JISで書き出されてしまうと、元データにShift_JISの範囲外の文字が入っていた場合にそれが失われていて、再変換したところで元データは手にはいりません。
- こういうことを避けるために、ExcelではCSVではなく、Unicodeテキストという形式で保存してデータをもらうようにします。
- UnicodeテキストのデータはUTF-16のTSV(タブ区切り)なので、それを受け取ることを想定して書いておきます。

今回、CSVを書き出すケースについては書いてませんが、同じように気をつけたほうがいい思います。あらかじめこういう点を考慮したコード書くのは手間ですが、あとあと文字コードやメモリ消費量でトラブルになる可能性をを考えると、はじめから少し手間をかけたほうがいいかなと思っています。
処理の委譲とDIについて

処理の委譲とかDIについての記事をいくつか読んだので、具体的な実装を追って理解を深めてみたいと思います。
DIについては軽く触れる程度となります。


## 複雑なコードができてしまう事例

例として、APIを呼び出してその結果を取得する処理を書いてみましょう。

```csharp
IEnumerator GetItems()
{
    var url = "https://qiita.com/api/v2/items";
    var www = new WWW(url);
    yield return www;

    var result = Json.Deserialize(www.text);
    Debug.Log(result[0]["title"]);
}
```

戻り値のJsonをパースして、最初の記事のタイトルを出力する処理ができました。

さて、ここで戻り値の型がMessagePackの場合もあるとします。シンボルを定義して処理の書き分けをしてみましょう。

```csharp
IEnumerator GetItems()
{
    ...
#if MSGPACK_API
    var result = Msgpack.Deserialize(www.text);
#else
    var result = Json.Deserialize(www.text);
#endif
    Debug.Log(result[0]["title"]);
}
```

なんと、本番環境では戻り値をgzip圧縮して暗号化することにする、と連絡がありました。対応してみましょう。

```csharp
IEnumerator GetItems()
{
    ...
#if MSGPACK_API
    var bytes = www.bytes;
#if RELEASE_MODE
    bytes = GZipDecode(Decrypt(bytes));
#endif
    var result = Msgpack.Deserialize(bytes);
#else
    var result = Json.Deserialize(www.text);
#endif
    Debug.Log(result[0]["title"]);
}
```

……往々にして、このようなコードが出来上がることは良くあります。


## 処理の委譲

さて、ここで処理の委譲を活用していきましょう。
`WWW`を引数に`result`を取り出す処理が複雑になってしまっていたので、そこをインターフェース化します。

```csharp
interface IDeserializer
{
    APIResult Deserialize(WWW www);
}
```

戻り値がJsonの場合、MessagePackの場合、本番環境の場合の3通りの`Deserializer`を作ってみます。

```csharp
class JsonDeserializer : IDeserializer
{
    public APIResult Deserialize(WWW www)
    {
        return Json.Deserialize(www.text);
    }
}

class MsgPackDeserializer : IDeserializer
{
    public APIResult Deserialize(WWW www)
    {
        return Msgpack.Deserialize(www.bytes);
    }
}

class APIDeserializer : IDeserializer
{
    public APIResult Deserialize(WWW www)
    {
        var bytes = GZipDecode(Decrypt(www.bytes));
        return Msgpack.Deserialize(www.bytes);
    }
}
```

`IDeserializer`を利用して、先ほどの処理を書き直してみましょう。

```csharp
IDeserializer deserializer;

IEnumerator GetItems()
{
    ...
    var result = deserializer.Deserialize(www.text);
    Debug.Log(result[0]["title"]);
}
```

`#if`による処理の分岐が消えてスッキリしました！
また、JsonやMessagePack、gzip展開などの処理はIDeserializerが行うことになったため、`GetItems()`はそれらに依存しなくなりました。


## DIについて

先ほどの例では`deserializer`の初期化が省略されていました。これはどこかで定義しておく必要があります。
`deserializer`を代入する処理まで書いた例を見てみましょう。

```csharp
class APIClient
{
    public static IDeserializer deserializer;

    public IEnumerator GetItems() { ... }
}

class Program : MonoBehaviour
{
    public void Start()
    {
#if RELEASE_MODE
        APIClient.deserializer = new APIDeserializer();
#elif MSGPACK_API
        APIClient.deserializer = new MsgpackDeserializer();
#else
        APIClient.deserializer = new JsonDeserializer();
#endif

        var client = new APIClient();
        StartCoroutine(client.GetItems())
    }
}
```

`deserializer`を外部から代入できるようにして、初期化時に利用する`IDeserializer`を選択して代入しています。
実はこれはDIパターンとして成立していて、フレームワークなどは利用していませんがDIを実現しています。

このように、場合によって処理が変わる、依存関係をなくして疎結合にするといったことを実現するためにDIが利用されます。
Unityの場合DIフレームワークとしてZenjectというものがあり、単純なDIの他にも便利な機能があるので使い方を覚えてみるのも良いと思います。
Pythonで並列処理（旧）

# これは古いです

https://qiita.com/miyagaw61/private/11ef458371d1c31502fe
こっちを見てください

# 方法

```python
from threading import Thread
from threading import Barrier

def function01(barrier, arg1, arg2):
    hoge()
    barrier.wait()
    fuga()

def function02(barrier, argA, argB):
    foo()
    barrier.wait()
    bar()

barrier = Barrier(<threads num>)
threads = []

t = Thread(target=function01, args=(barrier, arg1, arg2))
t.start()
threads.append(t)

t = Thread(target=function02, args=(barrier, argA, argB))
t.start()
threads.append(t)

for t in threads:
   t.join()
```

Example

```python
from threading import Thread
from threading import Barrier
from time import sleep

def function01(barrier):
    print('START function01 !')
    barrier.wait()
    for i in range(5):
        sleep(0.5)
        print('A')
    print('FINISH function01 !')

def function02(barrier):
    print('START function02 !')
    barrier.wait()
    for i in range(5):
        sleep(0.5)
        print('B')
    print('FINISH function02 !')

def function03(barrier):
    print('START function03 !')
    barrier.wait()
    for i in range(5):
        sleep(0.5)
        print('C')
    print('FINISH function03 !')

barrier = Barrier(3)
threads = []

t = Thread(target=function01, args=(barrier,))
t.start()
threads.append(t)

t = Thread(target=function02, args=(barrier,))
t.start()
threads.append(t)

t = Thread(target=function03, args=(barrier,))
t.start()
threads.append(t)

for t in threads:
   t.join()

# >>> START function01 !
# >>> START function02 !
# >>> START function03 !
# >>> B
# >>> A
# >>> C
# >>> B
# >>> A
# >>> C
# >>> B
# >>> A
# >>> C
# >>> B
# >>> A
# >>> C
# >>> B
# >>> FINISH function02 !
# >>> A
# >>> FINISH function01 !
# >>> C
# >>> FINISH function03 !
```
coincheckのpythonライブラリに取引履歴全件が取れる機能を追加した

coincheckのpythonライブラリに取引履歴全件を取れる機能がなかったので追加したおはなし

ライブラリ
https://github.com/kmn/coincheck

背景
coincheckのライブラリで取引履歴取ろうとすると件数制限だか期間制限だかで全量取れない。
ページネーションのメソッド使えばとれそうだけど、ライブラリが対応してない。
⇒ライブラリを改造するぞ！

```py3:order.py
    # 履歴全件返すメソッドを追加
    def historyall(self):
        ''' show payment historyall
        '''
        url= 'https://coincheck.com/api/exchange/orders/transactions_pagination?limit=25'
        headers = make_header(url,access_key=self.access_key,secret_key=self.secret_key)
        r = requests.get(url,headers=headers)
        res = json.loads(r.text)
        ret = []
        while True:
            if len(res['data']) > 0:
                ret.extend(res['data'])
                nextid = res['data'][len(res['data'])-1]['id']
                while True:
                    try:
                        headers = make_header(url + '&starting_after=' + str(nextid),access_key=self.access_key,secret_key=self.secret_key)
                        r = requests.get(url + '&starting_after=' + str(nextid),headers=headers)
                        res = json.loads(r.text)
                        if res['success'] == False:
                            time.sleep(1)
                            continue
                        break
                    except:
                        time.sleep(1)
                        continue
                continue
            else:
                break
        return ret

```

きれいじゃないし恥ずかしいのでコミットはしません。
python勉強中につき、もっとかっこいい実装できれば教えてください。
python setup.py install後のconsole_scriptでpkg_resources.DistributionNotFound: The '{package_name}=={version}' distribution was not found and is required by the application

pyenvを使用している時にこのエラーに遭遇することがある。
その場合は、以下の対応で対処することができる。

- `/usr/local/bin/{console_script_name}`のシェバンを`#!/usr/bin/python`から`#!/home/{user_name}/.pyenv/shims/python`に変更

- もしくは、次のコマンドを実行することでも解決する。

```
mv /usr/bin/python /usr/bin/python.bak
ln -s /home/miyagaw61/.pyenv/shims/python /usr/bin/python
```
apt update で 404  Not Found もしくは Updating from such a repository can't be done securely, and is therefore disabled by default. もしくは W: Failed to fetch hogehoge Could not resolve host: hogehoge

add-apt-repositoryで変なものを入れてしまった可能性がある。
その場合は、次のコマンドで治る。

```bash
$ cd /etc/apt/sources.list.d
$ sudo rm -rf ${失敗してるrepository}
$ sudo apt -y update
```
【JavaScript】配列を for in で扱わないほうがよい

よく言われていることですが、JavaScriptで`for in`ループを使うときは注意が必要です。
`for in` は、ただの `for` と違い、オブジェクトのプロパティがループの対象になるためです。
特に配列だと危険性が増します。

```js
// 例えばこんな配列があって、、
var arr1 = ['a1', 'a2', 'a3'];
var arr2 = ['b1', 'b2', 'b3'];
var arr3 = ['c1', 'c2', 'c3'];

// さらに１つの配列に格納されていて、、
var arr = [arr1, arr2, arr3];

// すべての配列のひとつ目を取得したい
for (i in arr) {
    console.log(arr[i].shift());  // "a1" "b1" "c1"
}
```

ここで`for in`の前で`arr`に関数を追加した場合、エラーが発生します。

```js
arr.myFunc = function () {
    return 0;
}

for (i in arr) {
    console.log(arr[i].shift());  // "a1" "b1" "c1" "TypeError: arr[i].shift is not a function..."
}
```

これは`prototype`に対しての追加でも同様です。

```js
Array.prototype.myFunc = function () {
    return 0;
}

for (i in arr) {
    console.log(arr[i].shift());  // "a1" "b1" "c1" "TypeError: arr[i].shift is not a function..."
}
```

どうなっているかというと、インデックスに`myFunc`がはいってきます。

```js
for (i in arr) {
    console.log(i);  // "0" "1" "2" "myFunc"
}
```

素直に`for`ループで書くほうが安全です。

```js
// 配列の length は 3
console.log(arr.length); // 3

for (var i = 0; i < arr.length; i++) {
  console.log(arr[i].shift());  // "a1" "b1" "c1"
}
```

だれがどこで配列を拡張するかわかったもんじゃないです、はい。
MySQLからMySQLi,PDOへの書き直し



#はじめに
この記事は文系出身の初心者([@azu369yu](https://qiita.com/azu369yu))が
PHPとMySQL学習をした際の忘備録として作成した記事となります。
その為、間違った情報が含まれている可能性があることを念頭に参照してください。
より良い方法があればコメントでお教え頂ければ幸いです。


#なぜ書き換える必要が？
mysql関数はphp5.5以降は非推奨とされており、php7.0から廃止されてしまったため。
主に[SQLインジェクション](https://ja.wikipedia.org/wiki/SQL%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3)への対策とその防止などが理由に挙げられる。
上記により、php7.0以降の環境下では、今までmysql関数で書かれてきたコードを書き直す必要がある。
コードの書き換えには、mysqlの拡張版であるmysqli(mysql improved)を使用するか、より汎用性の高い
[PDO](https://ja.wikipedia.org/wiki/PHP_Data_Object)(PHP Data Object)を利用することができる。

##mysqliでの書き換え
以前まで使われていたmysql関数に少し変更を加えるだけで利用できる。
オブジェクト指向が取り入れられ、データベース接続にクラスを使用する。

```ruby:mysqli
    // 1. 変数の宣言
	$host = "localhost";
	$user = "root";
	$pass = "****";
	$db   = "test";
	$test = "MySQLi_Result: ";

	// 2. mysqliでデータベース接続
	$mysqli = new mysqli($host, $user, $pass, $db);
	if ($mysqli->connect_error){
		error_log($mysqli->connect_error);
		exit;
	}

	// 3. SQL文を実行、表示
	$sql = "SQL文";
	$sqlq = $mysqli->query($sql);
	if(!$sqlq){
		error_log($mysqli->error);

		exit;
	}
		while($row= mysqli_fetch_array($sqlq)){
			echo $test;
			echo $row['col1'];	
	}
   
	// 4. データベースから切断
	$mysqli->close();

	
```

    


##PDOでの書き換え
MySQLのみならずその他のデータベースでも少し記述を変更するだけで使用できる。
メンテナンスや汎用性を残すならこちらを利用していくほうが良いのかも。

``` Ruby:PDO

    // 1. 変数の宣言
	$dsn  = 'mysql:dbname=test;host=localhost';
	$user = "root";
	$pass = "localhost";
    $test = "PDO_Result:";

    // 2. try&catchを使いつつPDOでデータベース接続
    try{    
	    $pdo = new PDO($dsn,$user,$pass);
    } catch (PDOException $e) {
        exit('データベースに接続できませんでした。' . $e->getMessage());
    } 


    // 3. SQL文を実行、表示
    $stmt = $pdo->query('SQL文');

    if (!$stmt){
        $info = $pdo->errorInfo();

        exit($info[2]);
    }
        while($data= $stmt->fetch(PDO::FETCH_ASSOC)){
            echo $testName;
            echo '<p>'. $data['col1'] ."</p>\n";
	}
	
    // 4. データベースから切断
    $pdo = null;
    
```

#  参考サイト
[PHPLabo] (http://www.php-labo.net/tutorial/class/pdo.html)さん
[@from_kyushu](https://qiita.com/from_kyushu/items/0023a2b0816f82e1740f)さん- MySQL関数からMySQLi関数への移行作業メモ
どうしてHerokuを選んだか 〜 テンマドの場合

## はじめに

私は今まで、webサービスのインフラ（まだクラウド環境がない時代のことです）の面倒を見たり、AWSを初めとしたクラウド環境の構築をしたりしてきました。しかし現在、自分の会社でメインで使っているのはHerokuです。どうしてHerokuを選ぶに至ったのか、経緯についてお話しします。

## 背景

現在私は自分で会社（[合同会社テンマド](https://10mado.jp)）を経営しています。事業としては2つあって、1つはビジネス支援事業。社外CTOや技術顧問などのアドバイザー業と、いわゆる受託のお仕事をしています。もう1つはサービス開発事業。[iruca](https://iruca.co)や[mimemo](https://mimemo.io)、[conasu](https://conasu.co)など、webサービスを中心に企画・開発・運営を行っています。

## インフラで楽をしたい

webサービスを作ることを決めたとき、初めに考えたのはプログラミング言語やフレームワークのことでした。でもすぐに、どこでその運用をするのか考えないといけなくなります。

選択肢は多いです。最初のwebサービス（conasu）を作るときは、手慣れたPHPで作ろうと考えていました。PHPの場合、格安のレンタルサーバーですら動作環境が用意されていますし、VPSを利用しても、AWSを利用してもよいのです。

ただ、今のところ、100%のリソースを自社サービスに割けるわけではありません。ビジネス支援事業の割合が大きいので、その時間の合間を縫って開発したり、メンテナンスしたりしなければいけないわけです。

そう考えると、例えばOSやミドルウェアのメンテナンス、アップデートを考えなければならないのは面倒なことでした。できることならそこに手はかけたくありません。プロダクトとしてのwebサービスを作ることに集中したい。その思いが強くありました。

## Herokuを選んでみて

そうしたとき、Rubyコミュニティーで使われ始めていたHerokuを思い出したのです。調べてみると、PHPにもきちんと対応していました。しかもバージョンを選べたり、必要な拡張（extension）を入れるための仕組みもcomposerをベースにしっかりしたものが用意されています。

最初、東京リージョンを選択できないので、レイテンシが気になりました。USリージョンを選択したものの、どうしても往復の時間はかかります。でも実際のwebアプリケーションを試しに動かしてみたら、体感的にそこまで気になるような時間がかかってしまうようなことはありませんでした。

PostgreSQLやRedisといったアドオンが用意されていて、すぐに使えるのも大きなメリットです。SendgridやPapertrailなど、機能を簡単に増やしていけるのもとても助かります。

そして何より、[The Twelve-factor App](https://12factor.net)の考え方に則ってwebアプリケーションを作っていくという考え方は、当時のPHP開発の中では画期的なものでした（今でこそ当たり前になっていますが）。

The Twelve-factor Appの考え方がもたらすものは、コードのシンプルさだけではありません。例えば将来的にHerokuではないプラットフォームで動かすことになったとしても、ちょっとした環境さえ整えてあげれば動かすことができるようになります。

今はHerokuで動かしていても、将来的にレイテンシなどを考えてAWSに移設することは十分にあり得ます。webアプリケーションとしてのポータビリティーが確保しやすいというのは、とても魅力的なことでした。

## まとめ

そういうわけで、Herokuを選んでwebサービスを始めました。

その後に作られたwebサービス（iruca、mimemo）はPHPではなくNode.jsで作られています。これもHerokuのおかげで、特段インフラに気を遣うことなく違うプログラミング言語を選ぶことができた例だと言えるでしょう。

例えば100%自社サービスの開発に時間を当てられたり、専任のインフラ担当のエンジニアがいるような環境であればまた違った選択をしたかもしません。でも現在の状況を考えると、Herokuが一番使いやすかった、ということです。

この先、例えばDockerのコンテナとしてwebプリケーションを動くようにしていけば、ポータビリティーはさらに高まるでしょう（Herokuの元々の仕組みを使うより面倒は増えてしまいますが）。時代がHerokuに追いついてきた、ということかもしれませんね。
OpenStack SydneyでLT発表されたCyborgのまとめ


## 2018.10.19追記

Intel FPGA Technology Day2018でNTT ATさんが発表されたとおり，
OpenStack Cyborgを使ってIntel PAC(FPGAカード)を管理するデモが行われました．
CyborgとOPAE(IntelのFPGAを制御するドライバ群)との連携が苦労されたとのこと．

今後に期待ですね!

#　はじめに

- OpenStack SydneyでLT発表された cyborg projectについてピックアップ
- 実際にインストールした(動くとは言っていない)
- ざっくりと書いているため間違いなどございましたら，お気軽にご連絡ください

## OpenStack Cyborg とは
[Youtubeリンク](https://www.youtube.com/watch?v=DXA0c62R4jI&t=259s)

> 元々，LT発表予定の方が来られなかったので代理の方が発表されていた
> 質問はIRCへ，とアナウンス

FPGAやGPUなどのアクセラレータをOpenStackで扱えるようにするプロジェクト
CyborgはもともとNomad(ノマド) と呼ばれるプロジェクトだった．

電話会社から来た要件が背景の一部にあり，
OPNFV DPACC project / ETSI NFV ISGを対処するためにNomad が設立された．
しかしNomadで定められた目標が限定的で，
OpenStackコミュニティ内での長い議論から
Cyborgプロジェクトが設立された

## Cyborgのユースケース例(オペレータ側)
### 実際に操作するコマンド例

- アクセラレータの列挙(リスト表示)

    `cyborg accelerator list --feature-tag DEEP_LEARNNING`

    ディープラーニングに特化したアクセラレータを列挙する機能？

- アクセラレータの識別と探索

    `cyborg accelerator discover`

- インスタンスにアクセラレータをアタッチ/デタッチ

    `cyborg accelerator attach --instance-id FPGA_VF_1`

- アクセラレータのドライバのインストール

    `cyborg accelerator install --driver-id SPDK_Driver`

## アーキテクチャ
アーキテクチャはOpenStackの他のプロジェクトと似ている, らしい

<img width="806" alt="cyborg-architecture.png" src="https://qiita-image-store.s3.amazonaws.com/0/80918/b14e45a8-4b3b-50eb-0dbf-28fb9f05452d.png">
> 上記画像はCyborgのRepositoryから引用

- REST APIインタフェース
- バックエンドにはDBを使用
- 各種ドライバ(現時点では，generic stub driverのみ)

## Pike リリース

- Basic frameworkをリリース
   -  REST API
       -  GET /accelerators
       -  GET /accelerators/{uuid}
       -  POST /accelerators
       -  PUT /accelerators/{uuid}
       -  DELETE /accelerators/{uuid}
   -  conductor & agent
   -  Devstack plugin
   -  generic stub driver

## Installation

最近devstack pluginが公開され，
devstackで簡単にインストール出来るようになった

```
enable_plugin cyborg git://git.openstack.org/openstack/cyborg master
```

> 2017/12/05現在 masterで動くことを確認．stable/pikeはインストール失敗する．

`cyborg-agent` `cyborg-api` `cyborg-conductor` `cyborg-dbsync`
がコマンドとしてインストールされる．

(6行目を除いて)中身は全て同じであり，

```
#!/usr/bin/python
# PBR Generated from u'console_scripts'

import sys

from cyborg.cmd.api import main

if __name__ == "__main__":
    sys.exit(main())
```

だったので現時点ではモック?(自信なし)
使い方が分からず...

`ImportError: No module named cyborg.cmd.api`とか言われるので，
ライブラリが見つけられていないかも

## アーキテクチャロードマップ
    ライトグリーンは既に実装済み
    グリーンはQueenリリースまでに行う優先事項
    赤色はサポート外 (GPUドライバとか)

<img width="855" alt="map.png" src="https://qiita-image-store.s3.amazonaws.com/0/80918/481958b0-1a6d-e854-b6e1-31752a5cd86e.png">

> youtubeの動画から引用

## Queens リリース
### Queens初回リリースの見通し
- Denver PTG discussion
- 2つの優先事項の実行，完遂
    - Nova (Placement) Interaction
    - 少なくとも1つのバックエンド環境でend to end 機能テスト

## オープンコミュニティ
    Huawei, Red Hat, NEC, Fujitsu, SUSEなど各社集まってプロジェクトが進行中
strictatime と find を使ってどのファイルがビルドに使われたかを調べる

# やりたいこと

ビルド(など)の処理の際に実際にどのファイルが使われているか知りたいことがあります。

例えばこんなケースです。

- 複数のビルドコンフィギュレーションがある大きなプロジェクトで、実際のプロダクトに使われているファイルを知りたい
    - プロダクトに関するコードメトリクス情報を収集するのに関係ないファイルは外したい、とか
- もっと簡単に、古くなって既に使われていないファイルを削除したい、とか。

単純なやり方ですが、ファイルシステムの atime で調べられることがあります。

# マウントオプションの変更

atime はパフォーマンスを悪化させるため、最近は `relatime` や `noatime` でマウントされていることが多いと思います。

手元の Ubuntu 16.04 LTS では

    $ mount | grep sdb 
    /dev/sdb1 on /mnt type ext4 (rw,relatime,data=ordered) 

のようになっていました。 
atime を有効にするため、`strictatime` で remount します。

    $ sudo mount -o strictatime,remount /mnt 
    $ mount | grep sdb 
    /dev/sdb1 on /mnt type ext4 (rw,data=ordered) 

これで有効になりました。
試してみます。 atime の確認には `stat(1)` コマンドを使うのがお手軽でしょう。

```
$ touch hello 
$ stat hello 
  File: 'hello' 
  Size: 0 Blocks: 0 IO Block: 4096 regular empty file 
Device: 801h/2049d	Inode: 256837 Links: 1 
Access: (0664/-rw-rw-r--) Uid: ( 1000/testuser) Gid: ( 1000/testgroup) 
Access: 2017-12-05 14:56:04.081279945 +0900 
Modify: 2017-12-05 14:56:04.081279945 +0900 
Change: 2017-12-05 14:56:04.081279945 +0900 
 Birth: - 
$ cat hello 
$ stat hello 
  File: 'hello' 
  Size: 0 Blocks: 0 IO Block: 4096 regular empty file 
Device: 801h/2049d	Inode: 256837 Links: 1 
Access: (0664/-rw-rw-r--) Uid: ( 1000/testuser) Gid: ( 1000/testgroup) 
Access: 2017-12-05 14:56:20.369457030 +0900 
Modify: 2017-12-05 14:56:04.081279945 +0900 
Change: 2017-12-05 14:56:04.081279945 +0900 
 Birth: - 
```

うまく atime が更新されているようです。

# find

find には `-anewer` というオプションがあります。(GNU find 4.7.0 で確認)

```
      -anewer file
              File  was  last accessed more recently than file was modified.
              If file is a symbolic link and the -H option or the -L  option
              is  in  effect,  the  access  time of the file it points to is
              always used.
```

これを使います。ビルド処理であればこんな感じです。

1. ソースコードを取得(更新)
2. `touch STARTTIME`
3. ビルド(など)
4. `$ find . -anewer STARTFILE -print` などとしてビルドの過程で参照されたファイルのリストを取得

この方法が使えるかどうかはもちろんビルドシステム次第です。全てのファイルの内容を見に行ってしまうような仕組みだと使えません。

# まとめ

atime と find を使って、ビルド(など)の処理の際に実際にどのファイルが使われているか調べる方法を紹介しました。

ごく単純な内容ですが、最近は atime が (毎回は) 更新されない環境が多いと思うのであえて書いてみました。
FizzBuzz on Windows/macOS/Linux

# マルチプラットフォーム FizzBuzz

[以前 Object Pascal で 97[byte] の FizzBuzz を書きました](https://qiita.com/pik/items/8f0a36857487b9bb8eea)。

## Object Pascal FizzBuzz コード

上記の記事で書いた最短コードはこれです。

```delphi
var i:Byte;begin for i:=1to 100do Writeln(i,^m,Copy('Fizz',i mod 3*9)+Copy('Buzz',i mod 5*9))end.
```

清書

```delphi
var
  i: Byte;
begin
  for i := 1 to 100 do
    Writeln(i, ^m, Copy('Fizz', i mod 3 * 9) + Copy('Buzz', i mod 5 * 9))
end.
```

# マルチプラットフォームで動かす

で、当然 Delphi なのでマルチプラットフォームで動くんですよ。
ただし、コンソールアプリなので今回は Windows, macOS, Linux だけ対応します。

## プラットフォームの追加
プロジェクトマネージャでプロジェクトを右クリックして「プラットフォームの追加」を選んで追加するだけです。

![addplat.png](https://qiita-image-store.s3.amazonaws.com/0/12977/d77d51a3-53ca-4752-f6fa-194c99b526d6.png)

## 実行
ターゲットをダブルクリックしてアクティブ化して、実行（F9 キーかメインメニューの「実行」→「実行」）するだけ！

![w.png](https://qiita-image-store.s3.amazonaws.com/0/12977/ef7f7a93-586d-239d-5ada-944e3967a8a8.png)

## 結果
各 OS での実行結果を載せておきます。

### Windows
![win.png](https://qiita-image-store.s3.amazonaws.com/0/12977/b3b5c03d-fb8b-2a12-565c-7cc106bcee5f.png)

### macOS
<img width="682" src="https://qiita-image-store.s3.amazonaws.com/0/12977/53925017-0a2e-c1de-863c-e00a2e2b2719.png">

### Linux (ubuntu 16.04)
![ubu.png](https://qiita-image-store.s3.amazonaws.com/0/12977/df20a87e-ab18-e636-0a0b-d4e01cee2123.png)

ちなみにこの Ubuntu は [Microsoft Store からインストールした ubuntu](https://www.microsoft.com/ja-jp/store/p/ubuntu/9nblggh4msv6)

# まとめ
Delphi ならスゴい簡単にマルチプラットフォームアプリが作れてオススメ！
[無料で使える Starter Edition](https://www.embarcadero.com/jp/products/delphi/starter) もあるよ（ただし、今のところ Win32 のみ作成可能）。

※なお Linux の場合、Delphi 単体では GUI アプリは作成出来ない… 
[FMXLinux](http://fmxlinux.com/) を使えば GUI アプリを作れるようにはなるけど有料。
CentOS7にWebminをyumインストールする方法

yumでインストール出来るようにする。

```shell-session:commands
# vi /etc/yum.repos.d/webmin.repo
# yum install webmin
# rpm -qa | grep webmin
webmin-1.860-1.noarch
# cp /etc/webmin/miniserv.conf /etc/webmin/miniserv.conf.original
# vi /etc/webmin/miniserv.conf
# chkconfig webmin on
# service webmin start
```

```bash:webmin.repo
[webmin]
name=Webmin Repository
baseurl=http://download.webmin.com/download/yum/
gpgcheck=1
enabled=1
gpgkey=http://www.webmin.com/jcameron-key.asc
```

```bash:miniserv.conf
# 追記（アクセスを許可するネットワーク）
allow=127.0.0.1 192.168.0.0/16
```

WebブラウザでWebminにアクセスしてみる。
https://SERVER_ADDRESS:10000/

![webmin.jpg](https://qiita-image-store.s3.amazonaws.com/0/97774/47a7e29f-45d9-fd39-203a-b3b4d9987816.jpeg)
Pythonの「return 1」は必ず1を返す。そう思っていたときが僕にもありました。

結論から書くとそんなことはなかったです。
ということで、Generator関数について勘違いしている部分があったので備忘録を兼ねて。

## 普通の関数

これは何の変哲も無い普通の関数です。ちゃんと1が返ってきます。

```python
>>> def a():
...     return 1
...
>>> a()  # 実行結果は当然1
1
>>> type(a())
<class 'int'>
```

## Generator関数

Generator関数はyieldキーワードで値を送出することでメモリ効率のいいiterableを作り出せます。

```python
>>> def b():
...     yield 1
...
>>> b()  # 実行結果は当然generator
<generator object b at 0x106db82b0>
>>> next(b())
1
>>> type(b())
<class 'generator'>
```

別の関数やメソッドに渡したり、使いまわしたりする際には多少気をつかう必要がありますが、個人的にはかなり使います。

## ここからが本題

さて、ここで下記は普通の関数、Generator関数どちらでしょうか。(実際にこんな感じのコードを書いてました)
また、実行結果はどうなるでしょうか。

```python
def c(n):
    if n:
        return 1
    else:
        yield 1
```

実際に動かしてみました。

```python
>>> def c(n):
...     if n:
...         return 1
...     else:
...         yield 1
...
>>> type(c(0))  # `yield 1`なのでまぁそうなるよね的な動き
<class 'generator'>
```

問題はこちら。
`return 1`だけど返り値は`1`じゃない！！

```python
>>> type(c(1))  # `return 1`だけど1が返ってきていない
<class 'generator'>
>>>
>>> c(1) + 1  # 当然数値型が要求される式で使うと怒られます
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'generator' and 'int'
```

ちなみに `yield from` を使った場合でももちろん同じです。

```python
>>> def e(n):
...     if n:
...         return 1
...     else:
...         yield from (i for i in range(9))
...
>>> type(e(0))
<class 'generator'>
>>> type(e(1))
<class 'generator'>
```

ということで、 `return 1` って書いても`1`が返ってこないこともあるよという話でした。

この例ではわかりやすいように`1`を返しています。
が、「listかgeneratorを返す」関数を作り、その返り値を他の関数に渡すなどしていると、`原因とエラーの箇所が離れてしまう非常に面倒なバグ`になります。
なので、正直なところ返り値の型が大きく違う関数はあまり書かないほうがいいのかなと思います。

### おまけ

ちなみに実際にこういう処理が欲しい時は、こんな感じで関数自体を分けるするのがいいと思います。

```python
>>> def _f():
...     return 1
...
>>> def _g():
...     yield 1
...
>>> def d(n):
...     if n:
...         return _f()
...     else:
...         return _g()
...
>>> d(0)
<generator object g at 0x106db8410>
>>> d(1)
1
>>> d(1) + 1
2
```
keras_to_tensorflow

#概要
jsdoに、keras.jsで学習したグラフを使おうとしたが、だめだった。
[だめなやつ](http://jsdo.it/ohisama1/OOFn)
deeplearn.jsに、鞍替えするため、kerasのモデルをtensorflowに、変換した。
手順を記載する。

#環境

windows 7 sp1 64bit
anaconda3
tensorflow 1.2

#kerasでモデルを学習して、セーブする。

```
import numpy as np
from tensorflow.contrib.keras.python.keras.models import Model
from tensorflow.contrib.keras.python.keras.layers import Input, Dense, Activation
from tensorflow.contrib.keras.python.keras.optimizers import SGD
import matplotlib.pyplot as plt

x = np.arange(200).reshape(-1, 1) / 30
y = np.sin(x)

inputs = Input(shape = (1, ))
m = Dense(30)(inputs)
m = Activation('sigmoid')(m)
m = Dense(10)(m)
m = Activation('sigmoid')(m)
m = Dense(1)(m)
model = Model(inputs, m)
sgd = SGD(lr = 0.1)
model.compile(loss = 'mean_squared_error', optimizer = sgd)
model.summary();
model.fit(x, y, epochs = 400, batch_size = 10, verbose = 0)
preds = model.predict(x)
plt.plot(x, y, 'b', x, preds, 'r--')
plt.savefig("keras13.png")
plt.show()
with open('keras13_arch.json', 'w') as f:
	f.write(model.to_json())
model.save('keras13.h5')
print ("save model")

```

![keras13.png](https://qiita-image-store.s3.amazonaws.com/0/18104/1879a3c5-5807-cb6f-7f03-2f239d73aa2e.png)

#keras_to_tensorflowで、pbファイルに変換する。

https://github.com/ohisama/keras_to_tensorflow

#pbファイルを、読んで、inputとoutputを確認。

```
import os
import os.path
import tensorflow as tf
from tensorflow.python.platform import gfile

with tf.Session() as sess:
	with gfile.FastGFile("keras13.pb", 'rb') as f:
		graph_def = tf.GraphDef()
		graph_def.ParseFromString(f.read())
		_ = tf.import_graph_def(graph_def, name = '')
	for op in tf.get_default_graph().get_operations():
		print (op.name)
		for output in op.outputs:
			print ('  ', output.name)


```


#pbファイルを、読み込んで動作確認。

```
import os
import os.path
import tensorflow as tf
from tensorflow.python.platform import gfile
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(200).reshape(-1, 1) / 30
y = np.sin(x)
g = []
with tf.Session() as sess:
	with gfile.FastGFile("keras13.pb", 'rb') as f:
		graph_def = tf.GraphDef()
		graph_def.ParseFromString(f.read())
		_ = tf.import_graph_def(graph_def, name = '')
	for i in range(200):
		result = sess.run('output_node0:0', feed_dict = {
			'input_1:0': [x[i]]
		})
		print (result)
		g.append(result)
	plt.plot(g)
	plt.savefig("predic13.png")
	plt.show()
```

![predic13.png](https://qiita-image-store.s3.amazonaws.com/0/18104/50c212ee-79f9-dd92-09c3-f7c15bd66be6.png)

以上。
OpenCV3 Thin Plate Splineの使い方

画像を歪ませる(Warp)手法Thin Plate Spline(TPS)がOpencv3.0から追加されましたが、思った以上に不具合にハマったのでメモを残します。

TPSは画像上のポイントを任意の場所に動かし、その間を連続的に補完する手法です。画像を歪んだ薄板に見立てて、三次元的に補完するイメージです。

![original.jpg](https://qiita-image-store.s3.amazonaws.com/0/80503/b8ec2eee-5b6f-c233-688a-0a6828a0c0b5.jpeg)　**⇒**　![warp.jpg](https://qiita-image-store.s3.amazonaws.com/0/80503/e11c4619-cc33-a7b5-abf8-ad52b73ea1ba.jpeg)


###環境
* OpenCV 3.1
* python 2.7
* numpy

###TPSのインスタンスを生成
```
tps = cv2.createThinPlateSplineShapeTransformer()
```
まずはインスタンス生成し、これにwarpの仕方を指定していきます。
###ソースとターゲットの座標指定
```
sshape = np.array([[100,100],[200,100],[240,200],[300,250]],np.float32)
tshape = np.array([[100,180],[200,130],[240,220],[300,280]],np.float32)
sshape = sshape.reshape(1,-1,2)
tshape = tshape.reshape(1,-1,2)
```
座標は何故か三次元で指定します。（cvMatの仕様？）
(1,ポイントの数,2)のように三次元目に座標(x,y)を指定します。

また、型は**np.float32**にしてください。np.float64では何故か後の座標変換関数が動作しなくなります。

###ソースとターゲットの座標を対応
```
matches = list()
matches.append(cv2.DMatch(0,0,0))
matches.append(cv2.DMatch(1,1,0))
matches.append(cv2.DMatch(2,2,0))
matches.append(cv2.DMatch(3,3,0))
```
ソースとターゲットの各座標の対応関係を指定するマッチングリストを作成します。ポイント数分のリストとなり、上記では同じインデックス同士を対応させています。
DMatchクラスの3番目の引数は不使用のため0とします。



###TPS変換の推定
```
tps.estimateTransformation(sshape,tshape,matches)
```
ソースとターゲットの対応関係からTPS変換を推定します。ここでは一旦関数の形を推定して、後から画像や座標をいろいろ変換します。
引数にソース座標、ターゲット座標、マッチングリストを指定して推定すると、任意の座標を変換できるようになります。


###任意座標の変換
```
ret, tshape_ = tps.applyTransformation(sshape)
```
任意の座標も(1,ポイントの数,2)で指定して変換します。
上記ではTPS推定に使用したソース座標を変換し、ターゲット座標になっていることを確認します。

###画像のTPS変換
さて、推定したTPSで画像を変換しますが、tpsクラスのwarpImage関数はバグのせいか**ソースとターゲットが逆に変換されてしまいます**。
なので画像変換した場合は別途、ソースとターゲットを反対にしてTPS推定した上で用いる必要があります。

```
tps.estimateTransformation(tshape,sshape,matches)

img = cv2.imread('sample.jpg', 1)
out_img = tps.warpImage(img)
```

座標と画像の両方にTPS変換を用いたい場合は、座標用と画像用のtpsクラスインスタンスを用意しなければいけないという有様です。

あとはwarpImageの補間方法等も指定できますので、別途OpenCVリファレンスを参照してください。
[連載 GLSL 物語] チカラが欲しいか……（第二話）新たなる力、その名はベクトルディスタンスフィールド！

# ベクトルディスタンスフィールド

![vdfcircle.png](https://qiita-image-store.s3.amazonaws.com/0/135381/f989a1a3-14b5-117a-b06b-74ec13c0c861.png)
https://goo.gl/BnkcKU

```glsl
 precision mediump float;
 uniform vec2  m;       // mouse
 uniform float t;       // time
 uniform vec2  r;       // resolution
 uniform sampler2D smp; // prev scene
  
 void main(void){
  vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y); // 正規化
  vec2 q = normalize(p)*.8-p;

  float l=step(length(q),.03);
  gl_FragColor = vec4(vec3(l), 1.);
 }
```

まずは、ベクトルディタンスフィールドを使って円を描いてみましょう。
普通に円を描いたのと変わりないですね。

ひと手間無駄な変換が入っただけなので、当たり前ですね。

```glsl
  vec2 q = normalize(p)*.8-p;
```

このqがベクトルディスタンスフィールドで

length関数を掛けるだけで

```glsl
  float l=length(q);
```

いつでも、ディスタンスフィールドに戻すことができます。

さて、2Dでは使われないnormalize(p)という見慣れないglslの関数が使われていますね。

円のディスタンスフィールドは

```glsl
1.-length(p)
```

でしたが、ここから、円のベクトルディスタンスフィールドを推測してみましょう。
1.というのは元は、pの単位ベクトルと推測できるので、normalize(p)と推測ができます。

```
length(normalize(p)) = 1.
```

ということは

```
length(normalize(p)) - length(p) 
```

lengthをまとめると

```
length(normalize(p)-p) 
```

ベクトルディスタンスフィールドはlengthを使ってスカラーにする前ですので

```
normalize(p)-p
```

ちゃんと導けました！

これだけだと、単にひと手間無駄な処理が入るだけなので、

早速、円のベクトルディスタンスフィールドに円のベクトルディスタンスフィールドを乗せていきましょう！

次回

* [[連載 GLSL 物語] チカラが欲しいか……（第三話）極座標リプリケーション](https://qiita.com/7CIT/items/67750e628ffd7d327689)
チャットでの質問はズバリ言おう

ちょうど業務で先輩に指摘されたので反面教師ということで書いておきます。
ちょっと気を抜くとこういうことがおきやすいので気をつけたいと思います。

# 結論

- **チャットで質問をするときは何をして欲しいか簡潔に言うべき**
  - 対面でのコミュニケーションと違い会話の行間を読むという行為が行いにくいため
  - また直結しない会話だと無駄なコミュニケーションが発生してもったいない

![スクリーンショット 2017-12-06 13.52.50.png](https://qiita-image-store.s3.amazonaws.com/0/56178/7b7f8a46-24d1-ba7d-4a7d-d3012dd2770d.png)

## こんなことがありました

### 前提条件
SalesService.jsの内容が間違っており、かつSalesService.jsは自動生成されるものなのだが定義が見当たらなかった

### その時のチャット

![スクリーンショット 2017-12-06 13.52.30.png](https://qiita-image-store.s3.amazonaws.com/0/56178/59000821-118a-74bc-d00c-088b29569782.png)

上記に書いたようにSalesService.jsは定義から自動生成されるコードです。
この元になる定義コードが見当たらず上記のようの質問をしました。
(自分としてはこのコードだけ、直書きしたのかと思い)

結果として、これ自体は修正プルリクが別に出ていて、そのプルリクがマージされれば解決するというものでした。

## ポイント

今回の自分が本当にしたかったのは、**SalesService.jsを正しい状態にする**ということでした。

↓そして自分がした質問はこれ

「SalesService.jsって直書きな感じですか？」

この質問では回答はYESかNOです。
そして、たとえこの回答でYES/NOが返って来たとしても**SalesService.jsを正しい状態にする**ことは達成できません。

### 本来すべきだった質問

**「SalesService.jsの内容が間違っているんですが、どうすればいいですか？」**

そしてSalesService.jsが自動生成されるものなのに定義がないからどうすればいいかわからないと補足すればよかった。

# まとめ

チャットツールは場所を選ばずコミュニケーションができる素晴らしいツールですが、対面してのコミュニケーションと比べて細かい部分が伝わらないことが多いです。
そのために不必要な作業が発生して効率が落ちてしまうのはもったいないです。
今回のような細かいことを意識しながら良い開発をしていきたいと思います:smile:
社内wikiをフル活用したら、脳筋を脱却した話

#はじめに
※この記事は偏見と若干のフィクションで構成されています。

体育会系エンジニアは脳筋だ（偏見）。
少なくとも自分は「気合で何とかなるだろう」「詰んでからが本番」と考える性分のため、いつも納期ギリギリだ。
そんなやつが保守・運用を任されるとどうなるか。

「この仕様どうなってるの～？」
（ソースを見る）
「これバグ？仕様？？」
（ソースを見る）
「これ、出来る？」
（以下略）

今回はそんな日々が少しでも楽になったお話です。

#前提
ウェブアプリケーションを開発しているが、とにかくアップデートの回数が多い。
またシステムとして未熟であることから、仕様書もできていない。アップデートに仕様書が追い付いていない。

システム創始者が一度作ろうとしたが、アップデートの回数が多すぎて、1か月後にはすでに別物のように見えるとのこと（ちなみにそれに気づいた瞬間にあきらめたらしい）。

そして闇が多い（ﾎﾞｿッ

そんなんだから、社内では
「仕様書などない」
「作成者が仕様書」
「仕様？ソース見た？？」
等といわれる始末。属人化の権化みたいなシステムである。

#やったこと
「質問をすべて社内wikiに書き留める」

ただこれだけ。書き方としては

- 質問への回答だけでなく、仕様も記載する。
- ソースがどこに書いてあるかをできるだけ細かく書く
- カテゴライズをする
- 導線は1つ（または同一のもの）

ぐらいは気を付けた。


#結果
質問量は圧倒的に減った。
実測はしてないが、

やる前：最低でも6～7件/週、多い時には3～4件が同時に来ることも
今：週で3～4件、多くても5件

と半分近くまで減ったように感じる。

また該当ソースの場所が書いてあるので、
「このボタンをクリックすると、これが関数が動いて、ここで分岐してて、、、」
みたいな面倒な確認がいらず、時間短縮にもつながった。

あと質問が来ても同じものなら、
「お前はここでも確認しておけぇ～い！」
とコンサルさんにURLを投げるだけでオッケイ！これも時間短縮！！


自分の持ち駒を増やすことが重要だなぁと思いつつ、最近はこの社内wikiが仕様書になることを願ってやまない。



今では空いた時間を更なる筋トレに費やし、脳筋に磨きをかけている（本末転倒）。
ネットワークエンジニアから色々経てコーポレートITエンジニアになった話

元ミクシィなエンジニアがお届けする [ex-mixi Advent calendar 2017](https://qiita.com/advent-calendar/2017/ex-mixi) も18日目になりました。18日目を担当することになった @kakky0312 です。

全然会ってない元mメンバーの近況を伺うことが出来たりして僕も楽しく読ませてもらってますが、ホントに色々なところで皆活躍してらっしゃいますね。

# やってきたこと
## ミクシィ時代
僕は2006年8月から2012年3月までミクシィ社に在籍していました。正社員として働き始めたのは2008年4月に新卒第一期生として入ってからで、それまでは長期インターンとして色々と勉強させてもらっていました。

2006年8月といえばミクシィがちょうどその翌月にマザーズに上場したタイミングで、大学生の間に会社がどんどん伸びていく成長フェーズの状態を経験できたのは今でもとてもありがたかったなと思っています。

その時はプログラマーとして働こうと思っていたのですがサーバ構築のお手伝いをしたりその時メンターだった社員さんがネットワーク構築していたりするのを見てるうちに気づけばサーバ構築やネットワークの仕事を希望するようになっていました。

そしてサーバ構築や発注系の業務を経てプロダクトネットワークの運用業務をするわけですが、タイミング的にネットワーク業界も色々な変革の時期でしたし、mixiというプロダクトもネットワーク的に色々とやった時期でした。ロードバランサーアプライアンスのリプレースだったり、1Gベースだったエッジスイッチを部分的に10Gベースにリプレースするためにネットワークのグランドデザインをやり直したりとても沢山の経験を積ませてもらいました。

さらにmixiといえば[memcachedにまつわる大障害](http://alpha.mixi.co.jp/entry/2010/10775/)もありましたが、そのちょっと後にネットワークサイドで起きていた[memcachedにまつわるバーストトラフィックのお話](http://gihyo.jp/admin/serial/01/mixi_wdb/0001)なんかも書かせてもらいました。

## その後は、、、
その後に、2社ほど転職をしプロダクトネットワークやミドルウェア領域、プライベートクラウドやパブリッククラウドの構築と運用、そしてクラウドへのプロダクト移行案件、最終的にはスタートアップの立ち上げとBtoB向けWEBアプリケーション開発と運用などを経験し、今はさらに転職してコーポレートITエンジニアとして働いています。

# なぜコーポレートITエンジニアなのか
## 選んだ理由
プロダクトサイドの仕事を今までしてきて、なぜコーポレートITエンジニアとして転職したのか。自分としても大きな選択だったのですが、理由の一つとしては今までやってきた仕事内容のバリエーションの多さがあります。

先にも述べたとおり、今まで何か一つのものに特化してというよりは幅広い領域の業務をしてきました。フルスタックエンジニアなんておこがましいことをいうつもりはありませんが単純にキャリアとしては多岐にわたったものになっています。

コーポレートITエンジニアは多方面の知識があったほうがより業務遂行しやすいポジションです。社員さんが日々業務をする上での問題だったり要望は多岐にわたります。そしてエンジニアリングに加えてサポート会社さんとの交渉だったり発注だったりもあるわけで、列挙しだすと枚挙にいとまがありません。

色々やってきた人こそコーポレートITエンジニアという仕事は向いているのではないかと思います。

## 気をつけていること
しかしながら、だからといって全部が全部できるわけではありません。その会社の歴史的背景だったり、その会社だからこその内部フローだったりそれぞれの会社には今までの歴史がありルールがあります。そういったものへ今まではこうだったからこうしたい、こうあるべきというのではなく、そういう背景があるならこうしていこうと考えられる柔軟性と慎重性こそ求められます。(当たり前っちゃ当たり前です)

何か社内的にプロダクトが入っています。それだけ見るとなんか使い勝手悪いなー、なんでこれを使ってるんだろうこっちのほうがいいじゃん。そう思うことって結構ありますよね。でもちゃんと背景を見ていくとAとBとCが連携して動いていてAだけリプレースしようとするとBとCとの連携が崩れて影響範囲がでかいなんてことがままあるわけです。そういう部分を紐解きながら色々改善方法ないかを考えていく必要があるところが難しくもありやりがいのあるところです。

## レスポンスのダイレクトさ
そして、もう一つの理由はアクションしたことへのレスポンスの早さは随一ではないでしょうか。やったことに対してありがとうといってもらえる早さ、これはたまらなくうれしいところです。逆に何かあった際のツッコミも早いわけで、フィルタリングされることなくストレートにくるのでがんばんなきゃなと思える点でもあります。

# コーポレートITエンジニアになってみて
色々と書いてきましたが、実際コーポレートITエンジニアになってみて思うことは「とりあえず忙しい」でしょうか(笑)

日々やってくる社内からの問い合わせを受けつつ、相談されている外部サービス導入検証や機器選定、社内ネットワーク運用だったりオフィスの法令停電対応をやるなどバタバタと業務に追われています。

そんな中で、気づきも沢山あり楽しく働けています。ネットワークひとつとってもプロダクトとアドレス設計思想からそもそも違ったり無線LAN運用があったりもするわけなので覚えることが沢山あるわけで、所変わればなんとやらというところでしょうか。プロダクトの開発や運用をされている方々とはまた別種の知識量が求められるわけで、オフィスの電源容量について深く考える機会なんて新鮮そのものでした。

こういう新しいことへの興味と知識欲は失わないようこれからも頑張っていければと思っています

# 最後に
というわけで [ex-mixi Advent calendar 2017](https://qiita.com/advent-calendar/2017/ex-mixi) 18日目はどうだったでしょうか。大した話でもないですが、コーポレートITエンジニアの一端がわかってもらえると嬉しく思います。

明日は、同じ日にミクシィを卒業された @bonnu さんです。

技術話じゃないエモい話を書くということでお楽しみに！
Atomic Design × Sketch Libraryを用いてデザインファイルを作る

<!--
ターゲットユーザー: Sketchは持ってる。Atomic Designについても聞いたことがある
目的: SketchとAtomic Designの相性が良く使いやすいと知ってもらう
最終ゴール: SketchでAtomic Designを実現してもらう。利用してもらう
-->

この記事は [リクルートライフスタイル Advent Calendar 2017](https://qiita.com/advent-calendar/2017/recruitlifestyle) 6日目の記事です。

自分はエンジニアですが、普段業務でAtomic Designを用いてデザインファイル作成を推進しています。
10月にリリースされたSketchの新機能であるSketch LibraryがAtomic Designを管理するのにかなり便利になったのでそのことについて書きたいと思います。

## Atomic Designについて
![](https://cdn-images-1.medium.com/max/900/1*j1P0pjQtl36QJavv8lHdyw.png)

Atomic Designとはパーツやコンポーネント単位で定義するデザイン手法です。
以下の例のようにデザインを定義されたコンポーネント単位に分割します。

|Component| 例 |
|:--|:--|
|Atoms| アイコン、ボタン |
|Molucules| 入力フォーム |
|Organisms| ヘッダー、フッター、サイドメニュー |
|Templates| ワイヤーフレーム |
|Pages| 画面 |

Atomic Designを取り入れることによって、デザイン、開発でも繰り返しコンポーネントを再利用出来るなどのメリットがあります。

## Sketch Library
Sketch LibraryはVersion 47(2017年10月10日release)で追加されたSketchの新機能です。
Sketchファイル間で作成したSymbolを共有、同期することが出来ます。

※Symbol: Sketchで繰り返し利用可能なページとは別で切り出された要素のこと

Sketch Libraryが便利な点は、以下のように今までは、共通の要素に対して修正が入ったときに全てのデザインファイルに対して手動で修正が必要でした。(デザインファイルを画面毎に分割している場合など)

**今まで**
<img src="https://qiita-image-store.s3.amazonaws.com/0/73659/35233b7f-c413-274c-36d2-a124281c8b10.jpeg" height=400px>

**Sketch Libraryを活用した場合**
<img src="https://qiita-image-store.s3.amazonaws.com/0/73659/1120a3b3-3bf0-4a07-b2ce-1fa6b94a27ad.jpeg" height=400px>

Sketch　Libraryを活用するとLibraryの更新があった場合には差分を抽出して、画面の更新を行うのみ(ボタンクリックのみ)で完結することが出来ます。

詳しい使い方は[公式](https://www.sketchapp.com/docs/libraries/)を見て頂けると！

## Atomic Design × Sketch Library
両者のメリットを改めて考えると
**Atomic Design**: コンポーネント単位でデザイン管理が可能、再利用性が高い
**Sketch Library**: Symbol管理、更新が簡単に出来る

Atomic Design単位で切り出したComponentをLibraryとして扱うことで再利用の高いコンポーネントの参照、更新を簡単にすることが出来ます。

例えばAtomic Designで以下のようにAtoms、Molecules、Organisms、Templatesで以下のように分けた場合、
<img src="https://qiita-image-store.s3.amazonaws.com/0/73659/78f471d1-2190-a467-8345-567d204ced1a.jpeg" height=400px>

Libraryの参照先ではは以下のように見ることが出来ます。
新規でデザインしたファイルに対してもLibraryを参照することができるのに加え、Atomic Designに沿って切り分けているため、どこにどんな要素があるのかを把握しやすくなります。
<img width="200" alt="library_focus.png" src="https://qiita-image-store.s3.amazonaws.com/0/73659/80796b6c-0f9d-72ea-8424-53ce2ff39f07.png">

### 実際に新規ファイルを作成する場合のデモ
![example.gif](https://qiita-image-store.s3.amazonaws.com/0/73659/2f365b6a-ed44-959f-84b9-1867b81c4786.gif)

以前は、別のツール(Craft)などを利用しないとSymbolの共通化は出来ませんでしたが、Sketch Libraryが出てからはSketchひとつで完結出来るのでComponentの管理もすごくやりやすくなりました。

今回Demoで作成したLibraryファイルはGithubにあげております。
https://github.com/ichiki1023/SketchLibraryExample


## 最後に
今回お話したSketch Libraryの活用はAtomic Designでなかったとしても十分活用出来ます。
ただ、個人的にはSymbol化する粒度が明確になるので、Library管理としてはAtomic DesignとSketch Libraryはかなり相性が良いのでオススメします。それではまた！


## 参考
### Atomic Design
- [珍しいワークフロー：Atomic Designの原則とSketchでデザインからプログラミングまで](http://postd.cc/the-unicorn-workflow-design-to-code-with-atomic-design-principles-and-sketch/)
- [Atomic Design を
分かったつもりになる](http://design.dena.com/design/atomic-design-%E3%82%92%E5%88%86%E3%81%8B%E3%81%A3%E3%81%9F%E3%81%A4%E3%82%82%E3%82%8A%E3%81%AB%E3%81%AA%E3%82%8B/)

### Sketch Library
- [公式](https://www.sketchapp.com/docs/libraries/)
ReactivePropertyで値変更時に古い値をDisposeする

まだ、ReactiveExtention を使い始めて三日目の ReactiveProperty 初学者です。

ReactiveProperty で値が変更されるのは良いのだけど、古い値を Dispose してくれなかったので。


```csharp
//  値の変更時に古い値を Dispose する
var d = this.RxProp.Zip(this.RxProp.Skip(1), (old, _) => old)
    .Subscribe(old => (old as IDisposable)?.Dispose());

//  これは別件
d.AddTo(this.Disposer);
```

### 参考

[neue cc - Reactive Extensionsで前後の値を利用する](http://neue.cc/2011/11/09_352.html)
Androidのプロジェクト分割

自分用のメモです。

## まえおき

Android Studio 3.0で新規プロジェクトを作っただけで

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74571/ad8239b7-a7d0-41ab-48f1-7e5bbcc096dd.png)

こんなにもたくさんのic_launcherが作られてしまうことに発狂した。


## やること

メインのプロジェクトに入ってるとごちゃごちゃしそうなものは別プロジェクトにしてしまおう。

## 手順

### サブプロジェクトのフォルダとかをつくる

```
$ mkdir launcher_icon
$ nano settings.gradle

----
include ':app'
include ':launcher_icon' ←追加
```

### build.gradleを置く

```groovy:launcher_icon/build.gradle
apply plugin: 'com.android.library'

android {
  compileSdkVersion 27

  defaultConfig {
    minSdkVersion 15
    targetSdkVersion 27
  }
}

dependencies {
}
```

### AndroidManifestを置く

```
$ mkdir -p launcher_icon/src/main/
$ touch launcher_icon/src/main/AndroidManifest.xml
```

```xml:launcher_icon/src/main/AndroidManifest.xml
<manifest package="io.github.yusukeiwaki.my_application.launcher_icon" />
```

### app/build.gradleで、launcher_iconをインクルードする

```groovy:app/build.gradle
// (前略)

dependencies {
    implementation project(':launcher_icon') //←追加
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.0.2'

// (後略)
```

### Sync Now

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74571/20bca49a-3c4a-f24b-3243-5f9c86e93fa3.png)


すると、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74571/809c6a2e-bf50-3896-453f-3805ca09b6fd.png)


ふえた。

### ic_launcherなんとか、をぜんぶlauncher_iconにうつす

```
$ mkdir launcher_icon/src/main/res
$ mv app/src/main/res/drawable launcher_icon/src/main/res/
$ mv app/src/main/res/drawable-v24 launcher_icon/src/main/res/
$ mv app/src/main/res/mipmap-* launcher_icon/src/main/res/
```

## ＼(^o^)／ すっきり ＼(^o^)／

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74571/5f36c8bf-b9f9-69af-cb0a-0f25e33c577f.png)
クロスアカウントでS3からAuroraに直接データをロードする

# LOAD DATA FROM S3

AWSのMySQL互換DBであるところのAuroraにはデータをS3から直接ロードする構文が用意されている。

- [Amazon S3 バケットのテキストファイルから Amazon Aurora MySQL DB クラスターへのデータのロード](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/AuroraMySQL.Integrating.LoadFromS3.html)

これの使用例はクラスメソッドさんなどもブログにしているのでそこまで話題にしない。

- [【新機能】Amazon AuroraにS3からの直接データロード機能が追加。](https://dev.classmethod.jp/cloud/aws/aurora-load-from-s3/)

## SQLの構文

詳しい設定方法は上の公式ドキュメントを見てほしい。結構大変で、DB側に専用のIAMロールと、DBのパラメーターグループ、そしてアクセスするユーザにパーミッションを設定する必要がある。

そしてなんやかんやで **'S3-URI'** にファイルパスを指定すれば読み込める

便利なもんですなあ

```sql
LOAD DATA FROM S3 [FILE | PREFIX | MANIFEST] 'S3-URI'
    [REPLACE | IGNORE]
    INTO TABLE tbl_name
    [PARTITION (partition_name,...)]
    [CHARACTER SET charset_name]
    [{FIELDS | COLUMNS}
        [TERMINATED BY 'string']
        [[OPTIONALLY] ENCLOSED BY 'char']
        [ESCAPED BY 'char']
    ]
    [LINES
        [STARTING BY 'string']
        [TERMINATED BY 'string']
    ]
    [IGNORE number {LINES | ROWS}]
    [(col_name_or_user_var,...)]
    [SET col_name = expr,...]
```

## サンプルDDL

- カンマ区切りのダブルクォート、ヘッダあり仕様のCSVをロードする

```sql:sample.sql
LOAD DATA FROM S3 's3://your.name.of.bucket/normal.csv' 
INTO TABLE `schema_name`.`table_name` 
FIELDS TERMINATED BY ',' 
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;
```

S3が同じアカウント内であるか、パブリックになっていればこれで設定は終わると思う。

## クロスアカウントでの操作とエラー

たとえ正しくIAMを設定したとしてもAuroraDBの対向になるS3を保持するAWSアカウントが自分のものと異なる場合以下のようなエラーが出る

```
error: Unable to initialize S3Stream
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/20634/5b944cfc-7fe7-595d-ae0b-33ef4dfc50e3.png)

参考


- [Bulk Load Data Files in S3 Bucket into Aurora RDS](http://ramblingsofraju.com/technology/bulk-load-data-files-in-s3-bucket-into-aurora-rds/)


- [Discussion Forums > Category: Database > Forum: Amazon Relational Database Service >Thread: Aurora Load From s3 Error - Cannot instantiate S3 Client](https://forums.aws.amazon.com/message.jspa?messageID=748264)

## クロスアカウントでの操作のためにS3を設定する

[例 2: バケット所有者がクロスアカウントのバケットのアクセス許可を付与](http://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/example-walkthroughs-managing-access-example2.html)

- AccountBのところにAurora側のAWSのアカウントIDを設定
- "Resource"のところは "arn:aws:s3:::your.name.of.bucket/*" とかで設定できるはず

```json
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Sid": "Example permissions",
         "Effect": "Allow",
         "Principal": {
            "AWS": "arn:aws:iam::AccountB-ID:root"
         },
         "Action": [
            "s3:GetBucketLocation",
            "s3:ListBucket"
         ],
         "Resource": [
            "arn:aws:s3:::examplebucket"
         ]
      }
   ]
}
```

これをS3のバケットに設定すると、Aurora内で `LOAD FROM S3` が実行できるようになる。
CSSフレームワークの社内啓蒙活動

[mwedアドベントカレンダー](https://qiita.com/advent-calendar/2017/mwed)6日目の記事です。

こんにちは。みんなのウェディングの平岡です。
[おっさん読書会でオブジェクト指向設計実践ガイドを読みました](https://blog.mwed.info/posts/ossan-dokushokai.html) に続いて、今日はCSSフレームワークの社内啓蒙活動に関して取り組んだ話をしたいと思います！

# はじめに

みんなのウェディングでは自社開発したCSSフレームワーク「Esthe（エステ）」を利用して開発をしています。
（Esthe自体に関しての説明は[こちら](https://blog.mwed.info/posts/esthe.html)）

苦労して導入したものの、みんなに使われないと悲しいですよね。。
本投稿ではEstheの社内啓蒙活動をする中で効果的だったものをピックアップしてみました。

# デザイナー・エンジニアを巻き込む

CSSフレームワークなので利用するのはデザイナーとエンジニア。
当然彼らの協力が必要ですが、皆のCSSに関する習熟度はまちまちですよね。

そこで、事前に個別でヒアリングを行い、習熟度を調査してメンバーを３段階のレベルに分けました。
そして、そのレベルに応じた社内勉強会を段階的に行うことで習熟度の違いによるミスマッチを防ぎ、より内容の濃い勉強会を開催することができました。

勉強会ではEstheの使い方はもちろん、習熟度の低いメンバーにはCSSの書き方自体からレクチャーを行いました。

また、ペアプログラミングを積極的に提案して実行することで、スムーズにEstheに慣れてもらうよう働きかけました。
ちょっと脱線しますが、welcome！ペアプロ！な空気を作るためにみんなペアプロしようぜ的な社内発表もしました。

# こまめなアナウンス

自社開発のフレームワークなのでもちろん、自らドキュメントを残していくのですが、
行った変更などをデザイナー・エンジニアの各共有ミーティングなどで積極的に発表していくことにより、意識づけとやってる感（大事！）を出していきました。

# 社外勉強会にて登壇する

社外の勉強会にて登壇することにより、社内の注目度は高まりますし
そういった動きをすることで、エンジニアでない他部署のメンバーにEstheを認識してもらい、「コンテンツを作る際はEstheを利用する」という認識を持ってもらえることができました。


# 最後に

うーむ。なかなか泥臭い施策ばかり。。
しかし、その甲斐あって今ではデザイン及び実装する際の基盤にはなり得たのかなと思っています。

明日は@matsuhisa_hさんの「HTMLメールの話」です。
踏み台の向こうにあるMySQLサーバに一発アクセスする

## 動機

株式会社iRidgeサーバーサイドエンジニアをやっています。lighttger2505です。
Vim以外の内容を書くのは久しぶりです。

さて弊社ではメインのDBとしてMySQLを使用しています。私は入社してから幾度なくDBにアクセスしてきましたが、
少し前の私には大きな不満がありました。

DBがローカルであればmysqlコマンド一発でアクセスできるのですが、
AWS RDS上に立っているDBサーバにアクセスするには踏み台サーバにssh後、mysqlコマンドを実行したり..
踏み台サーバーにssh後、更にwebアプリケーションサーバにssh後、mysqlコマンドを実行したり...
めんどくさいですね。

以下のように様々なめんどくささがあります

- DBサーバが遠くなればなるほどに、手間がかかる
- mysqldumpコマンド等でダンプ取るとかdumpファイルでリストアしたりとか、いちいちscpでファイルをやり取りする必要がある
- 踏み台等にmycliインスコされてないと自動補完が貧弱(重要)

本日はそんなときに使えるTIPSをご紹介致します。

## ポートフォワーディングしてアクセスッ

重要になるのがポートフォワーディングです。
平たくいうと『特定のポートに送られてきた情報を別のサーバに飛ばす』ことです。

取り急ぎ結論だけいうと、

1. ローカルの特定のポートに実行されるコマンドを踏み台サーバを経由してDBサーバに転送するトンネルを掘る
1. mysqlコマンドをローカルホストの特定ポートに対して実行する

これでローカルマシンからAWS RDSのMySQLサーバにアクセスできます。

### 踏み台サーバ経由でDBアクセス

```sh
# 踏み台サーバを経由してDBに対してポートフォワーディング
ssh -f -N -L 3306:{DB_HOST}:3306 -i {SECRET_KEY} {SSH_USER}@{SSH_HOST}
# 上記で割当したローカルホスト:3306に対してアクセス(ただし接続情報は最終的に接続するDBサーバ)
mysql -u {DB_USER} -D {DB_NAME} -h 127.0.0.1 -P 3306 -p
```

簡単?にできた!

### 踏み台サーバ経由でアクセスするサーバ経由でDBアクセス

```sh
# 踏み台サーバに対してポートフォワーディング
ssh -f -N -L 3306:{DB_HOST}:3306 -i {SECRET_KEY} {SSH_USER}@{SSH_HOST} -oProxyCommand='ssh {SSH_BASTION_USER}@{SSH_BASTION_HOST} -W %h:%p' -A
# 上記で割当したローカルホスト:3306に対してアクセス(ただし接続情報は最終的に接続するDBサーバ)
mysql -u {DB_USER} -D {DB_NAME} -h 127.0.0.1 -P 3306 -p
```

簡単???にできた!!!

### ポートダブリ

なお、複数ポートフォワーディングしてポートがかち合うこともあるのでそんなときは以下のコマンドでkillしてください。

```sh
kill `ps aux | grep "ssh -f" | awk '{print $2;}'`
```

### スクリプト化

最終的に以下のスクリプトをDB毎に作ってつなぎ変えてます。スマートジャナイケドネ。

```sh
# ポートフォワーディングしているプロセスをぶっころ
kill `ps aux | grep "ssh -f" | awk '{print $2;}'`
# 踏み台サーバを経由してDBに対してポートフォワーディング
ssh -f -N -L 3306:{DB_HOST}:3306 -i {SECRET_KEY} {SSH_USER}@{SSH_HOST}
# 上記で割当したローカルホスト:3306に対してアクセス(ただし接続情報は最終的に接続するDBサーバ)
mysql -u {DB_USER} -D {DB_NAME} -h 127.0.0.1 -P 3306 -p
```

## mycli

本筋と関係無いですが、mycliがめがっさ便利だから使うと良いと思います。

https://www.mycli.net/

- どのSQLクライアントをも凌駕する超賢い補完
- Syntax Highlight!!!
- confファイルによるカスタマイズ

## 今後の課題

とりあえずできましたが、現状は上記の様なスクリプトファイルを環境別に作成して`/usr/local/bin`に配置することで使い分けています。
これではあまりにも管理が雑。かつスマートじゃないので、なんらかのツールで接続情報を統合管理するなどしてもっとかっこよくやりたいものです。
[小ネタ]PaizaCloudでMySQL


## 手順

ターミナルを起動して

```
~$ sudo mkdir /home/mysql
~$ sudo chown mysql /home/mysql/
~$ sudo chgrp mysql /home/mysql/
~$ sudo usermod -d /home/mysql/ mysql
~$ sudo service mysql start
~$ mysql -u root -p
```

パスワードを聞かれたら何も入力せずにEnter

## 参考
　　[MySQLを起動すると「No directory, logging in with HOME=/」と表示される](http://d.hatena.ne.jp/graySpace/20140915/1410741641)