調べ物した結果

現役SEが仕事と直接関係ないことを調べた結果とか感想とか

SlackのAPI仕様が変わっててうまく動かなくなってたから直した channels.history->conversations.history

目次

以前
couraeg.hatenablog.com
こんな感じでSlack(channels.history メソッド)をGASでスプレッドシートに簡易の問題集を吐き出せるスクリプトを作ったんだけど(ずっと放置してたけど)
知らない間にAPIの仕様が変わっていたようで動かなくなっていた。

ということで動くようにした。

ざっと結果を先に。

・とりあえずうまくいく。
・channels.historyは非推奨だからconversations.historyを使おう。
・conversations.historyは親のメッセージしか読まないから、スレッドを掘りたかったらconversations.repliesも合わせて使おう。
ということでとりあえずいい感じになった。

発生している事象&トラブルシュート

ボタンをクリックして、スクリプトを実行。シートにSlackの問題を書きだすはずが・・・
gyazo.com
とまぁ。スクリプトは正常に動いてるけど全然吐き出されない。なんぞ。

おおよそ辺りはついていて、
gyazo.com
この辺(returnのところで)をブレイクしてみる。仕組みとしてはAPIで受け取ったレスポンスから
Questions(スレッドの開始)とそれにつながるAnswers(スレッドに紐づいてるメッセージ)
を振り分けている想定。
gyazo.com

Questionsが空っぽなので、まるで問題が生成されていない。。。
IsQuestionの実装は単純で

function isQuestion(message)
{
  return "replies" in message;
}

だ。なので、repliesさえちゃんとあればまともに動くはず。もしやと思ってmessageの中を開けてみると
gyazo.com
ご覧のありさまで。パラメータがなくなっている様子。
ひとまずchannels.historyメソッドの公式を見てみましたが・・・それらしきパラメータはresponseにはなさそうです・・・
api.slack.com
変わりにreply_countというパラメータが返ってきてます。こっちも公式には乗っていませんが、ひとまずこれを使ってみることにしました。
latest_replyにはTSが返ってきているのでこれも使えそうです。そのように変更してみます。

こんな感じに直します。

/**
 試験データとして扱いやすいように加工して返却する。
 */
function convertExamItems(response)
{
  var messages = fillExamMessages(response);
  var sortedMessages = orderByTimeStampeAscending(messages);
  Logger.log("formatExamItem:sortedMessages{" + sortedMessages + "}");
  
  // timeStampをキーとして、問題(リプライがあるか)と回答で分ける。
  var questions = {};
  var answers = {};
  for(i in sortedMessages)
  {
    var message = sortedMessages[i];
    if(isQuestion(message))
    {
      questions[message["ts"]] = message;
    }
    else
    {
      answers[message["ts"]] = message;
    }        
  }
  
  var examItems = [];
  for(key in questions)
  {
    var question = questions[key];
    //var replieKey = question["replies"][0]["ts"];
    var replieKey = question.latest_reply;
    question["answer"] = answers[replieKey];
    examItems.push(question);
  }
  return examItems;
}

function isQuestion(message)
{
  //return "replies" in message;
  return message.reply_count > 0;
}

試しに実行しました。
gyazo.com
とりあえずそれっぽく動くようになりました。あっていたらしい。

ところで、公式に不穏な記述があるぞ・・・

よく見るとAPIのレスポンスにも書いてあるんですが、いまつかっているAPIは非推奨なようで。。。
conversations.history
をつかっちゃいなよ!
みたいなことが書かれています。ということでとりあえず呼び出すAPIを変えてみます。
gyazo.com
あばばばばば。。。ということで公式見ながらデバッグします。
前と同じ場所にブレイクを張って見ます。
gyazo.com
今度はAnswerが一つもありません。母体となるmessagesのほうを見てみましょう。
gyazo.com
どうやら2件しか返ってきて稲用です。QとAで2組あるので、4件来る想定ですが。
どうやらQの部分しか取得できていないようです。公式説明を読んでみます。

conversations.repliesをつかう。

api.slack.com
残念ながらreplyに関する記述はここからは読み取れませんでした。観念してググって見ます。
dev.classmethod.jp
の中に答えがありました。
conversations.repliesを使えばよいようです。公式の方もみてみます。
api.slack.com

