読者です 読者をやめる 読者になる 読者になる

根性駆動開発

備忘録とか日記とか

研究室の先輩が開催してくれた学内ctfの話

ctfとはcapture the flagの略で、セキュリティ関連からコアな知識、なぞなぞみたいなやつまで幅広くコンピュータ関連の問題を解き、フラグを見つけ、最も点を稼いだ人が勝ちというゲーム。

↓ここのサイトが始めは参考になった。

qiita.com

めちゃ内輪な話だけど研究室がセキュリティ関係で、ctfもその一環としてやるのでその話。というかwrite up。

世にも需要無い内容だけど備忘録という名目で書く。

ただ、ctfをしてから数日経っていてうろ覚えになっているところも多いので思い出し次第追記していくかもしれない。

確かに画像だ1

ステガノグラフィの問題。詳細はわすれてしまった。

確かに画像だ2

ステガノグラフィの問題その2

殆ど真っ黒のepsファイルが渡される。

stringsコマンドでこのファイルを指定すると命令らしき文字列がたくさん書かれているのがわかる。

epsとかでググってみるとpostscriptという言語で記述された画像ということがわかるのでエディタでそのファイルを開く。

postscriptではfillという命令で対象の領域を塗りつぶすことが出来るらしいのでfillと記述されている部分を削除。

再度プレビューとかでこのファイルを開くとフラグの中身がわかる。

適当にコード編集するとチラチラ文字が見え隠れするのでそれで予想することも多分出来なくはない。けど、全部見れても空白スペース間違って入れたりしてフラグが通らなくて時間がかかった。

数字の文字

8桁くらいの数字だけ渡される。

たぶんASCII文字なのでASCII デコードとかでググって出てきたASCII文字をデコードしてくれるサイトでデコードする。

するとフラグがわかる。

これは簡単だった。

forensicsのやつ

画像ファイルが渡される。 exiftoolコマンドでこの画像を指定して実行するとフラグが表示されている項目がある。

これも簡単だった。

heavyQR

QRコードが渡される。 このQRコードbinwalkコマンドで指定するとzipファイルがあることがわかる。

binwalkd -eでzipを展開し解凍するとカレーの画像とヒントのテキストが出てくる。ヒントのテキストにはFLAG_IS_{T***_M***}とある。

このカレーの画像をexiftoolコマンドで指定して実行すると表示される緯度経度の項目をgoogle mapとかで検索するとタージマハルがヒットする。なのでtaj_mahalがフラグ。

タージマハルのスペルとか知らんのでTから始まる英単語をググったりして結構苦戦した。

wibQR

部分的に情報が欠如したQRコードが渡される。 そのままでは読み取りが出来ないので修正する必要がある。

QRコード ctf みたいな検索ワードでググると似たようなwrite upがヒットする。

そのあたりに記述されている、strong-QR-decorderというライブラリが文字列として読み取った欠損アリのQRコードも読み取ってくれるので頑張って手作業でQRコードの画像を文字列に置換する。

置換した文字列を読み取るとフラグがみつかる。

スーパー作業ゲーな感じで地味に時間がかかった。 研究室の先輩はこれを自動で置換し、読み取れるようにしたツールを研究でつくったそうな。

わーい、すごーい!

フレンズっぽい大量の文字列が記述されたファイルが渡される。

たぶんbrainfu*k系の言語っぽいので適当に置換ツールでbrainf**kの命令に対応するよう変換する。

branfu*k コンパイルとかでググるとbranf**kのコードを実行してくれるサイトが出るのでそこに完成したコードをコピペして実行するとフラグがわかる。

なぜかすぐわかったし、適当に置換していって完全に実行可能になったのでこのときが一番脳がキレてたんだと思う。

crypt2

めちゃ長いよく分からない感じの文字列が書かれたファイルが渡される。

文字列の末尾が==で終わっているのでbase64エンコードされた文字列とわかる。

