OmniAICreator/Qiita-1.07M huggingface dataset:
部分テストパラメータの値を使ってテストパラメータを生成する

generating test parameters using wrapper for collected partial parameters like test scenario, without metafunc

|pytest|URL|
|:--|:--|
|xdistの-nオプションについて|https://qiita.com/cielavenir/items/3f3319f3fa153c16c703|
|デコレータの作り方|https://qiita.com/cielavenir/items/542f7eaa612c6bb9ed90|
|デコレータに引数を渡す|https://qiita.com/cielavenir/items/2c971ca4bc138c375d17|
|部分テストパラメータの値を使ってテストパラメータを生成する|https://qiita.com/cielavenir/items/ce328313a9f0f498cbcb|
|pytestのfixtureを別の箇所でライブラリとして読み込みたい<br>(当該環境にはpytestが存在しない可能性がある)|https://qiita.com/cielavenir/items/8144774a6ac2eca2e2ce|

基底データをさまざまな角度からテストしたいということはそれなりにあると思う。

何も考えずに作ると、基底データをパラメータにして、テストの中でループさせることになると思う。

```py:loop.py
import pytest
def collect_data():
  return [1,2,3]

@pytest.mark.parametrize('num',collect_data())
def test_0(num):
  for idx in range(0,num):
    print([idx,num])

@pytest.mark.parametrize('num',collect_data())
def test_1(num):
  for idx in range(1,num):
    print([idx,num])
```

しかし、これはループ中にテストが失敗した場合にテストケース全体が失敗してしまうため、テストの作法としてはよろしくないとされる。

基底データを受け取ってテストパラメータを生成する関数を噛ませればよいのではないかと思った。

```py:wrap.py
import pytest
def collect_data():
  return [1,2,3]

def collect_test0():
  tests = []
  for num in collect_data():
    for idx in range(0,num):
      tests.append((idx,num))
  return tests

def collect_test1():
  tests = []
  for num in collect_data():
    for idx in range(1,num):
      tests.append((idx,num))
  return tests

@pytest.mark.parametrize(('idx','num'),collect_test0())
def test_0(idx,num):
  print([idx,num])

@pytest.mark.parametrize(('idx','num'),collect_test1())
def test_1(idx,num):
  print([idx,num])
```

行数は長くなったが、実際にはcollect_test0/1の処理はより複雑になると思われるので(たとえばcollect_dataがdatとjsonを返してtest1でだけjsonを読むとか)、誤差の範囲だと思われる。

2つのテストの出力は同じだが、前者のテスト数は6、後者のテスト数は9になった。idxについてもテストケースが分離されたことが確認できた。

```
collected 6 items                                                                                                                                                                                                

loop.py [0, 1]
.[0, 2]
[1, 2]
.[0, 3]
[1, 3]
[2, 3]
..[1, 2]
.[1, 3]
[2, 3]
.

collected 9 items                                                                                                                                                                                                

wrap.py [0, 1]
.[0, 2]
.[1, 2]
.[0, 3]
.[1, 3]
.[2, 3]
.[1, 2]
.[1, 3]
.[2, 3]
.
```

余談：これぐらいテスター的には常識なのかもしれないが、私はこの方法を思いつくのに半日かかってしまった。
便座の使用者をBLEとRedisで管理する

株式会社 日立製作所 OSSソリューションセンタ Blockchain推進部 梅田多一