This Conversations API method returns an entire thread (a message plus all the messages in reply to it), while conversations.history method returns only parent messages.

ということで、こっちにはおもいっきりconversations.historyでは親しかとれないよ。と書いてました。うまく組み合わせて使う必要がありそうです。
conversations.repliesはthread_idの指定が必要です。なので、まとめて一気にとるような使い方ができません。
histolyでスレッドを特定して、内容はrepliesでとるようにしてみます。

function cannelReplyURL(thread_ts)
{
  var url = "https://slack.com/api/conversations.history";
  url += "?";
  url += "channel=" + channelID;
  url += "&"
  url += "ts=" + thread_ts;
  Logger.log("cannelReplyURL:{" + url + "}");
  return url;  
}
/**
 * UrlFetchAppを使って結果を返す。
 * @param {string} Request URL
 * @param {Object} Request Option Parameters
 * @return {Object} Get Request Response Json Object
 */
function fetchApp(url)
{
  var response = UrlFetchApp.fetch(url, token);
  var parsedResponse = JSON.parse(response.getContentText());
  Logger.log("getRequest:{" + parsedResponse + "}");
  return parsedResponse;
}

/**
 試験データとして扱いやすいように加工して返却する。
 */
function convertExamItems(response)
{
  var messages = fillExamMessages(response);
  var sortedMessages = orderByTimeStampeAscending(messages);
  Logger.log("formatExamItem:sortedMessages{" + sortedMessages + "}");
  
  // timeStampをキーとして、問題(リプライがあるか)と回答で分ける。
  /*
  var questions = {};
  var answers = {};
  for(i in sortedMessages)
  {
    var message = sortedMessages[i];
    if(isQuestion(message))
    {
      questions[message["ts"]] = message;
    }
    else
    {
      answers[message["ts"]] = message;
    }    
  }
  
  var examItems = [];
  for(key in questions)
  {
    var question = questions[key];
    //var replieKey = question["replies"][0]["ts"];
    var replieKey = question.latest_reply;
    question["answer"] = answers[replieKey];
    examItems.push(question);
  }
  */
  var examItems = [];
  for(i in sortedMessages)
  {
    var apiResponse = fetchApp(cannelReplyURL(sortedMessages[i].thread_ts));
    var question = apiResponse.messages[0];
    question["answer"] = apiResponse.messages[1];
    examItems.push(question);
  }
  return examItems;
}

/*function isQuestion(message)
{
  //return "replies" in message;
  return message.reply_count > 0;
}
*/

fetchAppはもともとあるものを再利用。なんだかよくわからないループもすっきりしました。バッチりです。

SQLのたてもちよこもち。たてもちからよこもちへ

SQLを触っているとよくでてきますが。そのたびにGoogle先生に問い合わせをしているような
気がしています。ということで定着させるためにも一回まとめることにしました。

とりあえず検索

SQLもテーブル構造も出ていてとてもよくまとまっているので、このURLを覚えておくだけで事足りるのでは・・・
dev.classmethod.jp

定着が目的なので、自分でもやってみます。

検証環境

AWS RDS(SQL Server Express Edition)
SSMS v18.4
を使いました。
AWSSQL Serverをたてて、SSMSで接続するシンプルな形です。

テーブル

こんなノリのやつを用意しました。
gyazo.com
ステータス事の値を横に持ちたい。ということはあるでしょうから、こんな感じでしょう。

とりあえずくっつけてみる。

WINDOW関数もなく、そのまま「えいや!」でくっつけるとこんな形のSQLになるかとおもいます。

select
 emp.employee_id,
 st1.qualification_id,
 st1.value as status_1,
 st2.value as status_2
from
 employee_qualification emp
 left join qualification as st1
 on emp.qualification_id = st1.qualification_id and st1.status = 1
 left join qualification as st2
 on emp.qualification_id = st2.qualification_id and st2.status = 2

実行結果は
gyazo.com

こんな感じで。性能がどうのこうのなければ、このままでもいいんでないかと思います。
せっかくなので、プロファイル情報も取得します。
「SETSTATISTICS PROFILE ON」で取得を有効にすると
gyazo.com

