ローカルPC上の開発中のネットワークサービスを外部公開できるサービスngrok

はじめまして、私はPhiと申します。
システム開発業務に携わってます。

最近は外部サービスと連携するためwebhookを開発しています。
webhookなので、オンラインURLがないとテストできないです。
毎回テストするため、elasticsbeanstalkへデプロイするのは結構面倒 + 時間かかります。
上記の解決策を探していたら、ngrokを見つけました。

NGROKとは?

ngrokとは「セキュアトンネル経由、NATおよびファイアウォールの背後にあるローカルサーバーをパブリックインターネットに公開」というサービス。 f:id:phint:20200831225715p:plain

利点は?

  1. webhook/chat bot 開発する時にとても便利
  2. モバイルアプリもしくはSPAのバックエンドサーバをdebugできる
  3. リモートでお客さんにウェブサイトのデモを紹介できる
  4. ローカルサーバを別の環境(スマホwindows/linux/macos)でテストできる

使い方

ngrokでアカウントを登録して、アプリをダウンロードしたら使えます。

  1. アカウント登録:
    このサービスは無料で使えますが、有料プランもあります。開発のみの場合は無料を使っても全然問題ないと思います。
    ここで登録してください。
    登録さた後、ダッシュボードへ遷移されます。
    ここで認証ためのコマンドを見えます。
    例: ./ngrok authtoken xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    アプリダウンロードした後、例のコマンド叩いたら、ログインできます。

  2. アプリダウンロード:
    ダウンロードリンクです。
    私はmacOS使っていますが、windowsも大体同じです。
    ※下記画像はmacの画像になります

まずはダウンロードファイルを解凍します。そのあとは terminal を起動して、解凍先のフォルダーへ移ります。(私はApplications フォルダーに解凍しましたから、Applicationsへ移ります)
f:id:phint:20200901123155p:plain ここで、上記の認証コマンドを実施します。 f:id:phint:20200901123711p:plain ここまでは準備のステップは終わりました。ngrok使いしょう!
./ngrok http <port> この簡単なコマンドでローカルサーバがパブリックインターネットに公開されます。私のローカルサーバは port 3333 で動いてますから、 ./ngrok http 3333 実施します。これは結果です。 f:id:phint:20200901125700p:plain httpsのリンクもあります、便利ですね。無料プランですから、毎回コマンド実施したらランダムURL返却されます。
ngrokのダッシュボードページでURLも見えます。 f:id:phint:20200901130104p:plain そして、コマンド実施結果の Web Interface http:127.0.0.1:4040 をアクセスすればリクエスト詳細を検査できます。 f:id:phint:20200901130359p:plain

他の機能も色々ありますが、今回の記事はここまでになります。皆様ngrokを試して楽しんでみてください!

PHPのメモリについて(Part2)

どうもこんにちは。BriswellのTuanと申します。
今日また、PHPのメモリについて続きたいと思います。
前回の内容を参考したい方は下記のリンクを参考してください。

PHPのメモリについて(Part1) - Briswell Tech Blog

PHPは自動的にメモリ管理できると言うことを分かりましたが、何を管理しているのでしょうか?

まず、値代入参照代入を簡単に説明します。
PHPには基本的にオブジェクト以外各変数は値代入です。
例えば下記のコード確認しましょう:

<?php 
$a = 1; 
$b = $a;    
$a++;    
var_dump($a, $b);  
    
$x = (object)['value' => 3]; 
$y = $x;    
$x->value = 10;  
var_dump($x); 
var_dump($y);

実行結果

int(2)

int(1)

object(stdClass)#1 (1) { ["value"]=> int(10) }

object(stdClass)#1 (1) { ["value"]=> int(10) }

$a, $bの値は簡単にわかるでしょうか!
しかし、$x$yはどう思ういますか? $x, $yはオブジェクトですから値代入ではなく、参照代入ので、
個別のオブジェクトですが、実際は同じメモリ位置に参照しますので、$xを更新すると、$yにも反映されます。

関数の引数もデフォルトは値渡しです。

<?php 
function fnByVal($v) { 
        $v = "test";  
}   

// 参照渡しを指定
function fnByRef(&$v) 
{   
        $v = "test";  
}   
$y = 'Briswell';    
fnByVal($y); var_dump($y); 
fnByRef($y); var_dump($y); 

実行結果

string(8) "Briswell"
string(4) "test"

上記のコードを実行して、fnByValを呼んだ後に$yの値はそのまま「Briswell」でしょうか! でもfnByRefの場合、$yの値更新されました。

ちょっと面白いと思いますが、下記のコードを実行したら、結果は想定と同じでしょうか!自分で試して、是非コメントで説明してください。

<?php 
function fnByVal_($obj) {  
        $obj->value = "test";  
}   
$x = (object)['value' => 1]; 
fnByVal_($x); var_dump($x);    

PHPは必要であれば、自動的にメモリをアロケート又は解放します。
ただし、「必要であれば」はいつでしょうか? これから、色々を試しながら確認しましょう。

※注意:以降の例は基本的に検証の想定通りですが、PHPバーションによって、メモリ管理方違う部分があるので結果違います。ご注意してください。

例1:

<?php 
    $mem = memory_get_usage();    
    $a = str_repeat("1", 1000); // ①       
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
    $b = $a;                    // ②
    $c = $b;                    // ③ 
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
        
    $a = $a . '1';               // ④ 
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
        
    unset($b);                   // ⑤ 
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
    unset($c);                   // ⑥ 
        
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 

実行結果

used mem: 1280
used mem: 1312
used mem: 2592
used mem: 2592
used mem: 1312

ソース見るだけ分かりずらいと思いますが、下図を見てください。

f:id:tuanda:20200831183105p:plain

f:id:tuanda:20200831183143p:plain

配列も同じ管理方です。
例2:

<?php 
$mem = memory_get_usage();    
$a = array_fill(0, 1000, '1'); 
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$b = $a;    
$c = $b;    
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$a[0] = '2';   
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$a[] = '1'; 
echo count($a)."\n";  
echo count($b)."\n";  
echo count($c)."\n";  
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
    