なので base64 -D < デコードするファイル名 > 書き込むファイル名 で変換。

このときに書き込むファイルの拡張子をtxtとかで変換し、そのファイルを開くとなにも書かれていないっぽく見えるテキストファイルが開く。

実はここに白文字でフラグが記述されている。

ファイルの拡張子をtxtにしなかった場合、そのファイルを binwalk コマンドで指定するとzipファイルがあることがわかるので、binwalk -e エンコードしたファイル でzipファイルを開けるようにする。

zipファイルを解凍すると.xmlで終わるフォルダが出てくる。 この中にあるxmlファイルと読んで行くと word microsoft うんたらみたいなキーワードが出てくるのでこのxmlのフォルダはwordファイルなんだなということが推測される。

なのでエンコードしたファイルの拡張子をdocxとかにしてあげるとwordファイルとして開くことが出来る。

開くと表示されている画像の後ろに白文字でフラグが記述されている。

一番時間かかったと思う。さんざん困って最終的に白文字オチで笑うしかなかった。

client

バイナリファイルが渡される。

実行権限を与えて実行してみると、><の文字だけ表示されて終了する。問題がネットワークの分野に分類されていたのでとりあえずwiresharkを起動、特定の通信を読みとる。(あまり憶えてない)

その通信をみるとhttp通信をしていることと、websocketが使われていることがわかる。(たしか)

clientというファイル名からwebクライアントかなにかでリクエストをしていることが予想されるのでwebsocketの通信が可能なサーバのコードを記述する。今回はnode.jsで記述した。

var app = require('http').createServer();

app.on("request", (req, res) => {
    console.log(req);
}).listen(8080);
var io = require('socket.io').listen(app);
io.sockets.on('connection', (socket) => {
    console.log(socket);
});

これでクライアントがフラグを表示してくれるようになる。

感想

友達とみんなでわいわいやりながら解いていったのでとても楽しかった。

そして回答中は先輩方がどんどんヒントを出してくれたのでソーシャルエンジニアリングが捗った()

結果は4人中2位。1人は途中からバイナリの問題しかやらんと言ってそれだけ頑張ってたので実質3人中2位。平凡。

遅刻して午後から来た友達が1位をさらっていったので悔しかったが、まあ初心者だしということでよしとしたい。

まだまだ問題はたくさんあったが、時間の関係で解ききれなかった。解ききれないくらい作問して下さった先輩方が超絶すごい。すごすぎて来年の今頃自分がそうなっている想像が出来ないのでかなり頑張らないといけなそうだった。きっと未来の僕が頑張ってくれていることだろう。

TypeScript2.0でexpressする

TypeScript javascript node.js express4

javascriptでサーバつくるときのフレームワークとしてデファクト(っぽい)expressをTypeScriptで始めたのでメモ

expressについて → express実践入門 · GitHub

入門は上の記事でどうにかなりそう

expressでtypescriptについて → TypeScriptでNode.jsのexpressを使ってHello worldしてみる - oinume journal

ただし、上の記事ではtsのバージョンが古い。

TypeScript2.0でexpressするには、 ///<refarence path=もにょもにょ> とかしない。

具体的には

npm install --save types@node

これでtsがnode.jsのライブラリの型定義とかを解釈してくれるらしい。

expressがnodeある前提だしたぶん必要。

npm install --save @types/express

これでexpressの型定義を解釈してくれる。

あとは tsc app.ts --module commonjs

--module commonjs はnode使ったtsのコードをコンパイルするのに必要

適当に日本語でggって調べた内容で上辺しか分かってないので間違ってる内容があったら指摘お願いします。

railsのrailに乗らずにjqueryだけでSPAしようとしたらクソ辛かった話

javascript ポエム 日記 プロジェクト jQuery ajax

かなり久しぶりの投稿です。死んでないです。

素直にreactとか使えば良かったものをjqueryで頑張ったら辛かった話をします。