こんな形で取得できます。TotalCostは「0.0104844」
実行計画も以下の通りで。
gyazo.com

JOINをしてるので当然かもしれないですけど、やたらとNastedLoopsがでてきます。
ただただ横持ちを取りたいだけなのに、なんだかこれはいただけない感じがします。

いまはステータスが2つだけなのでいいですが。4つ5つとなった時にこれは無駄なことをしている感じが大きいです。

ということでいい感じにしていく。

今回はRow_Number等でとる必要がなさそうです。Statusわかっているから
まずは横持ちのテーブルぶぶん

select
	st.qualification_id,
	max(case st.status when 1 then st.value else '' end) as value_st1,
	max(case st.status when 2 then st.value else '' end) as value_st2
from 
	(
		select
			qualification_id
			,status
			,value
		from qualification
	) st
group by
	st.qualification_id

gyazo.com
実行計画もいい感じに落ち着いてます。これをそのまま先ほどのクエリに結合していきます。

こんな感じかと。

SET STATISTICS PROFILE ON
select
 emp.employee_id,
 st.qualification_id,
 st.status_1 as status_1,
 st.status_2 as status_2
from
 employee_qualification emp
 left join
 (
	select
		st.qualification_id,
		max(case st.status when 1 then st.value else null end) as status_1,
		max(case st.status when 2 then st.value else null end) as status_2
	from 
		(
			select
				qualification_id
				,status
				,value
			from qualification
		) st
	group by
		st.qualification_id
 ) st
 on emp.qualification_id = st.qualification_id

実行結果は同じようです。ここがずれていたら意味ないですからね。
gyazo.com
コストの方もよいほうに収まりました(0.00686062)
gyazo.com
実行計画も見ておきましょう。
gyazo.com
コンピューティングスカラーは気になりますが・・・気にしていたループの本数が減りました。やったね。
このままでも大分いい感じですが、今後のメンテナンス(出したいステータスが増えたときに)
そこそこ厄介なので、以下のようにしておきます。

select
 emp.employee_id,
 st.*
from
 employee_qualification emp
 left join
 (
	select
		st.qualification_id,
		max(case st.status when 1 then st.value else null end) as status_1,
		max(case st.status when 2 then st.value else null end) as status_2
	from 
		(
			select
				qualification_id
				,status
				,value
			from qualification
		) st
	group by
		st.qualification_id
 ) st
 on emp.qualification_id = st.qualification_id

これで単に必要なステータスが増えた場合でも、一か所修正すればOKとなります。
めでたしめでたし。欲をいえばもう少しわかりやすい位置に移動したいですが、今回はここまでとします。



データって一口に言うけど意識しないとまずいのでは


こんばんみAWSの勉強をしていてどうにも「データ」を「データ」のまま適当に認識して取り扱うと、
さっぱり理解が進まない気がしているの自分用に少し整理してみました。その他関連用語が多いので使いどころを含めて。

完全に個人の感覚なのであれですが。

目次

なにが気になったのか?

冒頭のとおり「データ」ってなんじゃ?という疑問。
データといっても、その性質によって名前がつけられています。
・ストリーミング
・キャッシュ
・記録
雑に分けてもこんな感じ。オンプレミスであれば、基本的にPCのメモリかもしくはSSDに打ち込まれるので、
開発する上では特に意識してこなかったんだけど、AWSサービスはインフラに近いところから選定が必要なので、この辺をほっておくとどうにもこうにも立ち行かず。
ちょっと一旦まとめてみようかいね。

「データ」が共通的に持っている性質

・データ構造
・タイムスタンプ
この二つは普遍的で必ず持っている。データ=情報といっても差し支えないかもしれない。
ある特定の時間(タイムスタンプ)における、特定のデータの抽出(データ構造)に名前をつけたものをデータと読んでいる。
Excelファイルもデータ「Excelデータ」、日次の感情や思い出などの記録は「日記」であったり。ここまではそらそうだ間があってあんまりではある。
この辺りは上記「記録」と記述しているが、データの基本的な形となる。

データ種別の判断