# はじめに
トイレの使用状況やにおいを通知、親の健康状態をラズパイで遠隔確認するシステム「[今日のうん性](https://tech.nikkeibp.co.jp/it/atcl/column/16/121900307/010500049/)」を改良すべく、今回はBLE(Bluetooth Low Energy)とRedisを使ってトイレの使用者を確認できるようにするための環境を作ってみます。

![Qiita.png](https://qiita-image-store.s3.amazonaws.com/0/322104/fb628611-6836-ff1f-51f4-69cda89dec4c.png)

# 前提環境
Raspberry Pi 3 Model BにRaspbianをインストールします。

```
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 9.6 (stretch)
Release:	9.6
Codename:	stretch
```

# BLE環境のセットアップ
Raspberry PiをBLEセントラルにしてBLEペリフェラルからのアドバタイズメントを受け取れるようにします。Node.jsのbleaconモジュールをインストールして使用します。

* nobleの前提ライブラリをインストール

```
$ sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
```

参考：
[A Node.js BLE (Bluetooth Low Energy) central module](https://github.com/noble/noble#prerequisites)

* Node.js v8.xのインストール

```
$ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
$ sudo apt-get install -y nodejs
```

* node-bleaconのインストール

```
$ npm install bleacon
```

参考：
[A Node.js library for creating, discovering, and configuring iBeacons](https://github.com/sandeepmistry/node-bleacon)

# BLE環境の動作確認
以下のプログラムを作成して実行します。受け取ったアドバタイズメントをコンソール出力しています。

```javascript:beacon.js
var Bleacon = require('bleacon');

// Start scanning 
Bleacon.startScanning();

// Events
Bleacon.on('discover', function(bleacon) {
  console.dir(bleacon);
});
```

iBeaconのシミュレータ等を使ってアドバタイズメントを飛ばしてみます。私はAndroidアプリのBeacon Simulatorを使用しました。アドバタイズメントに含まれるuuidで人を、proximityがimmediateかnearの場合にトイレにいると判定できそうです。

```
$ sudo node beacon.js
{ uuid: 'a881f9bec064434ba659df4cbb445b95',
  major: 1,
  minor: 1,
  measuredPower: -65,
  rssi: -97,
  accuracy: 6.265184188618567,
  proximity: 'far' }
{ uuid: 'a881f9bec064434ba659df4cbb445b95',
  major: 1,
  minor: 1,
  measuredPower: -65,
  rssi: -87,
  accuracy: 3.5309536541092137,
  proximity: 'near' }
```

# Redis環境のセットアップ
Raspberry PiにRedisをインストールしてBLEペリフェラルからのアドバタイズメントを管理できるようにします。

* Redisのインストール

```
$ sudo apt-get install redis-server
```

* node-redisのインストール

```
$ npm install redis
```

参考：
[redis client for node](https://github.com/NodeRedis/node_redis)

# Redis環境の動作確認
先ほどのプログラムを改造して実行します。受け取ったアドバタイズメントからuuidとproximity を取り出しRedisに登録します。uuidをkeyにproximityをvalueとしてセットします。Redisへのセット時にsetexを指定しTTL(Time to live)を5秒に設定しているのでトイレから離れるとRedisから情報は自動的に削除されます。

```javascript:beacon.js
var Bleacon = require('bleacon');
var client = require('redis').createClient();

// Start scanning
Bleacon.startScanning();

// Events
Bleacon.on('discover', function(bleacon) {
  console.dir(bleacon);
  client.set(bleacon.uuid, bleacon.proximity, 'EX', 5, function(){});
});
```

Redisに付属のredis-cliを使えば登録されているアドバタイズメントを簡単に確認できます。

```
$ redis-cli
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> keys *
1) "a881f9bec064434ba659df4cbb445b95"
127.0.0.1:6379> get a881f9bec064434ba659df4cbb445b95
"near"
127.0.0.1:6379>
```

# おわりに
Raspberry Piひとつで近くにいる人を管理する仕組みを簡単に作れました。いろんな業務に応用できるのではないでしょうか。例えば働き方改革。時間や場所にとらわれない多様な働き方の実現には、従業員がいつどこで働いているか証明できる必要があります。
仕事の証明と言えばPoW(Proof of Work)。PoWと言えばブロックチェーン。次回は便座の使用状況をブロックチェーンで管理します。便座とブロック、ベンザとブロック、、お楽しみに。
npmのバージョンの変更について

Reactのチュートリアルをみていると、npmのバージョンを6以上にしてくださいとかいてあった。
調べてみると自分のバージョンは６以上でなかったので、最新版をインストールして、確認したが前のままだった。
それを解決した話。

##npmはnodeに連動？
結論、nodebrewを使ってnodeのバージョンを変更するとそれに合わせてnpmのバージョンも変わった。

nodeを最新版にしたときnpmも最新版になった。

##流れ

```terminal
$ npm -v
v3.0.0
```

これを6以上にしたい。。。

```terminal
$ npm install npm@latest -g 
```

をしてみた。

正常にインストール終了。

確認した。

```terminal
$ npm -v
v3.0.0
```
あれ、変わってない？
なんで？

```terminal
$ nodebrew use v11.0.0
```
で別バージョンのnodeに切り替え。

```terminal
$ node -v
v11.0.0

$npm -v
v6.4.1
```

あ。変わった。
どうやら、npmはnodeのバージョンに合わせて変わるみたい？
php-master-changes 2018-12-18

今日は 7.2 系、7.3 系の開発バージョンの引き上げ、executor のコードサイズ削減があった！

# 2018-12-18
## cmb69: Prepare main branch for 7.3.2
- https://github.com/php/php-src/commit/a65133a17a8d88f38824fbb0af87ac15bfa4e8a6
- [7.3~]
- 7.3 系の開発バージョンを 7.3.2 に引き上げ

## cmb69: [ci skip] Fix release date
- https://github.com/php/php-src/commit/8734d6a73d650144d4872d3245d0dc559710588d
- [7.3~]
- 7.3.1 のリリース日を 2019 年 1 月 3 日に修正

## remicollet: bump to 7.2.15-dev
- https://github.com/php/php-src/commit/7161fe629d7449095e047b1d42c1de41e0c24a36
- [7.2~]
- 7.2 系の開発バージョンを 7.2.15 に引き上げ

## dstogov: Reduce executor size
- https://github.com/php/php-src/commit/868c1b7377e846bd5ea649129945785fe0556466
- 未定義変数の処理周りの呼び出しを単純化して executor のコードサイズを削減
PyramidSepDropのResidualDropoutを自作した(逃げ)

#環境
MacOS Mojave
Python 3.6
Keras 2.1.5(backend TensorFlow)

#失敗した話
先日、この記事と同じ主題で、KerasのDropoutレイヤーを参考に、Layerクラスを継承した物を実装しました。

ただ、callメソッドはバッチ毎に毎回呼ばれると思っていたんですが、インスタンス化した後に1回しか呼ばれない(らしき)ことが判明しまして…。全部パァになりました。

というわけで、完全に逃げの1手を打ち、無理やり実装しました。

#実装

```python
import keras
from keras.layers import GlobalAveragePooling2D, GlobalAveragePooling1D, Reshape, Lambda, multiply

def ResidualDropout(inputs, rate):
    layer = GlobalAveragePooling2D()(inputs)
    dim = layer.get_shape()[1]
    layer = Reshape((dim,1))(layer)
    layer = GlobalAveragePooling1D()(layer)
    layer = Lambda(lambda x : x ** 0)(layer)
    layer = Dropout(rate)(layer)
    return multiply([inputs,layer])

```

結果的に学習すべきパラメータ数は一切増えてないです。
けど、できればかっこよく実装したかったなぁと。

入力をひたすら圧縮(平均)していってある値にして、0乗する事で無理やり1にして、通常のDropoutで0、もしくは1にしてもらい、元の入力にかけています。

完全に力不足で太刀打ちできなかったので、逃げました。
pandasでgroupごとの差分系列をとる

```python
df.groupby.diff()
```
グループ数が多いときに上記のようにすると結構遅い。groupbyはapplyしたあとに返り値がスカラーなのかサイズのそろったベクトルなのか等を型判定してうまい具合につなげて返してくれるが、この部分がbottle neckになっているのかも。pandasが列指向型というのもあるかも。

index名を'name'、columns名を'value'とでもして、

```python

temp_df=pd.concat([df.reset_index(), df.reset_index().shift(1).rename(columns=lambda s:s+'_shift')], axis=1)
df_with_diff=temp_df.loc[(temp_df['name']==temp_df['name_shift']), slice(None)]
df_with_diff['diff']=df_with_diff['value']-df_with_diff['value_shift']
```
こんな感じにすると高速化できる。1行ずらしたdataframeをconcatして、name列が同じ行だけを抜き出して差を取る形。dfは差分を取りたい順番に事前にソートしてあるものとします。

なお、reset_indexで出現した'name', 'name_diff'カラムを取り除きたければ、以下。

```python

df_with_diff[slice(None), ~(temp_df.columns.str.startwith('name')]

```
C#入門② Hello world を詳しく見てみる

前回の記事：[C#入門①　C#とは〜Hello world](https://qiita.com/chihiro/items/3add1d18407751eb38c8)

今回はHello worldを詳しく見てみます。

###プログラム
```c#:MyApp.cs
using System;

public class Hello{
  public static void Main(){
    Console.WriteLine("hello world!");
  }
}
```
このプログラムをコンパイルして実行すると、`hello world!`と表示されます。

###using System;
usingステートメント。
`Console.WriteLine`は、`System`という名前空間に属する。
そのため、`System.Console.WriteLine()`とコード上に記述することで、コードがエラーなく実行される。
このように名前空間すべてを書く書き方を`完全修飾名`という。
usingステートメントを使用すると、完全修飾名をいちいち書かなくてもよくなる。
`using 名前空間;`とすることで、`名前空間`に定義されているクラスを使うことができる。
今回は、`System`という名前空間をusingステートメントで記述しているため、完全修飾名を使わずに、`Console.WriteLine()`と書くことができる。


(今回のプログラムには書かれていないが)`namespace 名前空間{}`で、名前空間を定義することもできる。
同一namespace内に同じ名前のクラスは定義できない。

```c#:MyApp.cs
using System;

// Mainという名前空間にHelloクラスが属している
namespace Main{
  public class Hello{
    public static void Main(){
      Console.WriteLine("hello world!");
    }
  }
}
```

**名前空間**
クラスを階層的に分類するための機構。
プログラムの規模が大きくなり、クラスの数が増えてきたときに、関連性があるもの同士をまとめて管理することができる。


###public class Hello
クラス宣言。`class クラス名{}`で宣言することができる。
publicはアクセス修飾子。
publicやprivate、internalといった種類がある。

**クラス**
オブジェクトを作るための設計図のようなもの。
`new`キーワードを用いてインスタンス化して使う。


###public static void Main()
プログラムの`エントリーポイント`。
1つのプロジェクトにエントリーポイントは一つだけ。

C#ではメソッド名やクラス名の命名規則にPascal形式を使う。
Pascal形式：単語の頭が大文字

###Console.WriteLine()
引数で受け取った内容を出力し、内容を出力した後に改行を行う。
`Write()`は改行はしない。

###コメント
プログラムには含まれていないが、基本的なこと。

`//`
行コメント。1行をコメントアウトできる。

`/*  */`
ブロックコメント。複数行をコメントアウトできる。

###; セミコロン
C#ではセミコロンで文が区切られる。
ファイル名の末尾に一括で名前を追加する

たとえば、png画像の後ろに「修正済み」とつけたいとき。

pngファイルがあるフォルダに移動して、

```
ren *.png *.
ren * *修正済み.png
```

とする。

一旦拡張子を削除してから、
「修正済み」と一緒にあらためてつけている。
Vue.js始めました。

最近Vue.jsという言葉をよく耳にします。
遅れてるのか...

Vue.jsとは、ユーザーインターフェイスを構築するためのプログレッシブフレームワーク
javascriptのフレームワークですね。

####■シンプルで自由度が高い####
本格的なWEBアプリから、簡単な一部の機能実装まで幅広い規模に対応できること。

####■MVVM「Model(M)-View(V)-ViewModel(VM)」####
「Model（データ）」「View（画面）」「ViewModel（メイン処理）」といった具合で分けて開発を行うことができる。
保守、運用なども行いやすいので、大規模なアプリにも対応できる。

####■コンポーネント####
各プログラムを部品化して再利用ができる。
書くプログラムの量が減るため、開発の生産性を上げることができる。

####■学習効率####
構造もシンプルで日本語のドキュメントも充実しているので、学習コストも低い。
HTML、CSSとJavaScriptの基礎を学習すれば使い始めることができる。
他のフレームワークに切り替えるといったことも比較的簡単。

これは覚えるしかない！！
といった感じで一から勉強中です。

#ディレクティブ#
Vueでは、タグに v-* の属性を指定することができる。

```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue TEST</title>
<!-- Vue.js を読み込む -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>

<div id="test">{{ msg }}</div>  <!-- {{ msg }} が Vueデータに置換 -->
<script>
var test = new Vue({
  el: '#test',                        /* #test 要素に対して Vue を適用 */
  data: { msg: 'Hello world!' }    /* msg という名前のデータを定義 */
})
</script>

</body>
</html>
```
```html:表示
Hello!
```

##テキストをレンダリングする(v-text)##

```html
<div id="test">
  <div v-text="msg"></div> <!-- この行と -->
  <div>{{ msg }}</div> <!-- この行は、同じ意味 -->
</div>
<script>
  var vt = new Vue({
    el: '#test',
    data: {
      msg: 'Hello!'
    }
  })
</script>
```
```html:表示
Hello!
Hello!
```


##HTMLをレンダリングする(v-html)##
v-html を用いた場合はタグが置換されずそのまま出力される。
※クロスサイトスクリプティングに注意。

```html
<div id="test">
  <div v-text="msg"></div> <!-- 置換される -->
  <div v-html="msg"></div> <!-- 置換されない -->
</div>
<script>
  var vt = new Vue({
    el: '#test',
    data: {
      msg: '<p>Hello!</p>'
    }
  })
</script>
```
```html:表示
<p>Hello!</p>
Hello!
```

##条件により表示を制御する(v-show)##
値の真偽により表示する・しないを制御。

```html
<div id="test">
  <p v-show="display">Hello!</p>
</div>
<script>
  var vt = new Vue({
    el: '#test',
    data: {
      display: true
    }
  })
</script>

```
変数 display が true の時は Hello! を表示し、false の時は表示しない。

```html:trueの場合
Hello!
```
条件分岐は他に、(v-if)(v-else)(v-else-if)がありますね。


Vue.jsはとても学習効率が高い！フロントエンドロードマップにも、
「フレームワークにも多くの選択肢がありますが、最近よく使われているのはReact、Vue、Angularです。」
こんなんかいてありますから、学習したほうが良いはず！！

長くなりそうなんで次回も引き続きVue.jsについてかこうかな...
Salesforce開発管理で大切にしている3つのこと

この記事は[LIFULL Advent Calendar 2018](https://qiita.com/advent-calendar/2018/lifull)の17日目の記事になります。

こんにちは。LIFULLでSalesforceエンジニアをしています。@ohbashです。
2年ほど前までは、片手で数えられるほどのSalesforceの開発者も、いまではパートナーさんも含め20名強にまで増えています。
拡張開発のスピードも格段に上がっており、今後も開発部署が増えていくであろうことが予想されます。
今回は、そんなSalesforce開発の管理体制に関するお話です。

#前提

一般論っぽいタイトルにしていますが、弊社で行なっている管理方法をピックアップして共有する記事になります。

現在弊社で使っているメインの組織では、"利用ユーザー数は1000人ほど"、"コミュニティユーザーは数万人"、"ステークホルダーは全社"に渡るなど、規模が拡大しています。
リリース頻度も週に1回程度、タイミングが重なると3回・4回といった具合です。
当然、規模とステークホルダーの多さ、開発スピードによって、有効な管理方法が変わってくると思います。
弊社での実施内容がその一例として参考になれば幸いです。


#① 変更諮問

Salesforceの本番環境に変更を加える時は、開発部署が事前にチケットを作成し、変更諮問委員会で協議をする運用をしています。

開発のたびに「変更諮問」って、お役所かよって思っていました。
しかしSalesforce開発では、一般的なweb開発にくらべ、一つの箱（オブジェクト）にレコードタイプを分けて、別の用途の情報を格納するため、他用途への影響を考えて全体で統制を取る必要が出てきます。

実は過去に、改修スピードを保ちながら他に干渉が無いように、カスタムオブジェクトを多用して開発をしていた時期がありました。
結果として、同じような意味合いのカスタムオブジェクトが複数でき、組織の流動に耐えられなかったり、標準オブジェクトへの機能追加の恩恵を受けられないという問題が発生しました。

現在は見直しを図り、出来るだけ標準オブジェクトを使っていく方針で、ひとつの改修で他の利用者に影響がでないようにコントロールをしています。

また、変更諮問の役割として権限周りの統制も重要です。
変更を加える際に、この情報は誰が見えて良くて、誰には見えちゃダメかを知っている必要があり、各施策の担当者がSalesforce組織の全容を把握しておくことは現実的ではありません。
そこも、この会議体で全体を俯瞰してみて、考慮が足りていないポイントがあれば注意を促すことをしています。

この変更諮問の体制ですが、運用を開始してから1年ほどが経ち、ノウハウも溜まってきたため、ある程度協議が必要か否かの切り分けが出来るようになってきました。



#② Sandbox運用

「技術導入検証」と「運用改修」、「大・中規模プロジェクト」を同時に進行させるには、恒常的なSandboxの運用ルールが必要になります。
現在は、下記の4種類の環境でステージングを管理しています。

* 開発者のSandbox
* 部署のSandbox
* 統合環境
* 本番環境

「開発者のSandbox」は一人の開発者に一つのSandboxを割り当ててあり、基本的には各開発者が好きに使っていいというポリシーです。
その分、動作テストの担保としては信用がおけず、テストフェーズは「部署のSandbox」を使います。

「部署のSandbox」でテストが完了すると、変更セットを使って「統合環境」にデプロイをします。
この「統合環境」は本番環境前に必ず通るステージで、全ての開発部署が共同で使います。
また、本番反映前の最終確認として、出来るだけ本番環境に近い状態を再現しておく必要があります。

3つのステージを経て、はれて「本番環境」にリリースをします。

現運用では、各環境をどれだけ最新に保つかが特に重要であり、リフレッシュの頻度がキーになってきます。
「統合環境」のリフレッシュは最低でも月に1回。プラスで大きめのリリースがあった後にはリフレッシュを実施しています。
「部署のSandbox」および、「開発者のSandbox」は出来るだけ高頻度でリフレッシュをする方針で、感覚値では2週間に１度ぐらいでリフレッシュをしています。

#③ ソース管理・デプロイ管理

Salesforceの開発機能の弱いところとして修正リソースのオートマージができず、コンフリクトに気づけないという点があります。

小規模で開発している場合は、それぞれ修正ファイルのスコープを区切ったり、情報連携をしながら開発をすることができますが、部署を分断して開発をしていると、共通リソースに手を加えるときに、他で修正をしていないかを知ることは困難です。

そこで、ソースレビューと「部署のSandbox」への反映をGitとAntを経由して行うことで、修正被りに気づき、マージ修正をかけるようにしています。
開発者は、自分の「開発者のSandbox」で変更を加えた後、Gitにソースを上げ、PullRequestとしてレビュー依頼を上げます。
レビューがOKであれば、Gitの共通ブランチにマージ権限のある人がRequestを承認し、そのままAntをつかって「部署のSandbox」にデプロイをかけます。

このフローを徹底していれば本番環境のリソースとGitの共通ブランチのリソースは一致するはずですが、イレギュラーがおこり、ファイルの内容が乖離してしまうと、この運用は破綻してしまいます。
そのため、定期的に本番環境から最新のリソースを取得して、Gitで管理しているファイル群にアップデートをかけています。

Apex・Visualforceについては、上記の運用ですが、項目の追加や設定内容の変更については、全ステージで変更セットでのデプロイをしています。
また、デグレのリスクが比較的高い、プロファイルとページレイアウトの変更は、手動で行うことが多く、些細な変更でも本番反映前には必ず「統合環境」でも同様の設定変更を行う運用です。

現在リリーサーは二人おり、チャットワークで実施予定日と修正サマリを共有するようにしています。（この辺がちょっと野暮ったい）


#今後について

管理体制の一環として、Sandboxリフレッシュ時のapex処理の追加と、Apexリソースの削除フローの構築をしようと思っています。
Sandboxのリフレッシュ時にApexクラスを起動できる機能を使って、「不要ユーザーの無効化」、「カスタム設定値を開発環境用に書換え」、「テスト用データの投入」をやりたいなと考えています。
また、Apexリソースの削除フロー構築が必要です。
現在は、本番環境への更新は変更セットか手動設定でのみ行なっているため、削除フローがありません。
「Force.com IDE」や「Ant」を使って削除することができるので、削除フローを構築して綺麗な状態にしていきたいと思います。


以上、今回の内容を（かなり強引に）まとめると、
① 変更前に全体統制とポリシーに合致するか第三者的（？）にチェックしましょう
② 変更が加わる経路を統一して整備しましょう
③ Salesforceが弱いところ（ソースのマージ機能）は、外部のツールを使って補いましょう
というお話でした。

それでは！よいSalesforceライフを。
8946 Take#９

# 問題

http://www.hackerschool.jp/hack/take9.php

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/bb207a05-009b-f85b-57d8-ea045a74713d.png)

# 解いてみた

- ナンバーを入力するだけの問題です。
- ナンバーの上の30ってところが、たぶん1秒で1増えていきます。
- ちょっと様子をみていると59の次が0になりました。
- きっと何かに使うんだろうと思いつつソースコードを見ましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/08c4a160-8587-03eb-53c7-247aa82c2fb2.png)

- 突破するボタンを押した時の挙動「fn_check()」を見てみましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/74403364-62a6-0551-c77d-3c8aa7f72eef.png)

- 確証は持てませんが、どうやらanswerを990にして、ifの中に入ったら正解な気がします。
- そのためにはanswerを導き出す式「( ( seconds * ( seconds - 1 ) ) / 2 )*(input_no % 2);」を解き明かす必要があります。
- 入力されたナンバーがinput_noです。secondsは何かというと少し上のところに「sec」と書かれています。
- secとか確実に1秒ごとに増えるやつのことだろうと思いつつ、念の為調べます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/c00ab52b-b1d1-1e0f-5cd7-9f5a0cfa099d.png)

- あってたー。
- それでさっきの式に戻ると「input_no % 2」に関しては2で割った余りなので0か1しかない。
- しかもそれを掛け算しているのでこれはもう1にしておくしかない。
- つまり奇数を入力しておけばなんでもいいじゃないか。
- 一度整理すると ( seconds * ( seconds - 1 ) ) / 2 * 1 = 990となります。
- 簡単にすると x * (x - 1) = 1980 です。
- 今この記事を読んでいて「2次方程式って食べれるの？」って人はいないと思いますが、今の時代便利な世の中になっています。
- まさかの自動で解いてくれるサイトがあるんです。
- 「方程式 解く」でgoogle検索すると出てきました。
- https://ja.numberempire.com/equationsolver.php です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/572e899e-bf9b-531d-ff78-e1e47f685989.png)

- んー、すごい。
- 今回の数値は0~59だったので-44は不可。
- ということで何か奇数を入力した状態で45が表示された瞬間に突破するボタンを押すのが正解。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/fc92f251-f251-b858-5875-e275f7343a2e.png)

- 下の方切れてますがご勘弁を。。。
8946 Take#１６

# 問題

http://www.hackerschool.jp/hack/take16.php

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/35987331-aeda-f1fc-77b3-8cd4ba3dcee5.png)

# 解いてみた

- ついにIDがなくパスワードだけの問題になりました。
- とりあえずソースコードみましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/30b725a8-5da3-69af-4868-19eac84555e8.png)