しょぼいなwとか、こうはならないようにしようとか思って読んでくれれば幸いです。

前置き

ぼくの大学ではプロジェクトという3年生限定のゼミっぽい授業が存在していて、そこで一人暮らしの大学生が余り物をとうふドーナツに混ぜることで上手いこと消費出来るようにしようという話になりました。豆腐はヘルシーだし安いとかそんな理由です。

ぼくはwebアプリを作る担当チームに参加し、3人で冷蔵庫の中身を任意で友達とシェアし、上手いこと余りものをみんなで消費出来る仕組みを作成することになりました。

タイトルにもありますがruby on railsを利用して開発しました。

ぼくはそのチームで冷蔵庫中身共有ボードをSPA化する仕事と、github管理をする仕事を担当しました。

github管理も経験が浅くてなかなかに辛い物があったのですがここでは割愛します。

どうして素直にreactしなかったのか

1番の理由は難しいのでは..みたいなビビりがあったためです。

今年の春からプロジェクトはスタートしたのですが、その時点ではチュートリアルを片手間にちょっと触っただけで何か作れるレベルじゃないという認識でした。

あとメンバーでreactを少しでも触れた経験があるのがぼくしかいなくて、あまりメンテナブルじゃないなとかそういう理由もあります(結局jsでロジック書いたのは僕だけだったのでこれはあまり意味のない配慮でした)。

作ったところの機能

ぼくが作った共有ボードには以下の機能がありました。

  • 共有された食べものリストを、投稿された順/ユーザ名順/食品順 にソートする。
  • ふぁぼる。ふぁぼると一緒に消費するイベントリストに登録される
  • リプを飛ばす
  • 貰ったリプを表示する

画面としては以下のような雰囲気です。デザイナーのメンバーもいたので見栄えは結構良いんじゃないかなと思います。

f:id:syathi:20161226174646p:plain

これだけなのでその気になれば数日で出来るのではみたいな気持ちにはなるのですが、なんだかんだ夏くらいからダラダラやってたらかなり時間を使いました。

辛かったポイント

html.erbファイルが猛烈に読みにくくなった

全体的な機能の実装とか骨組みを作成するとかを担当していたメンバーはjsonを飛ばしてそのデータからフロントエンドであれやこれやするという設計をしていなかったため、サーバから送られてくるデータはhtmlの形式でした。

そのため、サーバから送られる変数はstyle="display:none;"とか属性をつけてhtmlに埋め込んでjsから利用しました。

ActiveRecordのモデルクラスのインスタンス変数とかはgonみたいなgemを使えば上手いこと出来るっぽいですがそういう変数でもなかったので仕方ないのかなという印象です。

もしかしたらぼくのググり力が足りないだけで全部いい感じに出来るのかも知れないです。

なんかちょっとメンバーのせいにしてるっぽいけど別に僕もrailsわかるので適当にコントローラ書き換えれば良かっただけの話で、横着が辛みに繋がった感じでした。

DOMの操作が結構わかりにくかった

テーブルのソートをするのにDOMの深いところをいじるのですが、その選択が分かりにくくてパッと見なにをいじってるのか分からない感じになりました。

for(var i = 0; i < tab1FoodsRow; i++){
  tab1FoodsArr[i] = [];
  for(var j = 0; j < no_column; j++){
    tab1FoodsArr[i][j] = $(".foods_article").eq(i).children().eq(j).html();
  }
}
for(var i = 0; i < tab1FreshRow; i++){
  tab1FreshArr[i] = [];
  for(var j = 0; j < no_column; j++){
    tab1FreshArr[i][j] = $(".fresh_article").eq(i).children().eq(j).html();
  }
}

こんな感じでめちゃややこしくDOMを指定してます。

(友達にはこれでも綺麗と言われました...jQueryって闇なんですね)

jQueryのノウハウがある人ならもうすこし綺麗に出来たのかもしれないですが、そうもいかなくてjQuery嫌いになりそうでした。