データ種別の判断は以下のことで決まっている。
・生存期間
ポイントはデータそのものに生存期間の属性は持っておらず、データを取り扱う方が勝手に決めている。
なので、同じデータ構造、タイムスタンプを持つ「データ」でも取り扱う側からすると「キャッシュ」であったり「記録」であったりする。

ストリーミング

そもそもデータではない。と思っている。ストリーミングにもデータ構造は持っているが、タイムスタンプの形が異なる。
タイムスタンプはその瞬間を切り取っているが、ストリーミングでは永続的に流れ続けている。データの連続がストリーミング。
そのくせにストリーミングデータ。なんていうからタチが悪いなぁなんて思ったりもする。一つのストリーミングは同じデータとして扱うが、
ストリーミングから切り取った一部のデータは同じデータとしては扱はない。同じデータ構造は持っているが。
1つの動画であれば、動画は「開始、終了」を属性に持つデータ構造の「データ」ではあるが、あるタイミングの動画は動画と言わず、
「静止画」というと思う。時間がずれれば「別の」静止画としてあつかう。静止画ももちろんデータ構造を持っている(RGBとか、まぁそのた)

キャッシュと記録

生存期間が極端に短いものを「キャッシュ」という。どの程度短いかはデータを取り扱う側に委ねられる。
1日以上保持するものを「キャッシュ」ということは少ないかもしれないが、それでも場合によりキャッシュと言うことはある。1年だとどうかはわからないが。
キャッシュにはもう少し使う側のイメージによるものがある。
アクセシビリティ
キャッシュの目的は「再利用」にあるので、データを一度保存した後にどこからか「利用」することが前提となる。
「記録」についても再利用は発生することもあるが、キャッシュを用いる場合は「記録」とするよりも「高速」にアクセスすることを求める場合が多い。
「記録」にするまえのデータを「キャッシュ」と呼ぶこともある。
「記録」から別のElastiCacheなどのメモリに展開したものを「キャッシュ」と呼ぶこともある。
dynamoDBなどのストレージに「記録」をしないデータも「キャッシュ」と呼ぶことがある。
いずれもこれは生存期間によって判断しているためで「キャッシュ」をS3などのストレージなどに保存して永続化したタイミングで「記録」となる。
ストリーミングで吐き捨てたデータについて「キャッシュ」と呼ぶことはないが「記録」の判断のためにストリーミングからデータとして取り出すことを
「キャッシュ」する。とは言うかもしれない。

同時編集からの観点

ストリーミング、およびキャッシュを複数のアカウントから意識的にアクセスすることは基本的にはない。同時編集を行う場合「記録」であることがほとんであろう。
したがって同時編集を意識しないといけないのはストレージサービスである
右記urlより、 AWS が提供するクラウドストレージサービス|AWS
S3
EBS
EFS
のこの辺りは抑えておきたい。S3、EFSは並列の読み込みに耐えうるが、EBSは向いていない。
その他は公式QAを参考にされたし
aws.amazon.com
また、ストレージサービスではないがデータの保管場所という観点では各種DBサービスも候補に上がってくる。
(キャッシュという意味ではSQSも近いものがあると思うが)
DBの比較についても公式を
AWS が提供するクラウドデータベース | AWS

キャッシュが曲者

基本的にキャッシュが全てをややこしくしている。キャッシュという観点でいけば、
インメモリに展開しているEC2とELBのスティッキーセッションでも構成なども上がってくる。
完全にクラウドのメリットを享受できるような構成ができればいいが。状況によりそうもいかない時もあるので、手段はなるべく多くしっておいて損はなさそう。
キャッシュについては本当にいろんなところに保管できるので、その時のベストというのを理解するのがなかなかしんどいなぁと感じる。

こんなところか?「データ」の切り口からAWSざっと眺めてみたけど、この方が記憶に定着しやすいかな。
セッションとか、ログイン情報とか。データ構造による切り口で攻めてみるのもありかな。

S3のイベント通知でSNSに通知を飛ばしてみる

はろーはろー。こんばんみ
お祭り期間ではあるんですが、ちょっと思いついたことをやりたくなってしまったのでそっちを優先しました。

目次

とりあえずできたんか?