>unset($b);   
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
unset($c);   
    
>echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";   

実行結果

used mem: 36920
used mem: 36952
used mem: 73872
1001
1000
1000
used mem: 73872
used mem: 73872
used mem: 36952

例3:

<?php 
$mem = memory_get_usage();    
$a = array_fill(0, 1000, (object) array('x' => '1'));  
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$b = $a;    
$c = $b;    
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$a[0]->x = '2';    
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$a[] = '1'; 
echo count($a)."\n";  
echo count($b)."\n";  
echo count($c)."\n";  
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
    
>unset($b);   
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
unset($c);   
    
>echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";   

実行結果

used mem: 36960
used mem: 36992
used mem: 74288
1001
1000
1000
used mem: 74288
used mem: 74288
used mem: 37368

試した結果上で、PHPには同じメモリエリアに複数変数が参照できますが、
それぞれの変数がいずれか更新したい場合は別のメモリエリアをアロケートします。
これは大切だと思います。

*データベースから数万件のデータ抽出する時に、注意しないと、「Fatal error: Out of memory」発生可能性が高いです。

例えばデータ処理はほとんどForeachというループ命令を使ってますが、下記の2つバーションのForeach確認しましょう。

一般的バーション

<?php     
$mem = memory_get_usage();        
$a = [  array_fill(0, 1000, '1'),      
        array_fill(0, 1000, '2'),     
        array_fill(0, 1000, '3'),     
        array_fill(0, 1000, '4')];        
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";     
foreach ( $a as $key => $item) {        
     $a[$key][0] = '9';       
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";     
}       

実行結果

used mem: 148056
used mem: 185384
used mem: 222304
used mem: 259224
used mem: 296144

参照バーション

<?php 
$mem = memory_get_usage();    
$a = [  array_fill(0, 1000, '1'),  
        array_fill(0, 1000, '2'), 
        array_fill(0, 1000, '3'), 
        array_fill(0, 1000, '4')];    
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
foreach ( $a as <b><span style="color: #0000cc">&</span></b>$item) { 
    $item[0] = '9';        
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
}   

実行結果

used mem: 148056
used mem: 148152
used mem: 148184
used mem: 148216
used mem: 148248

結果見ると、どちら効率かすぐ分かりますね。でも、一般的皆あまり参照のバーション使ってないと思います。

PHPは自動的にメモリを解放できますが、必要であれば、自分達「unset」で解放できます。
PHPソースには配列を多分一番よく使うデータ型ですが、参照代入ではなくて、値代入ので、ご注意してください。
意外の増やすメモリのケースが多いと思います。

ではPHPのメモリについてここまで終わります。
みなさん是非試して確認して、実際のプロジェクトに適用すれば、良かっただと思います。

動画の人物をホネホネ化

今回のAIブログは、骨格検出(通称:ホネホネ化)についてご紹介いたします。
骨格検出とは、動画または写真の中から人物の骨格を検出する技術となります。
サクッとどのようなものなのか、見ていきましょう。

【下北ラヴァーズ】スマートスピーカー

こちらの弊社Uri&Yuki漫才コンビ「下北ラヴァーズ」のダンス動画について骨格検出をしてみます。

微妙にシンクロしていないですね...(いや微妙というか全然かも!?)
骨格検出を利用すれば、実際にどのくらいシンクロしていないかを数値で定量的に評価することもできます。

骨格検出には「tf-pose-estimation」というモデルを使用します。
これは以下の「OpenPose」という骨格検出アルゴリズムを「TensorFlow」用に移植したものとなります。

github.com

では、早速ですが検出結果を見ていきましょう!

youtu.be

ほぼ完璧にホネホネ化できていますね。素晴らしいです。
骨格の位置を可視化するだけでなく、骨格の各ポイントについてXY座標で出力することもできます。

例えば、右腕の座標位置の推移を見てみると

f:id:KenjiU:20200901185451p:plain
Uri(立ち位置左)の右腕の座標位置推移

f:id:KenjiU:20200901215246p:plain
Yuki(立ち位置右)の右腕の座標位置推移

f:id:KenjiU:20200901185550p:plain
UriYukiの差分

X座標の差分が徐々に大きくなってきてますね...
このように「微妙にシンクロしていない」というのを数値で評価することができるようになります。面白いですね!

次は具体的にシンクロ度「何%」と出せる仕組みも作っていきたいなと思っております。

Briswell AI Team

20代に読んでほしい書籍

こんにちは加藤です。 8月はオリンピック・パラリンピックのないまま今日で終わり、明日から9月になります。 2020年も残り4ヶ月、123日しかないです。

f:id:brix:20200831212406j:plain Pic by Skeeze at Pixabay

ブログネタに困っていたところ、社員がお題をくれたので乗りたいと思います。

・20代に読んで欲しい書籍

これ読んどきなさい的なやつを、経営者目線で書いて欲しいです。 社員のだれかが読んで、アンサー記事を書くところまでストーリー化したいです。

20代に読んでほしい書籍を紹介するなどと、おこがましいなと思いながらも、 ブリスウェルは平均年齢も若いので、初老の僕はそういう役割なのでしょう、素直に書きます。

そもそも僕の20代の頃はまだKindleがなく、紙の本を書店で買う時代〜ネットで買う時代の過渡期だったと思います。

以前勤務していた会社では、週次サーキュレーション(社内配送サービス)があったので、

Amazonから会社に送って転送してもらい、出張先でうまく受け取るといった、おばあちゃんの知恵のようなライフハックがあったものです。

今回は20代のころの本の読み方と、今の読み方をmixしながら紹介したいと思います。

ーーーーーーーーーーーー

20代に読んでほしい書籍

20代のころはPJTに入る際には、関連する領域の本を10〜20冊程度まとめてざっと読むということをやっていました。