railsのrailをあまりよく分かってなかった

正直今もあまりよく分かってないのですが、jQuery使うにしてもjQuery-railsとかのgemがあるみたいで、そんなことも知らずに実装を始めて引けずに力技で実装をするのを続けてました。

あと、ajaxで非同期に通信するときにPOSTとかする用のrailsが発行するトークンをつけてなくてCSRFの例外を踏んだりとか、動的に変わるパスの為にたくさんhtmlに変数を書き込んだりとか、非同期通信周りでrailsをきちんとわかってあげられていなかったことに起因する問題を踏みまくりました。

このあたりは全体的にごり押しで実装出来なくはないのですが、なんか汚いなとか納得いかない感じのコードしか出来上がらなくて、一番モチベーションが上がらない作業でした。

<td class="heart">
  <% if @list = List.find_by(refrigerator_id: fridge.id, user_id: current_user.id, delete_flag: false) %>
    <div>[♥︎]</div>
    <div style="display:none;">1</div>
    <div style="display:none;"><%= fridge.id %></div>
    <div style="display:none;"><%= current_user.id %></div>
    <div style="display:none;"><%= lists_path(@list) %></div>
  <% elsif fridge.user != current_user %>
    <% if List.find_by(refrigerator_id: fridge.id, user_id: current_user.id, delete_flag: true) %>
      <% @list = List.find_by(refrigerator_id: fridge.id, user_id: current_user.id, delete_flag: true) %>
    <% end %>
    <div>[♡]</div>
    <div style="display:none;">0</div>
    <div style="display:none;"><%= fridge.id %></div>
    <div style="display:none;"><%= current_user.id %></div>
    <div style="display:none;"><%= lists_path(@list) %></div>
  <% else %>
    <%= "#{List.where(refrigerator_id: fridge.id).count}人" %>
    <div style="display:none;">2</div>
  <% end %>
</td>

こんな感じで変数をめちゃ埋め込んでます。

たぶんこういうのもgemを探して上手いことやるのがベターだったんだと思います。

CSSわからなくて思ったように画面に配置出来ない

タイトルと関係ないですがCSSが分かりにくくてここでも結構苦労しました。

結局デザインに当たる部分はデザイナーのメンバーに任せてしまったのでロジックにちょっと関わってるところとかだけ触れたのですが、それだけでも結構ハマってきつかったです。

まとめ

こんな感じでフレームワークの恩恵を得ることなくごり押しまくり、綺麗な実装が出来ないときのごり押し力が鍛えられた感じだったのですが、そういうのはかなりミニマムなフレームワークを使ってるときとか、根本的なプログラミング力を(プロコンとかで)鍛えている時とかそういう場面でやるべきことな気がしました。

せっかくフルスタックのフレームワークがあるのにその恩恵を受けようとしなかったり、もっと場面に適したツールがあるのに(この場面ではreactとか)利用せずごり押したりとか、ただただ自分に苦行を強いているだけで進捗も出ないし、モチベも上がらないし、メンバーにも迷惑をかけるしで良い事ないなというのが今回の開発での所感でした。

今後の開発では適材適所で最適なツールを適切に使っていくことを念頭に置いて行きたいです。

という反省でした。

プロジェクトそのものはみんな仲良くやれて楽しかったです。

ニフティインターン秋の発表会に行ってきた

概要

ニフティが主催する夏のインターン参加者限定のイベントに行ってきた。

内容は夏に作ったものをブラッシュアップしたり新しいものを作ったりして発表しあう!というもの。

今回は夏に3人で作ったのを1人都合があわずに離脱して2人で開発した。

ただ、あんまり自分で写真を取らなかったし、社員の方々が撮影した写真はいろんな人が移っててまずそうだからここでは殆ど文章だけで紹介するので悪しからず。

つくったもの

KoRecRayというデバイスと、それに付随するアプリケーションを作成した。