掲題の件、できもうした。
SNSサブスクリプションに設定してある、私の携帯へSMS通信がきっちり届きました。
gyazo.com

とどきましたが。これじゃ何が何だかなので。このままではいけませんね。

構成

S3 → ファイルアップロード → SNSトピック → SMSメッセージ
の流れ。AWSで何かしようと思うと、たくさんサービスが現れてくるので慣れないと戸惑いますが。
ちっさくちっさく作っていくと少量でいけたりするので良いですね。

作業手順

SNSトピックを作る。

gyazo.com

名前はご自由に。緊急通報のRSSでも受け取って遊ぼうかなーと思っていたのでそんな感じのトピック名になっています。
S3からの通知を受け取るにはデフォルトのポリシー設定ではたりません。
以下のようなポリシーを追加してやる必要があります。

{
   "Sid": "example-statement-ID",
   "Effect": "Allow",
   "Principal": {
     "Service": "s3.amazonaws.com"  
   },
   "Action": [
    "SNS:Publish"
   ],
   "Resource": "arn:aws:sns:Region:account-id:topic-name",
   "Condition": {
      "ArnLike": { "aws:SourceArn": "arn:aws:s3:::bucket-name" },
      "StringEquals": { "aws:SourceAccount": "bucket-owner-account-id" }
   }

buckecName,AccountIDなどは調整が必要です。
※S3のHowToを参考に貼っておきます。
docs.aws.amazon.com

通知確認のために、一緒にサブスクリプションも作っておくと良いでしょう。

S3バケットのイベント設定をする。

バケットを作ってプロパティタブからイベントを選んで設定していきます。
prefix、Suffix等オブジェクトの情報である程度フィルタがかけられるようですが、今回は無視しています。
gyazo.com

前述のポリシー設定がうまく言っていないと、保存時に以下のようなエラーがでます。再度確認してみてください。
gyazo.com

発火するか

最後にバケットに適当なオブジェクトを投げ入れて通知が飛ぶか確認してみます。
結果は前述の通り、なんか帰ってきます。Goodですね!

最終目標

実はこれはまだ完成ではなくて、RSSのメッセージをうまいことごにょって遊ぼうかな。とおもって。
ひとまずSMSの通知部分から作るかなーとおもってやってみました。
lambda等経由する必要があるかなーとも思っていましたが、直接SNSに通知ができやったぜ。と言ったところ。
単純にResponseを返してしまっているので、このままでは使えなさそうなので結局lambda等の経由は必要そうですが、
S3への配置等が起因で発火できるのはいいですね。もっと定期巡回とか必要かと思っていましたが。やったぜAWS

オンデマンドセッション店回り感想(Day6)

本当はDay7。昼休みに書き溜めたものを下書きに上げ忘れてて「まーいいか。」の精神で
機能はアップできていなかった。ということで本日もお祭りを見ていく

1日目と同様、念のため。利害関係はありません。内容を避難するようなものでもありません。
アップするつもりで視聴する。アップするつもりでざっとまとめる。今回の記事の意図としてはそんなところです。

目次

お祭り会場① DE:CODE

www.microsoft.com

ゼロトラスト Deep Dive 間違いだらけのリモートワーク セキュリティ

https://decode20-vevent-media.cloud-config.jp/59f5a39e-2eea-49dc-bc43-28a7912327e3/thumbnail-decode20_S08-000001.png

安心安定のVPNという幻想。ゼロトラストと実は相反する。

アクセス元の識別→身元の確認認証→認可
認証と認可はだいぶ理解できてきた。
信頼レベルに応じて、アクセス制御をする。本人でも信頼レベルが落ちるというはすごい。
ふむ。これAWSでしようと思ったら、
認証にlambdaを介在させて、ポリシーを差し替えるような形になるんだろうか。
aws.amazon.com
公式の記事があった。うーん。認証はいける気がするが、認可の柔軟性はデフォルトであまいのかなぁ。

Azure ならこうする、こうできる! ~ AWS 技術者向け Azure サービス解説 de:code 2020 Edition ~

decode20-vevent.cloud-config.jp

よい。クラウドサービスの違いを見るということ。何がやりたいの?からスタートしよう
クラウドバイリンガルAWSも一つの手段だし、手段は多いほうがいいのは納得。そして
それらを使いこなせるならすごい「価値」だとおもう。
さて、あーんまりAWSの話はでてこなかったな。冒頭でも言っている通り、サービスそのものを比較してもしょうがないからだろう。
というところで。AWSと比較してもらったほうが理解するには楽だったりするかなーとおもったけど、全体的にAzure概要的な内容だった。
半分ぐらい。あとは飛び飛びでみて途中で視聴をやめてしまった。

会場② DEVELOPERS.IO 2020

classmethod.jp

AWSのDatabase・Analytics系サービスの概要と使い所をざくっとおさらい

youtu.be
以下のアイコンが判断できる人は見なくていいらしい。
gyazo.com
※画像は動画より引用。
lambdaとS3と。うーん。わっかんね。見よう。

みた。前半は関連するサービスの概要を話していくれる。
大体なんとなく理解できた。ないってるのかわっかんね。はなかったので、地力がついてきたのかなぁ。
残りの目的別も極端には驚きがすくなかった。サービスの名前も毎日見てるとだいぶ覚えてくるな。
最後のリンクを全部みたらもう一段高みへ行けるだろうか・・・ぜひ読んでいかねば

まっとめ。

よくわからなくても毎日。休まず(休んだが)見ていると違う。
ついでに「いまのオンプレなどうする」みたいなことを通勤道中で考えるようになった。
考えてわからないから答えってのはすぐに見つからないのでFBとしては弱いのだけど、ちゃんと公式をおっていったり、
先人たちの記事を見れば追いきれる。いい時代だなぁ。。。

オンデマンドセッション店回り感想(Day5)

月曜が始まってしまったのであいもかわらず放出されつづけるセッションを追っていきます。

1日目と同様、念のため。利害関係はありません。内容を避難するようなものでもありません。
アップするつもりで視聴する。アップするつもりでざっとまとめる。今回の記事の意図としてはそんなところです。

目次

本日のお祭り会場① Developers.IO 2020 connect

ついに来た!Amazon Detectiveでセキュリティインシデントの調査がちょー捗るからまずやってみよう

インシデント調査が超捗る。とはいいねいいね。
NISTの話が出ていた。
https://www.manageengine.jp/solutions/nist_publications/nist_csf/lp/
なかなかえぐいぜ。セキュリティはこの上で更新も頻繁なので、真面目にやるとこれだけで時間食われますね。
ログ調査を自動で吸い込んでくれるのはいいなぁ。インシデントもそうなのかもしれないけど、
エラーログ等攻撃的な不具合検知に使えないだろうか。

GuradDutyがそもそも強い感じがする。誤検知も考えるとネットワーク周りを触った時は確認したほうが良さそうだなぁ。
誤検知にまみれると本体が見えなくなるし。
1日目だか2日目にみたGoatと組み合わせて遊ぶのが学習には楽しそう。

早朝に見る内容にはちょっと重かったけども。朝だから頭も元気だったので、セーフだったかもしれない。

外に出れないこんなご時世だからこそ、AWS MediaServicesによるライブ配信入門

youtu.be
ピンあんどポイントな内容です。
ライブ配信って身近ではあるんだけど、裏の動き全然わからなくていい勉強になった。
AWSで構築する理由」ちゃんとあるかね。という話はとてもいいなと思いました。
焦点を絞ってるからこそのボリュームを感じるセッションでした。ちょっとだけMediaServices。わかるようになりました。

まとめ

これで6/16配信分はひとまず見切ったはず。見切っただけ。
全部無料でこのクオリティってのがね。ありがたく視聴させていただきます。せっかくみたんだから今後に活かせるといいなぁ
行かせないといけんよね。そんなかんじ。

お祭り会場② Microsoft DE:CODE2020

www.microsoft.com

Office365

Teams。
www.microsoft.com
なるほど。これに限らず、こーゆーのなんていうんだ?
ワークサービスというか機関部分というか。選択肢が多いのはうれしい。しかし業務で実際に選定されるのはどれだろうか。
各社特色があっていいのだけれど、いろいろ使うようになるのはつらかったりつらくなかったり(比較できるおかけで改善点が見つかったりはするかな)
いろんなIDE渡り歩くような気分で、なるべくデフォルトから離れたくなくなるのは私だけなのだろうか。
いやーしかし。市長普通にでてくるんだよな。最近。ご時世。すばらしい。
というかこの市長のはなしすごく貴重というか、いい意見だと思う。これだけでもみてよかったなぁと思った。
あんまり、普段仕事をしていてエンドユーザの声って聞きにくいんですが(クレームは間接的に届くけど)
大事ですよね。やっぱり使ってくれる人の意見というのは。

セキュリティオーバービュー

セキュリティマネジメント
https://it.impress.co.jp/articles/-/11116
SecurityPosture ゼロトラスト、Modern SOC
単語はなんとか拾えたが。。。これは他の詳細なセッションをみろということだな。
別々の会場でセキュリティの話するんだもんなぁ。一口にセキュリティといっても考えないといけない範囲は広いくて、
私は「セキュリティ」と一口にいってしまうレベルではあるんですけど。
セキュリティは基盤なので、セキュリティがあってこそ開発ができる。普段は邪魔ではあるんだけど。
邪魔をしないように相互に良い影響があるといいねぇなんて。そーゆー感じになってきてるかなーと思います。最近のセキュリティ。

まとめ

さぁ。基調講演はなんとか見切りました。
Microsoftはどことなく、使い方がなんとなく想像できるのが頭にやさしいなぁと思います。
AWSはちょっと想像が届きにくいんですよね。僕のバックボーンの問題かもしれませんが。

家系ラーメンがめちゃくちゃ食べたい。食べたいから作ってみたらなんか違う感じになった。

こんばんみ。ラーメン好きですか?私はめちゃくちゃ好きです。
というよりジャンクフード全般が好きで、時々無性に食べたくなります。
とくに、東京で生活していた折によくくってたラーメンが非常に食べたいですが、岡山在住のみではなかなか厳しい。
(1週間出張とかないかなぁ・・・)
tabelog.com

濃厚オブ濃厚。辛いまであるレベルで濃厚です。確実に体にダメージを与えてきそうな味ではあるんですが、
くせになるんですね。はー食いたい。ということで思い出しながら家にある食材で作ってみようということで頑張ってみました。

材料

どうせすぐに食べたくなってしまうので、
材料は手に入りやすく安価であること。また加工が楽であるところがポイントになります。
(この辺はそうでないなら店にいくしな。ということで)
・もやし、刻みネギ(ここは好み)
・牛豚ミンチ
・ニンニクチューブ
・鶏ガラスープのもと
コンソメスープのもと
・醤油
・砂糖
・塩
・冷凍うどん
だいぶ謎なアイテムもありますが、1から全部近所のスーパーで集めても1000円切るんじゃないですかね。

調理です。

とりあえず具材、タレ、その他を集めます。こんかいはもやしだけなんで、茹でるだけっすね。

こんな感じ。
gyazo.com
簡単ですね。

スープづくり

水を張った鍋にミンチ肉を放り込んで加熱。火が通ったら
鶏ガラ、コンソメのもと、砂糖を入れて完了。
gyazo.com
灰汁取りも何もしてないので見た目はすごくわるい。

もりつけ

タレと少量スープを混ぜ合わせ、麺、具材、最後にスープをダバーっとしてニンニクチューブをふんだんにひり出すと完成。
gyazo.com

こんな感じ。

実食。フィードバック

とりあえず子供2人は満足いただけた様子。奥様にも好評だったけどパンチが足りないとか塩が足りないとか言われた。
実際僕の方も「にたような味はするけど、なんか違うなこれ。。。」そんな感じ。美味しい。普通に美味しいけど
「はぇー身体にわっるー。けどうっめぇぇぇええええ!!!!」ではない。「あっ。うま。うんうん。おいしいおいしい」そんな感じ。
敗因を考えるにだいたい以下だと思う。

スープの煮込みが甘い。

そもそも煮込んでないのだけれど。だいたい家系ラーメンのスープってトロトロ、ドロドロしてるんだけど。
作ったやつはサラサラしてた。水分とミンチの割合をミスってたのかもしれない(ミンチ自体も加熱すると水分でるしね)
次はもうちょと水分をコントロールして作ってみることにする。

ニンニク感が弱い。

最後にチューブニンニクを放り込む形で再現したのだが。
効いてるところの再現度は高かったように思う。タレ作成時に醤油が不足していて塩の量をミスってたのもあり、
ニンニクのパンチがないのは致命的だったかもしれない。それでも美味しかったのだけど。
つぎは1球つかう勢いで刷り込んで見ることにする。

何がどうあっていい感じに再現しようとしたか。

前述のとおり安価かつ手軽(特殊な調理器具とかが入らない)かつ材料の入手が容易(食べたい時に食べられる)
をめざしつつ、既存のラーメン記事などを読みながら工夫しました。

スープについて。

記事を見る限り、家系ラーメンのスープは鶏ガラと豚骨をに出して作ったものが多いようです。
どちらも入手はなんとかなりますが(それも近所スーパーにはない)面倒ではあるし、価格もそれなりです。
また「出汁をとる」行為は素人には難しいです。失敗するとつらい。ということで代用品を考えました。
大事な構成要素は
・鶏ガラ
→鳥由来 の出汁→鶏ガラスープのもと。楽勝。安い。完璧
・豚骨
→豚肉由来の出汁→牛豚合挽きミンチ。
どん二郎なるものから着想。ようは肉の脂がいるのだと解釈。どん二郎は牛脂を使用していました。のであえて合挽きで行ってみるか。という形。
牛脂の入手が容易なスーパーであれば、牛脂もあると良さそうです。
・野菜
→だいたいの記事によると、野菜の甘みが重要なようでした。こちらも多量の野菜が必要になってしまいます。
 ということでコンソメでいいんじゃね?ということでコンソメのもとを使うことにしました。
・あと砂糖。砂糖は美味しいのです。上記甘みもありますが、人の舌は砂糖への反応は敏感です。スーパー安肉も砂糖につけこんでおくと謎のうまさを発揮します(甘いという感じないのに。うまくなるんだすねぇ)
 ということで砂糖も適当にぶち込んでおくことにしました。だいたい美味しいものは「砂糖」と「脂」でできている。

ということでスープの着想はこんな感じ。そもそも市販のもとがメインなのでまずハズレはしないでしょう。

ラーメンのたれ

家系ラーメンではかえし。といわれる醤油ベースのタレを使います。
これをスープと混ぜて調整します。いろいろ記事を見る限り、大量に必要で長期間煮込むスープには塩分を加えず、
塩加減はこちらのタレを混ぜ合わせることで調整する様子でした。
なので「醤油」と「塩(醤油だけで合わせるのは難しいかもしれない)」電子レンジに放り込んで軽く熱して塩をとかしておきましょう。
あとついでに砂糖も入れました。タレっていってるし。
スープにぶち込んだらええのでは?という思いもありますし、実際味を調整しながらするならそっちのほうが楽だと思います。
私の場合、小さな子供も含む家族にも振る舞うので、ここで塩分の調整が聞くのはプラスでした。

ニンニク

ここをおろそかにすると味わいが変わってしまいます。
実際今回は味わいが再現度が低くなってしまった要因はこのニンニクと分析しています。
ひとまずチューブでも美味しいですが、可能であれば国産の香りのよいニンニクをすりおろして入れたほうがよいでしょう。
中国産のやっすいやつは「辛い」だけで再現度が薄いです。好みもあると思いますがね。お値段気にしなければ国産ぶち込みましょう。
今度は中国産でやってみます。

材料のなかでも異才をはなっている。と思わしきうどん麺。実際妻にも「ラーメンと行っていたのでは?」といぶしがられています。
ようは特徴的な「極太麺」と麺に含まれる「塩味」を再現するにはうどん麺のほうが都合がよかったんですね。
ということで讃岐冷凍うどんを打ち込むことにしました。
こちらもどん二郎を参考に。あれもうどんですからね。いけると思いました。実際いい感じでしたよ。
何をもって頭が「ラーメン」「うどん」と認識しているのか謎です。

まとめ。

品川出張させてくれ。蒲田とか川崎のへんでもいいよ。
それかふらっとしれっと入れる感じで岡山にないかなー。