大きめの書店、当時の八重洲ブックセンターや、渋谷ブックファーストなどへ行って、お目当ての領域の目についた本を手当り次第、持てるだけ買います。

多くのビジネスマンの情報収集法にこの手法が出てきますので、僕も誰かに勧められたのかもしれません。

ただこの読み方はおそらく名前がついていません。

「スタメン20」などと呼びたいところですが、尾原和啓さんの「本のメートル買い」が一番適切かと思います。 logmi.jp

① ウォームアップ

短期間でビジネスパーソンとしてのいろはを身につけるための、入門編の定番たちです。

・入社1年目の教科書 岩瀬 大輔 (著)

何度か社内で新入社員に配った気がします。

就業経験・起業経験のない新人向けに心構えを説く本としては最高の1冊、これだけで十分だと思います。

・経済ってそういうことだったのか会議 佐藤 雅彦 (著), 竹中 平蔵 (著)

広告・メディア界と経済・アカデミア界のスーパースター同士の対談で、 マクロ経済・ミクロ経済の基本的な考え方を、柔らかい文章で書いてあったと記憶しています。

・コンサル一年目が学ぶこと 大石哲之

最近斜め読みしたのですが、平易な文章で若手に向けたハウツー本で、受け入れやすかったと思います。

MBAより簡単で英語より大切な決算を読む習慣 シバタ ナオキ (著)

MBAも英語も重要だと思いますが、決算を読めるとあるいは読む習慣があると強いでしょうね。

・図解入門ビジネス シリーズ

未だにですが、就職活動大学生向け・初心者向けのイメージのあるこのタイプの書籍も大好きです。

このシリーズと類似シリーズで計20-30冊は買ったのではないかと思います。

結局は、業界・企業に詳しくなればなるほど、こういった入門書に書いてあることが必ずしも正しくない、新しくないことがわかるのですが、 初心者が数時間で概要を掴むにはうってつけです。

ユースケースとしては、移動や出張の際にぷらっと書店に寄り、本格派に加えてこういった入門書を書い、まず入門書で肩慣らしするというのがよくあるパターンでした。



② 考え方の基礎

考え方を考える、見せ方を考えるなどと思考自体についての書籍達です。

・企業参謀 戦略的思考とは何か 大前 研一 (著)

今となっては経営学(経営工学)がデータドリブンとなって、これが書かれたときとは意思決定の依拠となるデータ・ファクトの厚みが全く違うのですが、 考え方の教科書としては未だに名著と言えると思います。

何度か紙で買った気がしますが、今はKindleで廉価版が出ていて良いですね。

・意思決定のための「分析の技術」 後 正武 (著)

こちらもかなり時代を感じる内容ですが、考え方の基礎として良い教科書です。

今はビッグデータをツールに打ち込めばあとはソフトウェアが分析してくれるというのが早いのでしょうが、その背景を理解しておくことが重要かと思います。

・考える技術・書く技術―問題解決力を伸ばすピラミッド原則 バーバラ ミント (著)

こちらも定番のハズですがKindle版がありません。人気ないのでしょうか。

「君の話はわかりづらい」などと言われる若手は是非読んで体得すべきかと思います。 うちの20代の皆さん、敢えて一冊だけといえば、これです。これをまず読んでください。

③ 業界のいろは

インターネット、ソフトウェア開発、エンタプライズ、DXなどと、インダストリー(業界)カット・業務領域カットなどでフォーカスを絞って集中して読むのが良いと思っています。

※この「インダストリーカット・業務領域カット」は、コンサルファームやエンタプライズSIでは一般的なのですが弊社のような若い会社にはあまり浸透していないので、別の機会に書きたいと思います。

・インターネット的 糸井重里 (著)

2001年時点でインターネットを「リンク」「フラット」「シェア」と特徴づける糸井さんの慧眼に、やられます。

・【全15巻合本版】角川インターネット講座 村井 純 他 (著)

村井先生に始まりJoi Itoに終わる壮大なSagaです。

・令和2年版 情報通信白書 総務省 (著)

敢えて読まなくても良いのですが、最新情報があふれるなか少し立ち止まって、ストックとなっている公知の情報を眺めて見るというのも良いものです。

自分たちが思っているより、テクノロジー自体はもっと先に行っている一方、その社会実装は全然進んでいません。

パラノイアだけが生き残る アンドリュー・S・グローブ (著)

僕の20代の頃はWinTelが兎に角強くて、ペイジとブリンが出てくるまでは、ビル・ゲイツアンディ・グローブがヒーローでした。

最近、新装で再発されたので新しいバージョンが良いと思います。

トヨタ生産方式 大野 耐一 (著)

最後は少し毛色が違います。 20台の頃、以前の会社で僕は通信業界の部署にいたので、製造業に深い造詣があるわけではないですが、最近Kindleで見つけたので紹介です。

製造業の生産管理、在庫・BOM管理、原価管理の基礎があると、エンタプライズ領域なら他業界でもなんとかなります。

また業界の大著は抑えておくと、クライアントと最低限のプロトコルがあいます。

ーーーーーーーーーーーー

なお、今回紹介したのは仕事の為のインプットという観点での書籍です。

つまりはPJT開始時に情報のシャワーを浴びるときの書籍たちなので、複数冊を並行して辞書のように使うのが通常です。

Kindle版へのリンクで紹介しましたが、上記の用途を考慮すると紙の本の方が使い勝手が良いかもしれません。



・以下ブリスウェルの今月の新製品のご紹介:

日々のExcelや紙の業務をクラウドで一元管理して効率化したいというご要望に答えて、販売管理/ERP領域のSaaSをリリースしました。 ぜひお問い合わせの上、触ってみてください。

〜 業務のアイカタであり続けたい 中小企業様向け クラウドERPソリューション 『アイカタ(ai-cata)』〜 bit.ly

Postmanで配列とファイルをPOSTする話

連日の猛暑が続くなか、自宅のPC部屋にクーラーがなく、リビングで運転しているエアコンの風をサーキュレーターと扇風機を駆使しながらリモートワークしているid:rosoneです。