- 「突破する」ではなく「送信」に変わってました。
- とりあえず、fnFormSubmit()を検索。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/81f3ebd8-09fe-f82b-db1c-f73fe351e20d.png)

- 10001011110010を10進数に直してね。っていう問題みたいです。
- 「2進数 変換」とかでgoogle検索したところ　https://hogehoge.tk/tool/number.html が最初に出てきたのでここを使います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/898b76d9-b219-fb06-ff8d-34604c544ff6.png)

- ということで、答えは8946です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/99c3cfbd-ec90-354a-67a8-14f5eeee8edc.png)
8946 Take#８

# 問題

http://www.hackerschool.jp/hack/take8.php

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/c586ee86-51ad-0802-da0f-1428c97a0c6e.png)

# 解いてみた

- Take1から順にならんでいるわけではないようです。
- 正解率の大きい順か？
- そもそも数字が大きくなると難易度が上がるわけではなく問題ができた順なだけみたい。

- ということでソースを表示します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/e5332a85-d772-06d3-c722-dfb181af045e.png)

- とりあえずIDはadmintake8ということは一瞬でわかりました。
- パスワードは(Math.round(8%2)*(88951634/2))+(6660/4)*4/3+6726だそうです。。。
- いちいち計算してもいいんですが、そんなめんどくさいことはしたくない。
- ということで、javascriptを実行してみて変数passを表示したらいいじゃないかと言う考えに至りました。
- ネットで検索してみるといろいろあるもんです。
- 今回は　https://jsbin.com/?html,output というサイトを使用しました。
- 問題ページのhtmlを全部貼り付けて、「残念」のところをpassに書き換えます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/fb84d087-8768-2fc8-436f-b76337e200f9.png)