イデア自体は夏のインターンシップの時に出されたもので、途中まではインターンの間に作ったあった。

それの間に合わなかった部分や有り合わせで作ったデバイスをちゃんとした材料をあつめて作った。

例によって僕はソフトウェアとかサーバとかだけやってThingsの方は全然関わってないけど、そっちを担当したメンバーが本当にすごくて、ほぼ彼のおかげでうまいこといったと思う。

どういうデバイスを作ったかが何故か全然過去の記事でも語られてなかったので書いておくと、手で「これくらい」ってやった時のジェスチャーで長さを測れる指にはめられるデバイス作成がひとつ。そして長さのデータをandroidアプリで表示してデータベース保存と取得、通販のAPIを利用して大きさに合うものをサジェストしたりするアプリの二段構成でつくった。

下は相方がつくった外観。CADだと思う。すごい。それと作成中の写真、本体を手に乗っけた写真。超絶テクノロジーという感じ。

f:id:syathi:20161026020828p:plain

f:id:syathi:20161026020846j:plain

f:id:syathi:20161026020854j:plain

下は僕が担当したアプリの画面。機能は頑張った。画面は色んな人に助けてもらった。

過去に測定した物リスト。起動時にDBアクセスしてリスト表示。

f:id:syathi:20161026020945p:plain

測定画面。値はダミーの決めうち。保存ボタンを押すと測った物に名前をつけてDBに保存される。

f:id:syathi:20161026020950p:plain

APIを利用した検索結果。机 60みたいなワードで楽天とyahooで検索してる。

f:id:syathi:20161026020954p:plain

...まあアプリからして制作が間に合ってないのは分かると思う。一応検索してサジェストされた商品リストをタップすればブラウザが起動するようにはしてある。

つらかったこと

今回の開発は個人的に結構つらくて、最高に逃げ出したかったし何度も本番をばっくれようと思うレベルだった。

つらかったことはいくつかあるけど一番はスケジュールがギリギリで相当頑張らないとアプリが間に合わない状況だったこと。ぶっちゃけこれは甘く見てた自分が悪い。

僕個人androidアプリは作った事がなかったし、長いこと動的型付き言語ばかり触ってたのでJavaでやるって時点でなかなかしんどかった。

しかも途中まで相方が作ったのを引き継ぐ形になっていて、androidの画面がどういう設計で作られてるとかロジックがどうとか想像もついてなかったから、いちいちググってコピペして意味分からんエラーと格闘して、terateilに聞いて...の繰り返しだった。

わからないことが多いまま突貫で開発するのは本当につらいと思ったし、他のハッカソンとかインターンでこれ初めて使って作りましたみたいな事を行ってる人たち本当にすごいなと思った。寧ろ頭おかしいんじゃないかなとか思った。

あとこれもかなりつらかったのが、本番二日前の夕方に僕が操作してるリポジトリが古い方で、そっちだと予めつくってあったblue-toothのデータを受け取る機能が使えないことが発覚したこと。

この時点でもまだandroid全然わかってないのでそこまでで実装した部分を移行したりするので結局徹夜することになったし本当にばっくれようと思った。

f:id:syathi:20161024024537p:plain

それでなんとか移行して、足りてない部分修正して、仕様を満たせた!と思ったら前日の夜中に幅高さ奥行き測れるようにしてあるよね?と言われて、幅の測定しか実装してなかったのでこれはもう無理でしょってなりながら修正した。なんとかなった。

でも発表の準備が全然間に合ってなくて本番のプレゼンはデモは止まるし僕の思考も止まるしガタガタだった。相方に申し訳ない。

結果

ここまで言っておいて正直僕も本当にダメだと思ったけど辛くも技術賞を取ることが出来た。

相方が本当にすごい。すごすぎ。

対して僕へっぽこすぎ。反省。

賞品はミニドローンとのこと。2人分来るのかな...

まとめ

超絶突貫で死にそうになりながら足を引っ張りまくりながらもどうにかなって本当によかった。