熱中症対策をしながら、ギリギリ無理のラインで頑張ってます。

はじめに

APIサーバのテストでPostmanを使用しているのですが、文字列・配列・バイナリファイルをセットしてPOSTするリクエストをうまく作れず、ハマりました。

振り返ってみると別に難しいことはないのですが、どのようにセットすればよいかを紹介します。

前提

サーバー構成

f:id:rosone:20200820184848p:plain
サーバー構成

  • サーバー構成は上記の図を参照
  • 今回はAPIサーバに対するテストをPostmanで実施

画面

f:id:rosone:20200821113517p:plain
画面イメージ

  • 姓名・セイメイ:文字列
  • 好きな食べ物:文字列
    • [追加する]ボタン押下で、入力フォームが増える(配列で送信)
  • プロフィール画像:画像データ
  • [登録する]:ボタン押下でareKoreCreateAPIを実行
  • バリデーションは無し

API

f:id:rosone:20200820185447p:plain
API仕様

  • Content-Typeはapplication/json
  • URI Parametersの情報をDBに登録
  • バリデーションは無し

Postmanのリクエス

姓名・セイメイ

f:id:rosone:20200820192226p:plain
リクエスト:姓名・セイメイ

form-dataを選んでそれぞれのKEY/VALUEにセットするだけなので、とてもシンプル。

好きな食べ物

form-dataどうやって配列を指定するのかよくわからない...。

ちなみに僕が好きな食べ物はハンバーグです...。

よくわからない①

f:id:rosone:20200821105308p:plain
NG①
f:id:rosone:20200821111020p:plain
NG①-②
VALUEを配列っぽくセットしてみるが、NG。

SUCCESS①

ぐぐってみたところ、jsonをそのままセットすればOKとのこと。

f:id:rosone:20200820193345p:plain
SUCCESS①
rawにJSONを書いてあげればうまく行った。

プロフィール画像

よくわからない②

f:id:rosone:20200821105702p:plain
NG②
好きな食べ物の配列を送るためにraw(JSON)でリクエストを作ったが、バイナリファイルをこのJSONにセットするやり方がわからない...。

SUCCESS②

一旦好きな食べ物のことは忘れて、そもそもバイナリファイルどうやってリクエストにセットするのかをぐぐってみると、form-dataでKEYの形式をtextからFileに変更すると、ファイル選択ボタンが出現するらしい。

f:id:rosone:20200820195105p:plain
SUCCESS②

無事にsibusawa-jidori.jpgをセットできた。

全てのパラメータをセット

さて、ここからがブログタイトルの通り、本題となります。

よくわからない③

配列はrawにJSONを書けばよいが、そうするとraw(JSON)で画像をセット出来ない。

f:id:rosone:20200821105702p:plain
NG②

画像はform-dataでKEYをFileに変えればセットできるが、そうすると配列の表現方法がわからない。

f:id:rosone:20200821105716p:plain
NG③

ハマりました。もうわからない。

Sending an array as form-data - Help - Postman

最終的にこの問題を解決してくれたのはPostmanのフォーラムに記載してあった上記ページの一文、

  • タイトル:Sending an array as form-data
  • コメント:use key[]: value

でした。

既にform-dataでファイルをセットするリクエストは SUCCESS② で成功しているので、あとはそのform-dataに上記の配列を追加してあげれば解決、ということになります。

SUCCESS③

実際にセットするとこんな感じになります。

f:id:rosone:20200821111339p:plain
SUCCESS③

カタクチイワシは配列の[0]、セキトリイワシは配列の[1]として送信されることを確認できました。

配列の添字も有効のようで、

f:id:rosone:20200821115322p:plain
SUCCESS③-②
このように表現することも出来ました。

おわりに

今回は手を動かすよりも色々とぐぐって「これはもう試したけど駄目だった!!」とやっていた時間が多かったです。

最終的には公式のフォーラムにどんぴしゃの答えがありましたので、

  • オフィシャルのリファレンスを読み込む
  • オフィシャルのフォーラムを覗いてみる
  • 日本語以外でも検索してみる

ここらへんを教訓にして、次に出会う課題ではもっと短時間で解決できるようにしていきたいと思います。

Neo4jを試してみた

どうも、こんにちは。としと申します。
毎日暑いですね... みなさま熱中症にはお気をつけください

私は最近在宅勤務とオフィス出勤 大体 8 : 2 くらいの割合で仕事をしております。
在宅勤務ですと、定時の18:30 ~ お酒を飲むことも可能になります。

通勤時間がない分酔うのも早い... 酒量がどんどん増えていく...
というスパイラルに陥りそうになったので、気持ちを切り替え AWS ソリューションアーキテクト プロフェッショナル レベルを取得しよう!と勉強を開始しました。

アソシエイトレベルは昨年取得したので、自信はそれなりにあったのですが、すぐ無くなりました。
Neptune
グラフ型データベースにぶち当たりました。


グラフ型データベース... 触ったことない...

よし... まずはグラフ型データベースとやらを触ってみよう!
という環境作りの備忘録になります。

私のPCはMacです。

下準備

JDK をインストール
(ターミナルで、

java -version

と入力するとPOPUPが出てくるので、詳しい情報をクリックすると開いてくれました)
Java SE Development Kit 8 - Downloads

Neo4j Desktop をインストール
※名前やメールアドレスなどの入力が必要です。
※ダウンロード画面の認証キーは後ほど必要になります。
Neo4j Desktop Download - Launch and Manage Neo4j Databases
インストール完了後、ダウンロード画面の認証キーを入れる画面が出てくるので、入れる。

するとこんな画面が出てきました。
f:id:Toshi_bw:20200819133942p:plain

Movie Database

デフォルトで Movie Database というのが用意されている!
これで色々試せるのか!
優男!
...
ブラウザで

http://localhost:7474/browser/

と入れる

f:id:Toshi_bw:20200819142758p:plain