- そして実行します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/bd636923-8def-2273-0cf9-fd2a87e798f4.png)

- とのことですので、答えは以下です。
	- admintake8
	- 8946

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/67979d45-885b-60c9-73db-cf602074ff6e.png)
8946 Take#４


# 問題

http://www.hackerschool.jp/hack/take4.php

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/726a9412-c78c-aacf-cdd4-d05c44627c7f.png)

# 解いてみた

- 今までと同じようにソースコードを表示。
- 「突破する」ボタンあたりのソースを見てみる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/5dce3e7a-8a7b-d130-eb2b-ee14c2da6653.png)

- ヒントありますが、文末に「=」ないのでbase64ではなさそう。
	- ちなみにbase64だと必ず「=」があるわけではないので、そこらへんは注意しましょう。
- 何で暗号化しているのかわからないので、googleで検索してみる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/75b4eb73-2f8e-ea24-9f59-ee9eced06620.png)

- おなじみのMD5だそうです。そしてabcdです。
	- ちなみにMD5は不可逆的なものなので、ハッシュ値から元の文字列を算出するのは基本的に不可能です。
	- 数年前に安倍首相が「慰安婦問題の最終的かつ不可逆的な解決」といっていた不可逆です。
	- なので、このサイトはハッシュ値からもとの文字列のabcdを算出したわけではなくて、「a」から順番にハッシュ値を出しまくって辞書的に記録した賜物だと思われます。
- パスワードの方もgoogle検索してみると以下ということがわかりました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/6b524c36-5fd6-b4fe-33d5-025e3f248322.png)

- ということで以下が正解になります。
	- abcd
	- 12345

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/87d78152-0d78-b982-669e-25615b20cf7d.png)
エンジニア向けのポートフォリオサイトまとめ

# はじめに
フロント周りのスキルも向上し、自分もポートフォリオサイトを作り直したいと思いました。
そのため、今回エンジニア向けのポートフォリオサイトを作る際の、参考サイトをまとめました。（全て手動検索です。）
ポートフォリオサイトと技術説明などあれば載せております。