あとandroid本当につらかった。今度やるときはもう少しチュートリアルとか段階を踏んでやりたい。それかxamarinとかreact-nativeとかそういうのでやりたいかも。そうすればクロスプラットフォーム出来るし。

そして相方に感謝感激雨霰。迷惑かけまくったしいつか愛想つかされそうだなとか思いながら開発してた。もっとがんばろう。

という感じで終わりよければ全て良しで、ただただ辛い思い出にならなくて本当によかった。今回も色んな刺激を受けられていい経験になって最高だった。

夏休みの始めにハッカソン行った話

ポエム IoT node.js ハッカソン javascript

結構長い期間何もブログ書いてないので生存報告的な意味合いで書きます。

備忘録の扱いで日記ではないので別にコンスタントに書かなくてもいいけど何もアウトプットしないのもまずいかなと思ったワケです。

行ったやつ

iot.tech-salon.com

テーマはお笑い×IoT とのことで、お笑いに関連するデバイスをチームで開発しました。

チームと言っても2人で開発を行いました。(本当は3人だったけど1人風邪で欠席しました。でも少しも責める気持ちはないです。本当です。)

つくったもの

のど元にセンサーをつけて笑ったかどうかを検知するセンサーデバイスを作りました。 ぼくはそのセンサーから送信されるデータを保存したり表示したりするweb側の部分を担当しました。相方はT担当だったのでのど元にセンサーを当てて爆笑していました。

システムの流れとしては、 curlでポストされたデータをnode.jsで受け取り、DBに保存、後からwebページにアクセスするとブラウザに笑ったグラフが表示されます。

ユーザは自分がどの芸人さんでどれくらい笑ったか、芸人さんはお客さんがどのくらい笑ったかを確認することが出来ます。

また、リアルタイムに折れ線グラフを描画するページもつくりました。 ここにアクセスすればどの場面でどれぐらい会場が湧いたか確認出来ます。

使った技術

  • node.js
    • とりあえず小さいwebシステムだしこれでいいかという気持ちで採用しました。この時はまだexpressを知らなかったのでhttpのレスポンスボディから必要なやつを自力で選び出して操作とかしています。
  • Nifty Cloud Mobile Backend
    • APIたたくだけで他のORM使うより楽そうだったので使いました。そろそろちゃんとnode.jsのORM憶えた方がいいような気がします。
  • socket.io
    • リアルタイムに通信するライブラリです。リアルタイムに会場が湧いてる度グラフを描画するために利用しました。
  • D3.js
    • グラフ描画するライブラリです。これでグラフを描いてます。

結果

現役のエンジニア達も参加しているなか学生二人で頑張りましたが、デモはデバイスが断線して失敗するし機能はDBアクセスしてポストしてブラウザに表示して。。。といった最小限しか実装出来ずどうにもならなかったです。圧倒的な生産性を得たい。あと面白いアイディアが思いつくようになりたい。

といった具合で賞になるものは得られなかったです。 でもハッカソンイベントは初参加だったし思い出にはなりました。 今後もこういうイベントは参加したいなと思いました。 欠席した鈴木には今度飯を奢らせます。

ニフティインターンでやったことに関するメモとか

node.js インターン express4 axios javascript npm クラウド バックエンド 日記

github.com

ぼくのコードはこのリポジトリのfeature/MYFEATUREというブランチの、Desktop/intern_backendというディレクトリ。(ブランチ壊したりしてよくわからない感じになった。)

インターン終わって一週間以上経っていい加減忘れそうなので知見的なモノを記録する。

やったこと

⬇️の画像の用なアーキテクチャでバックエンドにあたる所を主に担当した。 f:id:syathi:20160913015645p:plain

android端末(クライアント側)はチームの別の子が担当。

androi端末からAPIリクエストする機能は間に合わなかった。

クラウドサーバ設定について