このような画面が表示されました。
調べてみると、デフォルトは neo4j / neo4j で入れるとのことだったので入れてみると、

f:id:Toshi_bw:20200819142910p:plain

入れない... 優しくなかった...
よくわからないので、Neo4j Desktop に戻り、 Add Database をクリック
Create a Local Database を選択すると
Set Password があるので好きなPassを入力(DBMS Name はデフォルトのままにしました。)
作成されたらStart してみる
こんな状態
f:id:Toshi_bw:20200819143223p:plain

もう一度ブラウザでアクセス、UserName は neo4j でPasswordは先ほど入力したもので接続してみると
やっと入れたっぽい!
f:id:Toshi_bw:20200819143351p:plain

そして

Guide: Example Datasets - Neo4j Graph Database Platform

ここに書いてあった

:play movie graph

を画面上部の
neo4j $
部分に貼り付け、再生ボタンを押す。
なんか出た。
f:id:Toshi_bw:20200819143601p:plain

1つ右に行くと

f:id:Toshi_bw:20200819143651p:plain

Create文がある。再生ボタンもある。押してみると、上に貼り付けられたので、再度再生ボタンを押してみると、、、
f:id:Toshi_bw:20200819143729p:plain

おぉー、出てきた...
Tom Hanks...

f:id:Toshi_bw:20200819151409p:plain

蜘蛛の巣みたい...

今日はここまで...
内容薄くてすみません... どんどんアップデートします

グラフ型データベース...
格闘しつつ、メリット / デメリットを語れるように頑張ります。

システム開発プロジェクト成功の秘訣 ー 要件定義編

こんにちは、ブリスウェルの山口です。

リモートワークを始めて4ヶ月以上が過ぎました。
リモートワークが当然のように馴染んだ人、やっぱオフィスがしっくり来る人、色々あると思います。

ブリスウェルでは7月から出社を全面的に解禁し、自己判断で出社とリモートワークを選択するという試みを始めています。出社時間や帰社時間も自由に決めて良いということにしました。
東京では感染者数も収束しているわけではないので正直どうすべきか悩ましいところなのですが、シンプルに基本に立ち返って、パフォーマンスが発揮できれば働く場所はどこでも良いという考え方を基本に据えようと思ってこの試みを決めました。
まずは始めてみて、様子を見ながら軌道修正が必要であれば修正する。そういうスタンスでやってみようと考えています。

さて、今回は前回の提案編の続編ということで、要件定義編と題して私の考え方をご紹介していきます。

提案フェーズで競合との競争を勝ち抜き、いよいよプロジェクトがスタートします。
まず始まるのが要件定義フェーズになります。

進め方はプロジェクト内容や規模によって様々なので、ブリスウェルでよく手がけることの多い業務系アプリの再構築プロジェクトのような案件をイメージしてご紹介していこうと思います。

要件定義フェーズでとても重要な要素は以下の点だと考えています。

1)体制
2)要件ヒアリング
3)既存システムの調査
4)領域を横断できる人
5)データ

さて、個別に見ていきましょう。

1)体制

f:id:yamagoochi:20200702095641j:plain
体制

お客様とベンダーで両方とも体制は重要ではあるのですが、とりわけお客様の体制で重要なポイントがいくつかあります。

・プロジェクトに要件を抽出できるキーマンがいること、もしくはキーマンにコンタクトできること
・課題のレベルに応じて素早く判断をできる体制であること
・領域横断的に要件を把握し、適切な決定を行えるリーダーがいること

様々な領域でのヒアリングが同時並行的に進む要件定義フェーズでは、現状業務を漏れなくベンダーに説明し、新たにやりたいことを正しく伝えられるかがとても大切です
特に新たにやりたいことに関しては様々な検討課題が議題として上がってくるため、課題に応じた会議体でできるだけ早く解決法を決定していく必要があります
一番良くないのは課題を後回しにして、曖昧な部分が残った状態で開発のフェーズに入ってしまうことです

ベンダーにはお客様が直面する課題に対して、過去の経験や技術的観点から解決案や解決の道筋を提案できることが求められます

・要件定義においてベンダー側の体制は経験豊富なプロジェクトリーダーを立てること
・技術的に課題を解決するための提案をできるメンバーをアサインすること

ベンダー側はこのような観点で体制を組み立てられると非常に良いと思います

2)要件ヒアリング

f:id:yamagoochi:20200702095706j:plain
要件ヒアリング

まず現状業務を把握することが非常に重要ですが、現状にとらわれないことも重要です
現状を漏れなく把握した上で、新しいビジネスや業務のあり方を再構築していくのが王道だと思います

まずはお客様のビジネス(顧客、商品・サービス、仕入先、商流のパターンなどなど)を理解し、ドキュメントで可視化していきます
どのようなビジネスケースが存在していて、それぞれがどのような業務やデータの流れで構築されているのかを明確にしていくのです

お客様側で全ての領域のビジネスや業務を100%漏れなく説明できる方はほぼいないので、ベンダー側が第3者的な視点でQAを繰り返し、抜け漏れなくヒアリングできることがとても重要です
提案編で「お客様の見えない要求を嗅ぎ分ける」ことを重要なポイントとして挙げた理由もここにあります

次に新しくやりたいことの大枠をお客様からヒアリングするわけですが、ほとんどの場合はシステム化できるレベルで詳細化されていません
現状ヒアリングで得た情報を元に、新技術や様々なサービスなどを組み合わせながら新らしいビジネスや業務を構築していくことになります
様々な検討課題に対して、調査や費用対効果の分析などを実施して、決定をしていくことになるため、できるだけスムーズにお客様側で決定いただくための下準備をしていくことが重要です

不要な業務やシステム要件をバッサリと切り捨てることも非常に重要です
スケジュール的な制約で現状機能があるので今後も必要だという判断を行うケースもありますが、業務ボリュームが少ないとか複雑すぎるような要件に関しては、開発工数も膨大になるケースが多いため、システム機能を実装せず業務での対応が残るという選択肢を常に持っておくことも重要です