# ポートフォリオ（順不同）
## Youichi Hiraga's portfolio
http://musou1500.github.io/
[エンジニアだけどポートフォリオサイト作ってみた](https://qiita.com/musou1500/items/24ed32d7f5b0a6377bc5)

## tamanugi.com
https://tamanugi.com/
[Angular + Netlifyでポートフォリオを作ってみた](https://qiita.com/tamanugi/items/3920c98b5f7536b59ad7#_reference-eec301acaf0883f6780b)

## Yohei Munesada's portfolio
https://www.yoheim.net/portfolio/#top
https://www.yoheim.net/blog.php?q=20130607

## Portfolio
https://simablog.net/portfolio/protfoliopage/
https://simablog.net/engineer-portfolio/

## HodaLab!
https://hodalab.com/portfolio/

## Naoto Suzuki's portfolio
https://nsuzuki7713.github.io/portfolio/
[エンジニアでポートフォリオ作りました](https://qiita.com/turmericN/items/76559f0b70983469e7c7)

## yamasy.info
https://yamasy.info/

## Phoenix - Ako
http://eiko-phoenix.com/index.html
https://note.mu/phoenix_ako/n/n9dc9f6a90b71

## WELCOME TO MY PORTFOLIO!
https://portfolio0720.firebaseapp.com/

## Namizato PortForio
http://namizatop.sakura.ne.jp/

## Masahito Osako's Portfolio
http://ve-lucas.com/#

## TANI'S
https://tanis.jp/

## icchy Profile
http://icchy-profile.site/
https://icchy.hatenadiary.jp/entry/2018/10/01/203615

## Plus one
https://plus-one.tech/

## Kentaro Matsushita
https://kentarom.com/
[Next.jsとFirebaseで更新の手間がかからないポートフォリオサイトを作ってみた](https://qiita.com/kentaro_m/items/51ba502fd5b1c603a439)

## Welcome to Naoki Kishi's Portfolio Site
https://naoki-kishi.github.io/
[フロント未学習の大学生が1週間でVue.jsを使ったポートフォリオを作った話](https://qiita.com/plus_kyoto/items/a01578b782f17f573510)

## Akatsuki Portfolio
https://akatsuki-py.github.io/my-portfolio/
[大学生がReactで1日でポートフォリオを作った話](https://qiita.com/Akatsuki_py/items/351fb3aff9bad73f0378)

## Welcome to roottool's portfolio site!
https://roottool.github.io/
[React + Typescriptでポートフォリオを作ってみた](https://qiita.com/roottool/items/89b4adcea8314e5f8e17#_reference-af19093cfc0c06692019)

## Koumoto Junichi's WEB SITE
http://www.koumotoj.com/
[業務系システムのエンジニアが今風のポートフォリオサイトを作ってみた](https://qiita.com/koumotoj/items/6aa952bfd955f7ffc0f5)

## iwathi
https://iwathi.netlify.com/
[Vue.jsでドラクエ風のポートフォリオを作った話　①](https://qiita.com/iwathi/items/8f054d10590f32b438a4)

## Hello, YouJ's Portfolio!
https://jyouj.github.io/Portfolio/
[CDN版Vue.jsでポートフォリオをサクッと作ったよ！](https://qiita.com/jyouj__/items/fce41ca62d11e2873a47)

## fmatzy.github.io
https://fmatzy.github.io/
[Nuxt.jsでポートフォリオサイトを作製する](https://qiita.com/fmatzy/items/aeb1e761c87379780e7f)

## kakipy_lab
http://kyusuke.xsrv.jp/index.html

## その他
ポートフォリオではないですが、これすごかったです。git hub上にあるポートフォリオをgifで確認できます。
[皆さんのポートフォリオをgifアニメにして、一覧できるサイト作った【Flaskで静的サイト】](https://qiita.com/umihico/items/d1210c37accb57a621ba)

# 終わりに
皆さん、それぞれ個性があり、面白いですね。
自分が作成する際、取り入れていきたいと思います。
また、「自分も作成しました！！」や「こんなポートフォリオもあります」などがありましたら、コメントなどで教えて頂ければと思います。
8946 Take#３


# 問題

http://www.hackerschool.jp/hack/take3.php

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/92b280f1-3f82-a303-c99a-55128e0f567d.png)

# 解いてみた

- まずは突破するボタンあたりのソースコードを見てみる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/873588c3-650d-1752-d890-7a771c623888.png)

- なんか下の方にいい感じのコメントが。
- こんな長ったらしいランダム文字列が答えかなと思いきや、パスワードの方をよく見てみると最後の文字が「=」になっている。
- ということはみんな大好きbase64かなと。
- 適当にbase64を復元できるサイトを使う。
	- 今回はおなじみの　https://gchq.github.io/CyberChef/　を使った。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/9b998f79-4300-b03c-4d21-7d47b448aa11.png)

- ということで、答えは以下です。
	- adminadmin
	- passwordpassword

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/7ec30d71-67a3-0556-0273-dde42eeea2a7.png)
8946 Take#２

# 問題

http://www.hackerschool.jp/hack/take2.php

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/29ea59b0-3668-4ad9-80c4-d122ce239268.png)

# 解いてみた

- 1問目と同じですね。とか思ってソースコード見てみたけどさすがにidとパスはなし。
- ［突破する]ボタンを押した時の挙動を見てみる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/2155a8d4-8e70-c084-fbb3-206f7bfae5a6.png)

- クリックした時にfnFormSubmit()が呼び出されているんだなーと。
- じゃあfnFormSubmit()の中身を見てみよう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/1cc15b47-1d77-fc13-5feb-4c3ea1d4eb89.png)
		
- 入力したIDとpassが以下の条件で比較されていることがわかる。
	- IDはlogin_id
	- passはlogin_pass
- ただそれぞれの変数がソース内を検索しても出てこない。どこかjsで定義してる？
- ところで、直前にあるsrc="/hack/js/password.jsは最高に怪しい。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/df901b01-d1aa-7cb9-678a-ed462362be3b.png)
		
- ということで以下が正解。
	- admin2
	- password2

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/ef088199-0e87-7fbf-dbc1-8780e2c237cf.png)
8946 Take#１

# 問題

http://www.hackerschool.jp/hack/take1.php

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/391cb18c-e3e8-bc8c-1aa9-1561703d1259.png)

# 解いてみた

- まぁ一問目ですし、ということで、ソースコードを開くと。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/60295ff6-2007-e3ff-af45-13eb963fe02f.png)

- ということで以下が正解。
    - admin
    - password

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/f3342633-dd33-265e-39ed-a1e1622f4d51.png)
vue-test-utilsでVuetifyのコンポーネントを確認する方法

vue-test-utilsで単体テストを書く際に、Vuetifyのコンポーネントが存在するかfindしたい場合に、コンポーネントクラスが指定できなかったのでメモ。

## 前提

ライブラリのバージョンは以下で確認しました。

- vue: 2.5.17
- vuetify: 1.3.11
- @vue/test-utils: 1.0.0-beta.26


## 実装

以下のようなコンポーネントが実装されているとして、vue-test-utilsを利用してテストを書きます。

```vue:hoge.vue
<template>
  <v-select v-model="selectItem" :items="items"></v-select>
</template>

<script lang="ts">
  import {
    Component,
    Emit,
    Prop,
    Vue,
  } from 'vue-property-decorator';
  
  @Component({
    components: {},
  })
  export default class Hoge extends Vue {
    @Prop() public items!: string[];
    @Prop() public value!: string;

    @Emit()
    public input(auther: string) { /* */ }

    private get selectItem(): string {
      return this.value;
    }

    private set selectItem(value: string) {
      this.input(value);
    }
  }
</script>
```

```js
import { expect } from 'chai';
import { shallowMount } from '@vue/test-utils';
import Hoge from '@/hoge.vue';
import { VSelect } from 'vuetify/lib';

describe('Hoge.vue', () => {
  it('ダイアログが表示されるか', () => {
    const items = ['hoge1', 'hoge2'];
    const wrapper = shallowMount(Hoge, {
      propsData: {
        items: items,
        value: '',
      },
    });

    # NG(パラメータに指定できない)
    expect(wrapper.findAll(VSelect)).to.length(1);

    # OK
    expect(wrapper.findAll('v-select-stub')).to.length(1);
    expect(wrapper.attributes().items).to.equal('hoge1,hoge2');
  });
});
```

element-uiだとコンポーネントクラスをパラメータに割当できるのですが、Vuetifyの場合、指定できなかったので、やむを得ず`xxx-stub' と指定して確認するようにしました。
AWS Lambda 関数のリクエスト

###AWS Lambda 関数の呼び出し方法
AWS ドキュメント参照
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invoking-lambda-functions.html


**AWS Lambda 関数のリクエスト**


```
var xhr = new XMLHttpRequest();
xhr.open('GET','https://ganyf52nbe.execute-api.ap-northeast-1.amazonaws.com/dev/compare-yourself/all');
xhr.onreadystatechange = function(event) {
  console.log(event.target.response);
} 
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send();
```

**> 結果　OK chrome で表示される**
--------
#### all のケース

```
var xhr = new XMLHttpRequest();
xhr.open('GET','https://ganyf52nbe.execute-api.ap-northeast-1.amazonaws.com/dev/compare-yourself/all');
xhr.onreadystatechange = function(event) {
  console.log(JSON.parse(event.target.response));
} 
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send();
```

--------
#### single のケース

```
var xhr = new XMLHttpRequest();
xhr.open('GET','https://ganyf52nbe.execute-api.ap-northeast-1.amazonaws.com/dev/compare-yourself/single');
xhr.onreadystatechange = function(event) {
  console.log(JSON.parse(event.target.response));
} 
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send();
```

**> 結果 一つのデータが表示される**
PHPカンファレンス2018に参加してきました。

# PHPカンファレンス2018に参加してきました。

PHPカンファレンスに参加してきたので、きっかけ、公聴した内容等をつらつらと書いてみます。
間違い等がありましたらご指摘頂けると幸いです。

## PHP Conference 2018

開催日：2018年12月15日(土)
場所　：大田区産業プラザ PiO
サイトURL：http://phpcon.php.gr.jp/2018/

## 参加しようと思ったきっかけ
- 業務でPHPを使う機会が増えた
- こういう場に参加してみるのもいい勉強になると聞いていたので興味があった。
- 開催が土曜日だった

昨年からPHPを使う機会が増え、PHPの現状ってどうなんだろう？と気になっておりました。

また技術ネタのイベントは平日の勤務時間が多く、なかなか行けるタイミングがありませんでした。
PHPカンファレンスは開催が土曜日でしたので、この機会は逃さないほうがいいなぁ！と感じ参加しました。


## 当日までやったこと
- 聴きたいセッションの選定

このようなイベント自体初めての参加なので、漠然とした不安でいっぱいでした。
（公聴内容理解できるかなぁ、ブースにいる方に積極的に話を聞きにいけるかなぁとかとか）
なので、当日バタバタしないように公聴したいセッションは事前に選定しました。


## 当日聞いたセッション
- オープニング
- PHPの今とこれから2018
- LaravelでTDDを体験しよう
- Cygamesにおける長期運用タイトルのこれまでとこれから～負荷対策とPHP7への道～
- 継続的なバージョンアップのためのテスト戦略～自動テストの導入とコンテナ化～
- PHPを選ぶ理由
- php-fpm をもっと理解しよう
- 大LT大会

## 感想
- どのセッションも面白く、時間があっという間に過ぎました。
- PHP5系 から PHP7系へのバージョンアップ作業に関する講演は、現在の業務に直結する内容だったので、これからの業務にいかせたらなと感じました。
- １人で参加していたため講演後すぐに語れる人がいなかった。なので、複数人で参加している人達を見ると、講演内容を語り合っていたり、そういう雰囲気は羨ましかったです。

## 最後に

面白いイベントでした。
聴きたい講演がまだあったので、時間のある時に動画の視聴をしようと思います。
（2週間を目途に非公開になるらしいです）
また来年開催されるので、機会があれば参加しようと思います。
TypeScript の型定義から GraphQL のクエリを出力するライブラリを作った

# 概要

実験的に、 `typed-graphqlify` というライブラリを作りました。

https://github.com/acro5piano/typed-graphqlify

TypeScript の型定義っぽいものから、 GraphQL の文字列を生成してくれるライブラリです。
TypeScript + GraphQL の痛みが解消できれば嬉しい。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103885/cce5a0fe-f3ed-cc6a-c217-420993388828.png)

# モチベーション

GraphQL は良いのですが、戻り値をハンドリングする際、 TypeScript の型定義と二重で管理するのがつらい時があります。

普通に書くとこんな感じになると思います。

```typescript
interface GetUserQueryData {
  getUser: {
    id: number
    name: string
    bankAccount: {
      id: number
      branch: string
    }
  }
}

const query = graphql(gql`
  query getUser {
    user {
      id
      name
      bankAccount {
        id
        branch
      }
    }
  }
`)

apolloClient.query<GetUserQueryData>(query).then(data => ...)
```

せっかく TypeScript で型定義しているので、そこから GraphQL も自動生成できたら楽ですよね。

そこで、 TypeScript の型定義と GraphQL を足して2で割ったような JS のオブジェクトから、 GraphQL の文字列を生成するのが **typed-graphqlify** です。

# 使い方

## インストール

```
yarn add typed-graphqlify
```

## 例

まず、 GraphQL っぽい JS のオブジェクトを作ります。これがそのまま型定義になります。

```typescript
import { graphqlify, types } from 'typed-graphqlify'

const getUserQuery = {
  getUser: {
    user: {
      __params: { id: 1 },
      id: types.number,
      name: types.string,
      bankAccount: {
        id: types.number,
        branch: types.string,
      },
    },
  },
}
```

`types` を使って、 TypeScript っぽい型定義をしているところに注目してください。

次に、`graphqlify` 関数で、これを文字列に変換します。

```typescript
const gqlString = graphqlify('query', getUserQuery)

console.log(gqlString)
// =>
//   query getUser {
//     user(id: 1) {
//       id
//       name
//       bankAccount {
//         id
//         branch
//       }
//     }
//   }
```

最後に、 GraphQL を実行します。

```typescript
// We would like to type this!
const result: typeof getUser = executeGraphql(graphqlify('query', getUser))

//`result` を `typeof getUser` にキャストしたので、型定義が生きている
// `result` の型はこんな感じ。
// interface result {
//   user: {
//     id: number
//     name: string
//     bankAccount: {
//       id: number
//       branch: string
//     }
//   }
// }
```

うまくいけば、下記の画像のように型が定義されるはずです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103885/cce5a0fe-f3ed-cc6a-c217-420993388828.png)

もっと詳しい使い方は、 GitHub のリポジトリをご参照頂けると嬉しいです。

https://github.com/acro5piano/typed-graphqlify

# 特徴

- ネストしたクエリを定義できる
- 配列を定義できる
- オプショナル型を定義できる (`types.optional.integer`)

# 所感

かなり便利そうなので、しばらく使ってみます。

で、これ作った後に知ったのですが、 GraphQL のスキーマから TypeScript の型定義を生成するツールはあるみたいですね・・・
他にあるツールとして、 Apollo-CLI や graphql-code-generator, graphqlgen など。

スキーマの更新が必要になってくる、必要なカラムは定義しないといけない、等の問題があるかも（多分）。でもそっちの方が確実で良いかも。作っちゃった。


# Thanks

Inspired by

- https://github.com/kadirahq/graphqlify
- https://raw.githubusercontent.com/19majkel94/type-graphql

Refs

- https://qiita.com/hitochan777/items/3390ec6a66098bfb552f
- https://qiita.com/mizchi/items/82138e98bccab60aeaac
Elasticsearch API を emacs buffer から呼ぶ

Elastic stack AdventCalendar 19 日 になります。

Kibana の DevTools でクエリを実行するのと同じことを emacs の中から実行する話です。

# はじめに

elastic emacs というキーワードでグーグル検索をすると、上位に Classmethod さんのインタビュー記事が出てきます。

[Elasticの中の人に聞いてみた(開発チーム編)](https://dev.classmethod.jp/server-side/elasticsearch/elasticon-2016-interview-elastic-dev-team/)

この中で開発環境について、こんなくだりがあります。

> CM「開発ツールにはどのようなものを利用していますか？」
Ryanさん「エディターはIntelliJ、Eclipseを利用しているメンバーが多い。中にはEmacs使いもいる。Emacs使いは開発だけではなく、メールなどの業務も全てEmacsでこなしている（笑）」

emacs でメールを読み書きしている私はとても親近感を感じます（笑）。

# 閑話休題

Elastic Stack はオープンソースのプロジェクトですので、 github でソースコードが公開されています。

試しに [elastic/elasticsearch](https://github.com/elastic/elasticsearch) を見てみると、一番上のディレクトリに[.dir-locals.el](https://github.com/elastic/elasticsearch/blob/master/.dir-locals.el) というファイルがあり、emacs の java-mode のカスタマイズが設定されています。もしかするとインタビューで話題になっていた方が、このファイルの主なんじゃないかと勝手に想像してます。その [dakroneさんのリポジトリ](https://github.com/dakrone)には elasticsearchを emacs から操る es-mode が公開されています。(ありがたや〜)

# 本編
前置きが長かったですが、本編は短いです。

[An Emacs major mode for interacting with Elasticsearch](https://github.com/dakrone/es-mode)

この es-mode を emacs に追加すると、Kibanaの Dev Tools でクエリを書いて実行するように、emacs buffer から RestAPI を実行できるようになります。

こんなふうに↓ Elasticsearch のクエリをファイルに列挙しておき、実行したいクエリの上にカーソルを置き、そこで Ctrl-c を ２ 回押すと、結果の json が別の buffer に表示されます。

![sample.es.gif](https://qiita-image-store.s3.amazonaws.com/0/124189/553f48ea-7bc4-cf4f-6c91-2410203b26c6.gif)

Kibana の DevTools に比べて何か利点があるか？と自問自答してみると、

クエリをファイルに保存しておけば、DevTools にコピペしなくても、すぐ実行でき、エディタの中で完結している、といったところでしょうか。

## org-mode

また、emacs には org-mode という、独自の markdown 的な仕組み(モード)があります。es-mode がセットアップされた状態で、org-mode内でクエリを実行すると、同じファイルのRESULTS というブロックが生成され、そこに結果を返してくれます。

検索クエリとその結果を記録しておきたい場合は org-mode の中で es-mode を使うほうが便利でしょう。

![sample.org.gif](https://qiita-image-store.s3.amazonaws.com/0/124189/865ad172-e3ef-2a15-42e4-6709b2419f84.gif)

↑の gif にもでていますが、json の結果を jq で処理したものを RESULTS で取得することもできます。

```
#+BEGIN_SRC es :jq ._source.title
GET demo/doc/1?pretty
#+END_SRC
```

```
#+RESULTS
: "hello elastic"
```

## es-mode のセットアップについて
[公式のREADME](https://github.com/dakrone/es-mode)を見てください。

とはいえ、emacs のバージョンや環境によって、うまくセットアップできない場合もあるかもしれません。お試しで es-mode 使うための[Dockerfile](https://github.com/s112358k/es-mode-demo) をつくってみました。コンテナのなかで動いている emacs なので、以下の２点に注意してください。

* endpoint は http://localhost:9200 になっていたら変更する必要があります。endpoint は .emacs ファイルの中で指定することができます。
* Elasticsearch もループバック以外のネットワークからもつながるようになっている必要があります。
ソフトウェアエンジニアと賢者の運用知識 (SRE本)

##まえがき
この記事は [iRidge Advent Calendar 2018
](https://qiita.com/advent-calendar/2018/iridge) の19日目です。間違いなく。

##TL;DR
ソフトウェアエンジニアが運用業務に携わって行き詰まった時にSRE本が役立った事例の話。
※この記事で出てくるSRE本とは[こちら](https://books.google.co.jp/books?id=81UrjwEACAAJ&redir_esc=y)

##あらすじ
@orfx は実務2年ほどのソフトウェアエンジニア (サーバーサイド)。
一般的なウェブサービスならなんとなく運用できる程度にインフラ面の知識はある。
が、低レイヤーの知識は乏しくインフラエンジニアを名乗るには程遠い存在。
そんな人間が自社サービスの運用チームにアサインされたからには人一倍頑張らなければならない、、、！

##はじまり
運用チームにアサインされて最初の任務が **インシデント管理** の引き継ぎ。
その会合でチームに古より伝わる **インシデント定義** と呼ばれる表を託される。
端的に言うとインシデントの重大度や対応優先度をあらかじめ定量的に定義しようとしたものだ。

###(例) インシデント定義のイメージ
| 機能 | 判定対象 | Aランク | Bランク |
|:--:|:--:|--:|--:|
| コンポーネント1 | 5xxエラー | 1件 | - |
| コンポーネント2 | 5xxエラー | 10件 | 1件 |
| コンポーネント3 | 5xxエラー | 100件 | 10件 |

また **インシデント対応フロー** と呼ばれる資料ももれなく付いてきた。
こちらも端的に言うとランクによって報告経路・頻度と対応期限を取り決めたものだ。

##迷走
このインシデント管理の資料や運用の見直しが次に着手する業務である。
運用業務の実状と合っておらず、定義に当てはめると対応が過剰になってしまうケースがあるから良い方法を考えなければならない。
先述の例でいうとコンポーネント1のような定義のことである。
が、しかし運用経験が浅い @orfx はどこから手を付けていいか分からない。
それ以前にインシデントという言葉が意味することがよく分からなくなっていた。

> - ITサービスマネジメントにおける定義
>     - **インシデント**
>         - サービスの中断又はサービス品質の低下を引き起こす、あるいは引き起こす場合がある、サービスの標準オペレーションに含まれていないあらゆるイベント
> 
> (https://ja.wikipedia.org/wiki/インシデント#ITサービスマネジメントにおける定義)

「インシデントを定義するってこう言うことではないのか・・？？」
「他にも用語の使われ方が資料によって微妙に揺れていて訳が分からなくなってきたぞ・・・」

「インシデントってなんだ・・・？🤔」

##出会い
そんな中、答えと救いを求めてひたすらにググり続けている時に下記の記事を発見する。

[SRE本まとめ（14章 インシデント管理）](https://qiita.com/bassbone/items/cb3501fe4bbad4c9b514)

「SRE?そういえば先輩の前所属チームがSREだったな・・・」

そして @orfx は偉大なる先輩からSRE本を受け渡されたのであった。

> Google では、可用性を過度に高めないようにするため、一部のサービスで定期的にダウンタイムを実施するようにしています。Google の Marc Alvidrez は SRE 本の中で、内部ロック システムの Chubby について語っています。
> (https://cloudplatform-jp.googleblog.com/2017/02/availability-part-deux-CRE-life-lessons.html)

「意図的にシステムダウンさせて顧客からの過度な依存性を排除する・・・だと！？」
インターネット界の巨人から放たれる圧倒的スケールな一文は自身の固定概念を木っ端微塵にされた。
それから電子書籍版を自費でポチるまでにそう多くの時間は掛からなかった・・。

##糸口
SRE本を読み進めるとある考えが頭に浮かんでいた。
インシデント管理という言葉に業務要素を詰め込みすぎているのではないかと。
Googleの信頼性を支えるエンジニア達は関連する内容を少なくとも下記３つの章に分けている。

- 4章 サービスレベル目標
- 14章 インシデント管理
- 16章 サービス障害の追跡

「賢者達ですら分けて考えている内容を凡人中の凡人の自分が一度に整理できるわけがないっ・・！」

そしてサービスレベル目標が明確でないことが最初に解決すべき課題だと確信して、各コンポーネントのSLI/SLO定義に着手し始めたのであった・・・。

##強引なまとめ
- 運用業務においてもフレームワーク的なものは重要でSRE本がその役目になり得る。
    - スクラッチ開発でいう神クラスのように、定義が曖昧で便利な言葉があると過剰に役割を持たせ過ぎてしまう。
    - フレームワークを取り入れるとベースとなる設計があり、知見など情報量も多いので引き継ぎコストが削減できる。
    - とはいえ現時点で体系化されてはないので盲信できる訳では無い。
- SRE本は経験の浅いエンジニアでも運用入門書のように役立てられる。
    - SREの全てを導入する必要はなく、やり易い所から取り入れていけば良い。
    - 運用業務に行き詰まった時のヒントとなる可能性がある。

##あとがき
4年半振りのQiita投稿が技術要素皆無のポエムになってしまい誠にごめんなさい。

SREの考え方を実務に取り入れた事例は小さなことでもすごく参考にさせて頂いていて、今回のSREに触れるキッカケの話でも誰かのヒントになれば幸いです。

具体的に起こしたアクションの話もまたどこかで紹介できれば良いなと思います。
最後までありがとうございました！
2D IDCT を計算する ~ Python


# はじめに
Pythonを使って2D IDCTを計算します。

# code

```py:test.py
from numpy import *
from scipy.fftpack import dct, idct

set_printoptions(linewidth=200, precision=1, suppress=True)

def dct2(a):
    return dct( dct( a, axis=0, norm='ortho' ), axis=1, norm='ortho' )

def idct2(a):
    return idct( idct( a, axis=0 , norm='ortho'), axis=1 , norm='ortho')

a = array(
  [
    ( 568,     0,     0,    -4,    -4,     0,     4,     0 ),
    ( -27,     9,    -4,    -4,     0,    -5,     5,    -5 ),
    ( -49,    -4,     4,     4,     0,     0,     0,     0 ),
    ( -12,    -4,     0,     0,     5,     0,     0,     0 ),
    ( -14,    -5,     0,     0,     0,     0,     0,     0 ),
    (  -5,     0,     0,     0,     0,     0,     0,     0 ),
    (  -5,     0,     0,     0,     0,     0,     0,     0 ),
    (   0,     0,     0,     0,     0,     0,     0,     1 ),
  ]
);

print("a=")
print(a)
print("idct2(a)=")
print(idct2(a))
print("dct2(idct2(a))=")
print(dct2(idct2(a)))
```

実行します。

```
> python --version
Python 3.4.3
> python .\test.py
a=
[[568   0   0  -4  -4   0   4   0]
 [-27   9  -4  -4   0  -5   5  -5]
 [-49  -4   4   4   0   0   0   0]
 [-12  -4   0   0   5   0   0   0]
 [-14  -5   0   0   0   0   0   0]
 [ -5   0   0   0   0   0   0   0]
 [ -5   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   1]]
idct2(a)=
[[ 52.9  53.6  54.8  54.   53.   56.3  50.3  56.9]
 [ 67.9  70.5  71.4  68.1  65.2  68.6  62.4  66.4]
 [ 74.4  78.4  80.5  75.   72.   74.5  70.   71.2]
 [ 74.7  78.5  81.3  78.3  75.3  77.5  75.1  76.2]
 [ 75.7  76.4  80.1  78.9  78.2  77.5  78.4  79.5]
 [ 75.6  74.   76.1  76.4  76.   75.   77.3  77.4]
 [ 73.3  71.   72.3  70.7  72.5  72.7  77.1  73.9]
 [ 67.   65.6  66.1  63.6  66.5  69.6  75.   69.4]]
dct2(idct2(a))=
[[ 568.   -0.   -0.   -4.   -4.   -0.    4.   -0.]
 [ -27.    9.   -4.   -4.    0.   -5.    5.   -5.]
 [ -49.   -4.    4.    4.   -0.    0.    0.   -0.]
 [ -12.   -4.   -0.   -0.    5.    0.    0.   -0.]
 [ -14.   -5.   -0.    0.    0.    0.   -0.   -0.]
 [  -5.   -0.    0.    0.   -0.    0.    0.   -0.]
 [  -5.    0.    0.    0.   -0.   -0.    0.   -0.]
 [   0.    0.    0.   -0.    0.   -0.    0.    1.]]
```
Android WebViewにおけるセキュアコーディングについて

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

はじめに
--
非機能要件として機密性や安全性が求められるアプリの開発をすることとなり、復習がてら日本スマートフォンセキュリティ協会（[JSSEC](https://www.jssec.org/))が公開しているガイドを読み、WebView実装において何が必要かをまとめました。

『Android アプリのセキュア設計・セキュアコーディングガイド』【2018年9月1日版】
https://www.jssec.org/dl/android_securecoding.pdf

### 自社もしくは連携会社が管理していないコンテンツでJavaScriptを有効にしない

自社や連携会社が管理している、もしくは安全性を保証できるコンテンツでなければJavaScriptを有効にすべきではありません。

また、Build.VERSION_CODES.JELLY_BEAN以前で`addJavascreptInterface()`をコールするとリフレクションを用いることができます。

JavaScriptを有効にする＝思っているより危険なコードを実行したり、アプリの権限で端末の情報を抜き取る、あるいは端末を操作することができる可能性があるため有効にする場合は注意が必要です。

### HTTPS（暗号化されたページ）でないページにアクセスしない
自社のサービスにアクセスする際は、悪意ある第三者によるサービスのなりすましによる被害を防ぎ、対象サービスへ確実に接続する必要があります。
HTTPのページにアクセスすることは安全性を保証できないということで、悪意のある第三者への情報流出を防ぐことができません。

### SSL通信のエラーを適切にハンドリングする
SSLエラーが発生した場合、有効期限切れなど証明書に不備があるか、
プライベートな証明書が設定されたり、もしくは中間者攻撃を受けている可能性があるので、安全のために接続を中止する対策が必要です。

```java
// URLリクエストをハンドリングするためのクラス
private class MyWebViewClient extends WebViewClient{
    // SSL通信で問題がある場合にコールされる
    @Override
    public void onReceivedSslError (WebView view, 
                SslErrorHandler handler, 
                SslError error){
        // 接続を停止するなどの処理
    }
}
```

### ブラウザアプリとしてActivityを公開する場合の注意点
例えばサービスのWebページをブラウザで開いていて、その中にアプリへのリンクを設け起動させるURIスキームに対応したActivityを実装する際も注意が必要です。同じURIスキームに対応したマルウェアアプリをインストールさせURLに含まれるパラメータを横取りされるといったことが可能だからです。

また、URIスキームに対応したActivity側では、URLのパラメータを利用する前に値の安全性を確認することが必要です。

```xml:AndroidManifest.xml
<application>
  　// ブラウザアプリとしてActivityを公開
   <activity
    android:name=".BrowsableActivity"
    android:exported="true" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <categoryandroid:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            // 暗黙的intentを受け付ける
            <categoryandroid:name="android.intent.category.DEFAULT"/>
            // Browsable intentを受け付ける
            <categoryandroid:name="android.intent.category.BROWSABLE"/>
            //　URI 'hoge://iridge' を受け付ける
            <data android:scheme="hoge" android:host="iridge"/>
        </intent-filter>
    </activity>
</application>
```

### その他

WebViewの他、センシティブなものを入力する箇所ではロングタップを無効化しClipBoadへのコピーを防ぐなどの対策も必要と考えています。
Java 文字列 複数置換

標準ライブラリ　ちょっと煩雑だけど早いかも

```java
    String str = "$aTEST$bTESTTEST$cTESTTEST$aTEST$bTESTTEST$cTESTTEST";
    // 置換前, 置換後
    Map<String, String> map = new HashMap<>();
    map.put("$a", "AaA");
    map.put("$b", "BbB");
    // ・
    // ・
    // 置換処理(java.util.regex.Matcher)
    Matcher matcher = Pattern.compile(map.keySet().stream().map(Pattern::quote).collect(Collectors.joining("|"))).matcher(str);
    StringBuffer sb = new StringBuffer();
    while (matcher.find()) {
        matcher.appendReplacement(sb, map.get(matcher.group()));
    }
    matcher.appendTail(sb);
    sb.toString();
```


appache commons ライブラリ  簡潔だけど思ったより遅い．．．

```java
    String str = "$aTEST$bTESTTEST$cTESTTEST$aTEST$bTESTTEST$cTESTTEST";
    // 置換前, 置換後
    Map<String, String> map = new HashMap<>();
    map.put("$a", "AaA");
    map.put("$b", "BbB");
    // ・
    // ・
    // 置換処理(org.apache.commons.lang3.StringUtils)
    StringUtils.replaceEach(str, map.keySet().toArray(new String[map.size()]), map.values().toArray(new String[map.size()]));
```
ACS712を使ってみた

#ACS712とは
ACS712とはAllegro社が出している電流センサです．英語が得意な方はこちらをどうぞ．
[ACS712のリファレンスガイド(英語)](https://www.sparkfun.com/datasheets/BreakoutBoards/0712.pdf)
電流に応じた電圧を出力するセンサで，ACDC両方で使えます．
また通常の電流センサはシャント抵抗を流れる電流で計測するのに対して，ホール素子を用いることで導線の間に接続して計測しないので，シャント抵抗分の電力を消費せずに済みます．
その代わりセンサ用に別途5V電源が必要です．
5A, 20A, 30Aの3種類があり，それぞれ0~5Vに応じたレンジが存在します．
素子の特徴の説明(日本語)はこちらをどうぞ．
[ACS712電流センサモジュール - スイッチサイエンス](https://www.switch-science.com/catalog/107/)
#Arduinoで使ってみた
##ハード接続
たぶんC国製のこちらのモジュールを購入．安すぎるやろ...
[ACS712 5A範囲電流センサモジュール](https://ja.aliexpress.com/item/30A-range-Current-Sensor-Module-ACS712-Module/2038552144.html)
ACS712単品だと抵抗やコンデンサを付けないといけないので，モジュールを買うのをお勧めします．
以下接続図．
![ACS-712-Basic-Hook-Up.png](https://qiita-image-store.s3.amazonaws.com/0/246335/efa1c7e0-e99c-a6e0-0d57-8e2390d3c55f.png)
##プログラム
プログラムをどう組むか，最初データシートを見てもさっぱりでした．
が，要は以下のような特性図になっているらしいので，自分でレンジを調整するようです．(海外サイトにいくつかArduinoスケッチは転がってたけど，係数がイミフだったので自分で作ることにしました．)
![ACS712.JPG](https://qiita-image-store.s3.amazonaws.com/0/246335/b60d2523-4468-28d5-f1f6-b08f50cb93b3.jpeg)
以下に5Aの物をArduinoで動かした際のスケッチを載せておきます．

```cpp:ACS712
//CAS712
//使う電流センサのアンペア数
double Ampere = 5;
//現在の電流値(mA)．
double current;
//オフセット値(V)．デフォだと0Vの時センサ値は512(レンジを5Vにすると2.5V)なので ．
double offset = 2.505;
//レンジ調整値．0Vに調整した後，電源等でこの電流計の値が合っているかをチェックして，ズレていれば調整する．
double range = 0.95;
//forを回す回数．大きくすると処理が遅くなるが，電流値は安定する．10000times/secがanalogReadの限界な事に注意．
int times = 100;

void setup() {
  Serial.begin(9600);
}

void loop() {
  current = 0;
  for(int i = 0; i < times; i++){
    //1.5~3.5Vレンジなので2.5Vオフセットすると-1~1V．これを-5~5Vにする為5をかけている．
    current += ((double)(analogRead(A0)) / 1023 * Ampere - offset) / range * 5 * 1000 / (double)(times);
  }
  Serial.print("Current(mA) = ");
  Serial.println(round(current));
}
```

これでシリアル画面を開けばmAの値が見れるはずです．
for文でセンサ値のばらつきを平均しています．要らなかったら外してください．
#まとめ
Arduinoで手軽(？)に使える絶縁タイプの電流センサ．
メリット　：計測対象の電力を消費しない
デメリット：外部電源が必要
オフセットと微調整がだるいですが，逆にそれさえ済めばそのセンサ固有値として非常に精度高く電流値を求めることが出来ます．
Vue.js の Vuex における mapGetters と、 this.$store.getters の使い分け

Vue Component から Vuex の getters を利用する際の、複数ある書き方をどのように使い分けるべきか自分なりに整理してまとめたものです。この考え方が一般的に正しいわけではなく、プロジェクトごとにある程度ルールを決めておくとコードに統一感が出てメンテナブルになり嬉しいので、自分が関わるプロジェクトにコーディングルールを提案するための情報整理です。

## `this.$store.getters['SOME']` 
- 基本的にはこちらを使う

## `mapGetters` 
- 同じコンポーネント内で、3回以上同じ `this.$store.getters['SOME']` は書かない
- template 内で参照したい場合
- computed で宣言したい場合

## computed get set を使う
immutable でななく、変更したい場合は computed を　set と get で書く方法を覚えておくと便利です。

```js:todo.vue
  computed: {
    todos: {
      get () {
        return this.$store.getters['todos']
      },
      set (value) {
        this.$store.commit('SET_TODOS', value)
      }
    }
  },
```

```js:vuex/index.js
const getters = {
  todos: state => state.todos
}

const mutations = {
  SET_TODOS (state, val) {
    state.todos = val
  }
}
```

このように回りくどいような書き方をするのは、単一の方向でデータの状態を管理させるためです。

下記の図では `Vue Components > Actions > Mutations` という流れですが、上記で書いた例では Actions を飛ばしています。Actions を飛ばして書くのはアンチパターンだという説もありますが、私は `Vue Components > Mutations` の流れでも OK だと考えていますので、Vue Component で `this.$store.commit['SET_TODOS']` を利用しています。

![vuex.png](https://qiita-image-store.s3.amazonaws.com/0/62259/00e0d203-5b55-d526-ea61-5bd737895bd1.png)


参照 https://vuex.vuejs.org/ja/

## 使い分けのルールまとめ
`mapGetters` は import して使うので、これがあるとコードを初めて読んだ人でも、Vuex から参照している情報であることが分かります。一方で `this.$store.getters` と書いた場合、Vuex を知らない人が読むとどこから参照している書き方なのか分かりません。ググラビリティ的に `mapGetters` のほうが良いと考えています。

ですが、基本的には `this.$store.getters['SOME']` を使うと書きました。１回しか書かない場合、どこから参照しているか確認する必要がない場合が多いためです。 `SOME` の部分で具体的に何を get しているのかが明確に分かるようにしておけば、OK です。

また、Getters だけではなく、Mutations も Actions もほぼ同じように考えますが、同じコンポーネント内で、　繰り返して同じ commit と dispatch を 3回以上書くことがあまりないため、ほぼ mapMutations と mapActions は使っていないかもしれません。

getters は template 内で参照したいことがよくあるので、mapGetters は高頻度で利用しています。

## 最後に
一般的にルールがあるわけではありませんが、自分で簡単な決まりを作るとコーディングがしやすくなるので、オススメです。気になる点や、ご指摘ございましたらお気軽にコメントください！
re:Inventで発表されたAWS新機能で使いたいと思った機能をリストアップしてみる

[K.S.ロジャース株式会社](https://www.wantedly.com/companies/ks-rogers)の[民輪](https://www.facebook.com/kazuhiro.tamiwa)です。今更ながら11末にあったAWS re:inventで発表された新機能のうち自分が使ってみたいなーと思った機能のみをリストアップしてみます。もっと早く記事にするつもりが、忙しくてできてなかった。。。自分の頭の整理もかねて記事化します。

![Logo-2.png](https://qiita-image-store.s3.amazonaws.com/0/137026/42b29909-3f99-12d8-1d24-34e09791efe6.png)

# Lambda系
## ALB Support for Lambda
ALBのバックエンドにLambdaを紐づけることができるようになりましたねー。
これでLambdaをAPI Gatewayだけじゃなく、ALBに紐づけることでサーバーレスを普通のwebアプリケーションに組み込むことが容易になったはず。
今年の6月に参加したAWS CTO Nightではサーバーレスのことを強く推されていたことを思い出した。AWSは今後もサーバーレス系についてはかなり力をいれていくように思えます。

## Custom Runtime
もうこれはかなり有名ですが、Lambdaでサポートされた言語がかなり増えました。自分はCOBOLで書いてみたいなー(棒)

## AWS Toolkit for popular IDEs
AWS Lambda のコンソールのエディタはぶっちゃけ使いづらくてデバッグもしづらかったですが、拡張機能としてPyCharm、IntelliJ、VSCodeに導入されるのは嬉しい。。。弊社はJetBrainsに身も心を捧げている会社で、自分自身もエディタは普段VSCodeなので非常に嬉しいです。

## Lambda Layer
Lambdaで共通処理を外出しできる機能です。弊社でもバッジ処理をたくさんLambdaで書いているのですが、バッジ処理が多いサービスを運用している中で同じようなビジネスロジックの処理の関数が複数存在しているので非常に嬉しい機能です。
少なくともステージング環境と本番環境で同じバッジ処理を用意する中で共通処理を外だしすることができそうですね。


# DB系
## QLDB
https://aws.amazon.com/jp/qldb/
履歴管理に特化したDBで変更履歴などを保存できるのでRDBで頑張ってアプリケーションを構築する必要がいらなくなりますね。

## Timestream
https://aws.amazon.com/jp/timestream/
時系列データの扱いに特化したDB。自分が使うとしたらアプリケーションのモニタリングとかパフォーマンスのデータ管理でしょうか。


DB系のサービス調べてましたが、グラフDBを扱うのに特化したNaptuneとか去年発表されていたのか。。。見逃していた。。。

## DynamoDBでトランザクションができるようになった
そのまま。地味に嬉しい。。。

# EC2系
## LightsailがEC2に移行できるようになった。
地味に楽な機能。使いうる場面としてはWPをEC2に移植するときだろうと思いますね。

# その他
## GoFormation
弊社はCloudFormationを使ってインフラをymlにテンプレ化しており、GitLabと連携をしたDevOpsまで全てymlでテンプレ化しています。以前オークファンさんとの共同勉強会で内容については発表させて頂いたこともあるのですが、これがGoでかけるようになりました。
Goについては弊社もgRPCをやっていくにあたり力を入れているところなので面白いなぁと。ymlに変換もできるので動的に変更したいパラメータとかが存在するときにはGoで処理系をかいてymlではき出すみたいな処理を書くのも良いですね。

## RoboMaker
実はROSを用いた画像認識と制御のロボット開発を行ったことがあるのですが、とにかく環境構築含め色々面倒でした。当時は画像認識のためのCUDA環境の構築とROS環境を共存させようとしてドライバ周りで不具合が起きまくり文鎮化しまくる事案に陥っていたことを思い出します。この辺楽になるといいなーとぼんやり思っています。

## Transfer for SFTP
S3にSFTPでアクセスできる機能ですね。まぁ、Macを使っていると昨今のFTPクライアントにはS3に接続も機能としては存在しているのであんまり不要かもですが、機能自体は面白いですね。

## StepFunctionsで連携サービスの追加
めっちゃ嬉しいー！連携できるようになったのは以下の通り
DynamoDB
AWS Batch
ECS
SQS
AWS Glue
SageMaker


# 最後
こう整理してみると自分はLambdaが好きなんだなーと思わされる次第。
PRとしてでたApp Meshもマイクロサービス志向の自分にとっては非常に気になるし、Firecrackerも使ってみたいし時間がいくらあっても足りない。。。
サーバーレスが一気に色々進みそうですね。かわりに去年EKSで盛り上がったコンテナ系が非常に悲しい内容となりました。

# Wantedlyでもブログ投稿してます
Techブログに加えて会社ブログなどもやっているので、気になった方はぜひ覗いてみてください。
https://www.wantedly.com/companies/ks-rogers