この内容はインターン中にメモとして投稿したけど、クラウドの主にファイアウォール周りの設定をした。

具体的には、

  • 22番、80番ポートは特定のネットワークからのアクセスに限定
  • 3000番ポートは全部からアクセスを許可

全部アクセス許可する時の設定は0.0.0.0/0という風に記述しておく。 詳しいことは別記事にかいてあるのでそっち参照。

バイルバックエンドについて

ここだけサーバ経由してなくて、webとクロスプラットフォームとかしたいときサーバ経由するように直さなくちゃいけないしイケてないとか思ったけど、こういうアーキテクチャにしたのには理由があって、

  • expressからORMとか使ってmysqlとかにアクセスするのにはexpressで使うORMについての知識がなかった。
  • それを学習する時間も(5日間のインターンだし)なかった。
  • 突貫でスキーマ設定するには仕様が明確には決まってなかった。
  • もし仕様が変わったとして、スキーマ設定変えたりする時間も惜しかった。

という理由からとりあえず過去にも使ったことがあるしスキーマレスで楽だからNCMBを使った。

実際これにしたことで他のORMの使い方はわからなくて詰まるということも当然なかったし、最後の方であるカラムの型が変わることになったけどスキーマレスなので問題無く普通にあとから新しいデータ追加するだけで済んだ。

きっちり開発するならもうすこしこの辺はこだわった方がよさそうにも感じるけど突貫で作る分には問題ないと思った。

API叩くAPIサーバについて

メインで開発したのはここ。

やりたかったのは、送信された距離(家具とかの幅)のデータから商品をネット通販からサジェストする機能をつくること。

具体的には、リクエストが送られた時に楽天yahoo!APIをnode.jsのサーバが叩いて、二つのAPIから返ってきた異なるデータを同じ形式に直してレスポンスするというもの。

処理の流れとしては、

  1. リクエストにある家具の名前と長さとかで検索ワードを作る。
  2. レスポンス用の新しい空オブジェクトを作る。
  3. 非同期処理内でAPIを叩く。
  4. APIのレスポンスを空オブジェクトに追加する。
  5. JSON文字列に直してクライアントに返す。

といった流れ。

上の方にある画像のように、楽天JSONでデータを返してきて、yahoo!ショッピングXMLでデータを返してくる。(たぶんyahoo!JSONでも返すよう設定出来るけどなんかよくわからなかった)

また、それぞれのデータの内容も異なるので、商品名とか値段とかURLとか必要そうなものにだけ絞って新しいJSONオブジェクトに配列で追加して行った。

以下のコードがそのあたりの処理

var datas = {
          service:[],
          name: [],
          url: [],
          images: [],
          price: []
}
request(options, (error, response, body) => {
          if(error){
                  console.log(error)
          }else{
                  var parsedResult = JSON.parse(xml2json.toJson(body, opt))
                  parsedResult.ResultSet.Result.Hit.forEach( (hit) => {
                          datas.service.push("yahoo")
                          datas.name.push(hit.Name)
                          datas.url.push(hit.Url)
                          datas.images.push(hit.Image.Medium)
                          datas.price.push(hit.Price.$t)
                  })
          }
})

クライアントに返すJSONオブジェクトについて、そのときは何も考えずに一つのオブジェクトにそれぞれvalueが配列になっているkeyを設定し、クライアントはループ回すとかして全部にアクセスする見たいな形式にしてあるけど、

今思えばそれぞれの商品ごとに個々のオブジェクトに分かれてないの意味分からない。すごく使いにくそうな気がする。

こういう設計のところとかは明らかに経験不足というか、考えの浅さとかが露呈しててつらい。

もっと頭使えって話だけど、コツとかあったら教えてほしい。

実際にそのあたりが開発中に問題にならなかったのは、5日間の間でクライアントがリクエストを送るところまで実装するのに至らなかったから。

たぶんここでリクエスト機能が間に合ってて使いにくい!ってことになったらめちゃ焦ってたと思う。