3)既存システムの調査

f:id:yamagoochi:20200702095727p:plain
既存システムの調査

業務アプリの再構築プロジェクトでは業務をヒアリングする流れの中で必ず既存システムが登場します
要件ヒアリングでの抜け漏れを防ぐ目的で、既存システムの画面、帳票、データベース、機能を漏れなく調査することが大切です

以下のようなメリットがあります
・要件や機能の抜け漏れを防ぐことができる
・業務要件を深掘りできる詳細な質問ができるようになる(データ項目やリスト値のレベルで現状を理解します)
・データ移行の下調べになる

私の経験上、既存システムには使っていない機能がごっそりあるケースがあります
その場合は、要件定義で不要な機能が入り込んでいないか、要件が複雑になりすぎていないかを特に注意する必要があるかもしれません

2と3の調査ができて、初めて現状が把握できた状態になるイメージです

4)領域を横断できる人

f:id:yamagoochi:20200702095750j:plain
領域を横断できる人

プロジェクト規模が大きくなればなるほど、お客様もベンダーも問わず、領域を横断的に把握できる人が少なくなります
全体の流れが常に頭の中に入っていると、以下のようなメリットがあります

・領域ごとの要件に不整合が出ることを防止できる
・領域をまたがる課題の解決が早くなる
・ユーザー部門へ新システムを普及させる際に幅広い観点からうまく説明ができる
・リリース後の追加改修の際に影響調査を効率的に行える

5)データ

f:id:yamagoochi:20200702095809j:plain
データ

業務アプリで最も重要なのはデータです
アプリケーションの機能やインフラ・ネットワークなどシステムを構成する様々な要素がありますが、全てのビジネスや業務を最終的に支えているのはデータです
そのデータがどのような構造で保持されているのかをデータモデルと呼びますが、この設計をいかにうまく行うかがベンダーの腕の見せ所です
新システムのデータモデルが既存システムのデータモデルから大きな変更を伴う場合、データ移行の工数が非常に大きくなります
現状をより正確に、より詳細に理解し、新しい要件を元に新しいデータモデルを構築できる人がいるかどうかがプロジェクト成功の鍵となると言っても過言ではありません
4で紹介した領域を横断できる人でないとデータモデル設計をすることは非常に難しいです
ベンダー側にこのようなスキルを持つ人がいるかどうかを提案時点や要件定義時点でチェックすることがお客様にとっても重要な指標となります

以上が私が要件定義で大切にしていることになります

今回は考慮すべき要素が多い「業務アプリの再構築プロジェクト」を例にご紹介しました
新しいサービスを構築するプロジェクトだと既存調査のプロセスが無いとか、小規模プロジェクトだと領域横断的な要素が少ないとか、今回のお話を引き算してイメージしていただけるのではないかと思います

インフラやデータ移行など色々と書けなかったこともありますが、重要な5点に絞り込んで紹介させていただきました

皆様のお役に少しでも立つことができたら幸いです!

About the Amazon S3

Hello, nice to meet you.
I'm Shun.

僕個人としてのブリスウェルブログ初upになりますが、最近ちょこちょこAWS関連の本などを読んで学んだ「Amazon S3Amazon Simple Storage Service)」について執筆したいと思います。
※僕自身はAWS歴1年程度ほどでございます

S3は、AWSAmazon Web Servicesサービスのうちの1つで、高耐久・大容量のストレージサービスです。
→Servicesサービスで何か言葉がおかしくなっちゃった
S3について本記事で触れる内容については、次の通りになります。

1. 耐久性
2. ストレージ
3. 静的Webサイト
4. アクセス制御
5. 操作性
6. 使用料

Let's go!

1. 耐久性
・S3に保存したデータは、デフォルトで同一リージョン内の3か所以上のAZへ自動的に複製される
・データの耐久性は99.999999999
 →9が11個並ぶのでイレブンナインと呼ぶらしいです、覚えやすい!

S3は実質100%と言っても過言ではないほど、非常に高い耐久性を備えているため、ただ単にデータストレージとして使用するのではなく、 バックアップデータやその他機密情報などの退避場所としても検討できると思います。
2. ストレージ
・利用容量が実質的には無制限
 ※1ファイルあたりのサイズ制限はあり

実質的には無制限とは言っても、AWSがS3に割いているサーバーの容量を超えてしまった場合にはもちろん制限がかかります。
ですが、そのような事態が起こる可能性は限りなく低いと思います。なぜなら、利用者に制限がかからないよう今後もサーバー台数を増やしていくと思われるからです。
AWSはとにかく規模が大きい!
サーバー費用、設備費用等、年間どのくらいかかっているんだろう・・・と気になっちゃいます。
3. 静的Webサイト
・静的ページを公開できる
 →公開がS3単体で行えるため、サーバー構築不要

Amazon Route53のDNSフェイルオーバー機能と連携して、障害やメンテナンス時によく表示するsorryページを表示したりできます。
4. アクセス制御
ACLでの制御
 →バケットに対して、AWSアカウントレベルのアクセス制御を行う
・IAMでの制御
 →IAMユーザー、IAMロールからの読み取りや更新のリクエストに対して制御を行う
バケットでの制御
 →IPアドレスでの制御など、IAMユーザー以外の他ユーザーに対して制御を行うことができる

このように、S3ではアクセス権を詳細に設定することができるセキュアなサービスのため、非常に高い信頼性・安心感を持てます。
5. 操作性
・画面上での操作が可能
AWS CLIAWS Command Line Interface)での操作が可能

AWS CLIから操作することもできるのですが、僕はCUIよりGUI派(おそらく多くの方がそう?)なので、いつも画面上からポチポチあたって操作しています。
操作画面上はこのような感じのUIです。

f:id:artistyuiguitarelegance:20200805175251p:plain
S3バケット中のファイル
S3の画面イメージを初めて見られた方はどういった印象を持たれましたでしょうか?
僕が初めて触ってみた時には、「何この全体的に角ばった感じのデザインは。すごいシンプルやな・・・」こう思いました。笑
シンプルがゆえに、S3を初めて操作する方でも簡単に操作することができます。
Simple is bestっていいますもんね。
個人的には、非常に操作しやすいと感じます。レスポンスも早いですし。

もうS3最高です。
まだ使用されたことがない方、ぜひ使ってみてください!
もうあなたの虜になること間違いなし。←
6. 使用料
・従量課金制

使用料については、使用した分だけ支払う従量課金制になります。使用に際しての最低料金等はありません。
金額についての詳細は、こちらのAWS公式サイトをご参照くださいませ。
aws.amazon.com
以上、簡単ではございましたが、Amazon S3についてのご紹介でした。

弊社内にはAWSに精通している者(僕のような勉強中の方も含め)が在籍しており、AWSを使用したシステム構築を考えられている方々のお助けになれるかと存じます。
ぜひ、お気軽にお問い合わせいただけますと、非常に幸いでございます。

それでは今回はこの辺で✋
See you next time!

PHPローカル開発環境 Devilboxを試す

はじめに

PHPのローカル開発環境として、Devilboxを試してみました。

Devilboxの日本語の記事が見当たらないので簡単にまとめます。

Devilboxとは

公式サイトの説明によると、 "LAMPやMEAN環境をフルサポートしたPHPスタック。 主な目標はローカル環境のバージョン切り替えを容易にすること"とあります。

The Devilbox is a modern and highly customisable dockerized PHP stack supporting full LAMP and MEAN and running on all major platforms. The main goal is to easily switch and combine any version required for local development.

環境のイメージとしてはLaraDockとよく似ていますね。

Laradockと比較するとDevilboxは公式ドキュメントが充実しているような気がします。

https://raw.githubusercontent.com/devilbox/artwork/master/submissions_diagrams/cytopia/01/png/architecture-full.png

上記は公式の画像ですが、最小構成のApache, PHP, MySQLのみ起動することも可能です。

お客様の環境がオンプレだったり、Docker化されていない既存案件を手軽にローカルで試してみたい人に向いていると思います。

手元に既にDocker化している環境がある場合はDevilbox導入のメリットは特にないです。(そもそも全部入りなDocker環境は不要という意見もよく目にします。)

この記事でやること

  • 下記の弊社記事に必要な開発環境をMac OS X上でDevilboxを使って構築し、CakePHPのinstallと接続確認まで行います。

tech.briswell.com

手順

Devilboxをclone

$ git clone https://github.com/cytopia/devilbox

envファイルをコピー

$ cd devilbox
$ cp env-example .env

envファイルを編集

このenvファイル編集によりPHPのバージョン切り替えも可能です。

$ vim .env

Macで作業する場合、下記リンクの通りUID, GID, cache設定も.envファイルに

https://devilbox.readthedocs.io/en/latest/getting-started/install-the-devilbox.html#osx-performance

docker-compose upで各コンテナの起動

今回はhttpd php mysqlがあれば良いので末尾にhttp php mysqlと指定します。

$ docker-compose up -d httpd php mysql

PHPコンテナ内に入る

$ ./shell.sh

f:id:usami-t:20200806035432p:plain

PHP、composer、npm、Node.js、Vue CLIを確認

全て含まれていますね。 f:id:usami-t:20200806035629p:plain

CakePHP環境の構築

今回はmy-cake.locをアクセス先として繋がるローカル環境を作成していきます。

# PHPコンテナ内の/shared/httpdにて
$ mkdir my-cake
$ cd my-cake

# CakePHP4のインストール
$ composer create-project --prefer-dist cakephp/app:4.* hello_briswell

# my-cake/htdocsにシンボリックリンクを作成
$ ln -s hello_briswell/webroot/ htdocs

実行した結果、下記のようなディレクトリ構成になります。 f:id:usami-t:20200806045901p:plain

/etc/hostsの編集

Macの/etc/hostsファイルに下記の記載を追加します。

127.0.0.1 my-cake.loc

追記した結果、ブラウザにてDevilboxの管理画面であるlocalhost/vhosts.phpにアクセスするとURLが有効であると表示されます。 f:id:usami-t:20200806050244p:plain

接続確認

http://my-cake.loc/にアクセスすると、無事アクセスできました。 f:id:usami-t:20200806050623p:plain

最後に

プロジェクトを追加したい場合は、別フォルダを作成しhtdocsのリンクを作っていけば良いだけなので簡単です。

Devilboxの管理画面もリンクが色々含まれていて便利そうでした。(phpMyAdminやOpcache Control Panelなどへ遷移可能) f:id:usami-t:20200806053424p:plain

今回の記事では未実施ですが、設定を行えばhttpsも使えるようです。

手軽に開発環境を作りたいときの選択肢の一つとしていかがでしょうか。

AES-256-CBCを利用したPHPによる暗号化処理の実装

はじめまして、naoyaです。
全く別の業種からブリスウェルに入社して4年目になり、普段はお客様との打ち合わせや設計などを担当させていただいております。

新型コロナも中々収束の兆しが見えず、まだ外出がしづらい日々が続いておりますが皆様いかがお過ごしでしょうか?
私はリモートワークで数少ない運動であった毎日の通勤がなくなり当然のように体重が増量しましたが、家で運動が出来るゲームを購入しなんとか減量に成功しました。

今回はそんなリモートワークの中で起きた、とあるプロジェクトに途中から参画して暗号化処理のテストでハマってしまったお話になります。

AES-256-CBC

保存処理の中で、一部の値を暗号化して格納する処理を発見
暗号化処理自体は該当の項目を平文に復号し利用する別の処理が実行できていたため問題なさそうだけど、暗号化自体の確認も兼ねて別のテストで既に保存されたデータ(開発者がテスト用に作ったデータ、平文は不明)を復号して使用出来るようにもしておきたいので、再現可能かテストを続行