もっと経験積もう。もっと頭使おう(反省)

ブランチ壊した話

インターンではgit flowを使うよ!と事前に言われていて、ブランチをしっかり分割して開発するよう指示されていたのだけど、ブランチを切って開発するという経験が自分にはなかった。(にもかかわらず碌にその辺を予習してなかった。)

インターン期間の夜中にQiitaの関連記事とか見てよくわからないながらブランチ作ったりした結果が上に貼ってあるリポジトリ。(自分のコードだけ新しくリポジトリつくってpushしようかと思ったけど戒めとしてあげておく。)

謎にDesktopからディクレクトリが分かれているのは別にDesktopをそのままpushしたわけではなくて、元々express_practice2という名前でpushしたものの、名前が適切じゃないから変えようと思って後からローカルで勝手にリネームしてpushしたらそうなった。というかそうなるらしい。

対策としてはgit mvか何かのコマンド(何かは忘れてしまった)で名前の部分を変更するとかすると上手くいくらしい。

ちゃんとした修正方法は別の記事で備忘録として書くと思う。

まとめ

ハッカソン形式で突貫開発すると一気にわからないことが出てきたり、発見することがあったりと忙しいのでこうやって忘れないうちにメモすることが必要。たぶんもう時間があいてるから書こうと思って書き忘れてることもあると思う。できればその日の晩に書けたら良いと思った。

あと反省は次に活かしたい。

感想的な記事はまた別で書くかもしれない。

redux-saga/effectsについてメモ

redux redux-saga axios 非同期処理 javascript フロントエンド

qiita.com

⬆️大体これを読めばわかるけど使用した関数や細かいメモを。

今回自分で使ったのはcall, fork, put, take, selectの五つ。

  • call: promiseの終了を待つ。引数にはpromiseを返す関数を入れる。
  • fork: 別のタスクの開始。 function*から始まる非同期関数を引数にとる。
  • put: actionをdispatchする。
  • take: action、イベントの発生を待つ。actionを待つけど引数に取るのはactionの関数ではなくてaction.typeとなる文字列。
  • select: stateからデータを取り出す。stateを引数にとる関数を引数にとる。

importするときは、

import { call, fork, put, take, select } from 'redux-saga/effects'

のように書く。

以下サンプルコード

//callサンプル
function* callSample(){
    const { result, err } = yield call(getData) //promiseを返す関数
    if(result){
        console.log(result)
    } else {
        console.error(err)
    }
}
/*axiosはpromiseパターンで非同期にhttp通信するライブラリ*/
const getData = () => {
    return axios.get('./get')
        .then( res => {
            const result = res
            return {result} //返して代入する変数名と合わせる
        })
        .catch( err => {
            return {err}
        })
}

callでpromiseを返す関数に引数を与える場合は、以下のような感じ

function* callSample2(){
    const data = {
      name: 'hoge',
      password:'huga'
    }
    const {responce, err} = yield call(postData(data))
}
const postData = (data) => {
    return axios('./post')
        .then( () => { /*処理*/ }
        .catch( () => { /*処理*/ }
}

forkはrootとなるタスクから分岐して処理を書いて行く感じ。

//forkサンプル
export default function* rootSaga(){
    yield fork(forkSample)
}
function* forkSample(){
   //処理
}

putは他の非同期処理の結果に応じてactionをdispatchしたりする時に使う。

//putサンプル
function* putSample(){
    const { result, err } = yield call(getData) 
    if(result){
        yield put(get(result)) //dispatchする
    } else {
        console.error(err)
    }
}

takeはほかの所からdispatchされたら実行される

//takeサンプル
function* takeSample(){
    while(true) {
        const action = yield take("ADD")//typeの文字列を引数にとる
    }
}
//selectサンプル
function* selectSample() {
        const state = yield select(getState)
    }
}

//stateを引数にとる関数
const getState = (state) => ( state )