DBに格納された値をブラウザ上でチェック出来るツールなんかでさっと見比べて終わりかな、などと思いつつ既存の暗号化処理を利用しているとのことだったので、まずは開発者にチャットで暗号化形式について質問してみた所「SHA-256で実装しています」との回答
SHA-256はハッシュ化で、項目は平文に戻せないとダメなはずなので再度確認するも「戻せます」との返答、いまいち納得がいかないがとりあえずSHA-256でハッシュ化してみる

やはりDBに格納された文字列とは異なっている
これ以上はソースを見たほうが早いな、と思いソースを漁ってみると暗号化処理の部分には"openssl_encrypt"の関数と形式として"AES-256-CBC"が使用されていた。 なんだ、チャットの打ち間違いか。AES-256-CBCは初めて聞いたけど、ここまでわかればすぐ終わるだろう

前提
1. 入力値をAES-256-CBCで暗号化している
2. 暗号化はPHPのOpenSSL関数で実装済
3. 最終的な目的は暗号化された文字列の復号まで

opensslコマンド

AES-256-CBCがどんな形式かはわからないが、詳細は後にしてまずは実装された処理が合っているか確認したいので、再現できるようなツールがないか検索

ツールなどは見つからず、PHPやNode.jsでの実装方法などが出てくる
ローカル環境建てたりは面倒なのでなんとか出来ないか探していたらopensslコマンドの存在を発見
PHPの関数と同じ名前だしこれなら再現できそう、と思いサイトに載っていたコマンドを参考に実行

$echo "test" | openssl enc -aes-256-cbc -e -base64

で"test"をAES-256-CBCで暗号化(-eを-dにすると復号)
-base64オプションを付けてbase64エンコードして表示
これでいけるかな、と思ったらパスワードを求められつまづく
適当に入れても当然結果は一致しない
よく考えると、ソースに書いてある処理の"key"と"iv"について何もしていない
ここまで来てAES-256-CBCについて調べ始める

....
なるほど、opensslコマンドのデフォルトでは入力したパスワードと自動生成されるsaltから共通鍵である"key"と初期化ベクトルの"iv"を生成し、この2つを利用して暗号化を行うのか
それならソースの処理と同じ形でkeyとivを直接指定すればいけそう(-K "共通鍵" / -iv "初期化ベクトル" で指定が可能)

ここで改めてソース内の処理を確認して気づいた
opensslコマンドで指定できるkeyとivはhex(16進数)での指定
一方、ソースのkeyとivは文字列で送っている

あれ、これソース側で送っている文字列を変換したとしてもkeyが変わる = 暗号化文字列が変わるから無理じゃないか。。。
ということで、これ以上は自分の理解では進めなさそうなのでopensslコマンドでの再現は諦める

OpenSSL関数

当初の目的である暗号化のチェックからは逸れてしまうが、こうなるともうソースの処理を逆にしてデコードする方が早そうなのでPHPの処理を再度解読する

$ciphertext = openssl_encrypt($str, $method, $key, OPENSSL_RAW_DATA, $iv);
return base64_encode($ciphertext);

str = 暗号化したい平文
method = aes-256-cbc
key / iv = ソースで処理された値
をそれぞれ持ってきて暗号化→base64エンコードを行っている

ここまで避けてきたけどもう観念してMAMPを起動し、ローカルサーバーを建てる。 当然ソースの入力画面と処理は別のファイル、ただPHPで外部ファイルから処理読み込んだりといったソースを書いたことはないので、1ファイルで処理が実行できるように簡単にフォームを作成

<form method="post">
  <table border="1">
    <tr>
      <td>暗号化したい文字列</td>
      <td><input type="text" name="str" value=""></td>
    </tr>
    <tr>
      <td>key</td>
      <td><input type="text" name="key" value=""></td>
    </tr>
    <tr>
      <td>iv</td>
      <td><input type="text" name="iv" value=""></td>
    </tr>
  </table>
  <br>
  <input type="submit" value="実行">
</form>

とりあえずkey/ivも直接入力する形にして、暗号化処理はソースからツギハギして作成

<?php
  //constant value
  $method = 'AES-256-CBC';

  //screen input
  $str = $_POST['str'];
  $key = $_POST['key'];
  $iv = $_POST['iv'];

  // encrypt
  $ciphertext = openssl_encrypt($str, $method, $key, OPENSSL_RAW_DATA, $iv);
  $encryptresult = base64_encode($ciphertext);

  //screen output
  print ("暗号化したい文字列: $str <br />");
  print ("暗号化結果: $encryptresult <br />");
  print ("key: $key <br />");
  print ("iv: $iv <br />");
?>

これでようやく暗号化された結果(encryptresult)がDBの値と一致した
続けて、復号処理を追加

フォーム

    <tr>
      <td>復号したい文字列</td>
      <td><input type="text" name="encryptstr" value=""></td>
    </tr>

復号処理

  $encryptstr = $_POST['encryptstr'];


暗号化と逆にopenssl_decryptを使って

  $decryptresult = openssl_decrypt($encryptstr, $method, $key, OPENSSL_ZERO_PADDING, $iv);

表示部分

  print ("復号したい文字列: $encryptstr <br />");
  print ("復号結果: $decryptresult <br />");

をそれぞれ追加
注)このソースは「とりあえず動く」レベルの物なので、PHPの作法など色々おかしいかもしれませんが私は開発者ではないのでご容赦ください。

試しに"test_text"という文字列をkey = "testkey" / iv = "testiv"※ で暗号化
※実際は複雑な値が使用されていますが簡略化します

暗号化された文字列は"eivIkeGzth5HH8VgV6Biew=="、これを「復号したい文字列」に入力して同じkey/ivで再度実行すると無事"test_text"が返ってくる
やっと出来た...
f:id:bw_naoya:20200803164148p:plain


おわりに

当然といえば当然ですが、やはり暗号化は複雑なので手軽に再現出来るものでもないですね。
openssslコマンドにしてももしかしたら再現方法があるかもしれないので、ご存知の方がいらっしゃればご教授いただければ幸いです。