利用中のトレーニング・健康器具
長期間の不健康な生活に耐えるためのトレーニング・健康器具のまとめ。
利用中の物
懸垂マシン
- 腕立てより短い時間で強い負荷をかけれる。
- 自分の体を持ち上げるのは楽しくモチベーションが上がる。
- 横の棒の持つところは手のひらが痛いのでこのグリップテープを巻いて使っている。
- 懸垂で回数をこなしたい場合はこのトレーニンググローブを利用している。
フィットネスバイク
- 台があるのでノートPCを置いて動画を見ながら使える。
- 脈拍計が付いているので目標の脈拍(150回/分など)になるように運動を調整できる。
- 靴を履かずに靴下で使うのでペダルにこのグリップテープを巻いて使っている。
- 欠点としては重いし場所を取る。負荷調整はできるが最大負荷でも自分には少し弱い。
ダンベル
- 以前は金属のダンベルを使っていたが運動中に何かにぶつけるのが怖かったのでこちらに変更。
- 重さの調整ができる。
ハンドグリップ
- 負荷調整ができる。
- プラスチックなので軽くてじゃまにならない。
ランニングシューズ
- クッション性の高く深夜ランニングで少し走るときに丁度いい。
ストレッチローラー
- 背中のストレッチにいい。
マッサージクッション
- 背中の下に置いて体重をかけてもガッツリ動いてくれる。
フットマッサージャー
利用を止めた物
ハンドマッサージャー
- 音がうるさい。
- 手のひらの自分が力を入れてほしい場所に力を入れてくれない。
足首ウェイト
- 付け外しが手間。
- PCで動画を見ながら使おうと思ったが、買ってからよく考えたら動画を見ながら足を動かすのに適した運動がない。人類は愚か。
リングフィットアドベンチャー
- 運動とゲームのリンクが非常にうまくできているが、ゲーム性や運動の内容が万人向けにでちょっと合わない。ゲームとして面白くないし、敵を倒すためにはしたくない運動も選ぶ必要がある。
- ながらでできない。有酸素運動がしたいときは考え事をしながらできるようなフィットネスバイクかランニングを選んでしまう。
AWS Summit Tokyo 2016 3日目に行ってきた
Lambda! Kinesis! Lambda! Kinesis! ... DynamoDB! Aurora!という感じだった。
非常に勉強になった発表が下記。
秒間数万のログをいい感じにするアーキテクチャ クックパッド
https://speakerdeck.com/kanny/miao-jian-shu-mo-falseroguwoiigan-zinisuruakitekutiya
感想
ログ管理は「ログはfluentdで流すようにしてS3に保存する。ElasticSearch/BigQueryにも流して解析に利用する」まではまあ簡単で、もう少し改善できないか悩んでいた私にはちょうどいい発表。
やっぱりKinesis Stream。pull型のpubsub分散キューは素晴らしい。
実験的なアプリをconsumerとして気軽につなげるという発想はなかったが、新しいことを考えてすぐに試せるのが楽しそう。
Kinesisのshardは運用イメージがつかみにくいので、注意点も参考になる。
ログの集約ノードが結構新しい構成まで残っていたことが意外。スライドにある通りいろいろ問題あるし冗長化とかも相当手間。
GREE流! AWSをお得に使う方法
コストとmemcachedの整合性の問題から、memcached + mysqlからDynamoDB(一部のみmamcachedを利用)に移行したという話。
- BatchWriteItemしてもwriteされたitem数で料金計算されるのでコスト面からは減らない
- atomic counterとかconditional saveが整合性を保つのに便利
- DynamoDBはコストが見えやすいのでコスト意識が湧く
- writeは整合性のあるreadより10倍高い
- indexもwriteの増加に影響するので無駄につけないように
- deleteをせずに新規にtableを作る方がいい場合もある
- randomな取得はindex付きのrandom idを作ってrange&limitでクエリすればいい
- capacityを超えても5分のburstはあるけど確実にthrottringを防いでくれるものではないし当然設計ではそうならないように考慮する必要がある
- aws sdkを使っていればretryはしてくれる
- partition
- partitionがsplitされたらcapacityも分割される。その時にリクエストが片方のpartitionに偏るとcapacityを超えてしまう
- partition keyはuser idなど分散されるものを使う
- とは言っても難しいものはあり、mamcachedを一部利用しているものもある
- partitionのcapacityを計算したり管理するのは大変なので、スケーリングにはAmazon DynamoDBというツールを利用している
- scale upでpartitionが作られるが、scale downしてもpartitionは減られないことに注意
aurora
- auroraはwriteのパフォーマンスが高い
- slaveへの切り替え時に数秒処理できなくなるので注意
インフラの作業をlambdaで改善
- ちょっとした作業にはmanagedサービスを使うとすごく安く済む
- EBSスクリーンショット取得とかインスタンスの定期監視とかをcloud watch eventから呼び出したlambdaを使って行った
- lambdaは公式には起動に失敗する可能性があるのでログをチェックする仕組みを入れる必要がある。ただ、実際に運用で起動に失敗したことはなかった
- 実行時間は5分までなので、必要ならば処理を分けること
- lambdaをhttp/httpsから呼び出す場合はAWS gateway apiを使う必要があるがこのコストをかけたくない場合、クライアントからhttp/httpsを使わにという手がある
- lambdaは呼ばだしリクエスト量とその時間単位での課金なので、lambdaでの非同期処理を使うことでコストを下げることができる
他
- 開発に利用するes2インスタンスは夜中とか休日は止める
[phoenix][elixir] Phoenixのログ周りの調査
リクエスト受付時のログ(コントローラーレイヤー)
- PhoenixでのPlugの定義(https://github.com/phoenixframework/phoenix/blob/master/lib/phoenix/controller/logger.ex)
- Plugでは.callの第2引数がlevelになっている
- PhoenixでのPlugの設定場所(https://github.com/phoenixframework/phoenix/blob/master/lib/phoenix/controller.ex#L126)
- __using__のoptsをそのままPhoenix.Controller.Loggerに渡している
- サーバアプリでレベルをdebugではなくinfoにしたい場合
- Phoenix.Controllerのusingに引数で設定する(https://github.com/ndruger/hello_phoenix/commit/276537e8386e9b2a0e27009fa449644bd59f3e2b)
リクエスト受付時・レスポンス時のログ
- Plug.Loggerの定義(https://github.com/phoenixframework/phoenix/blob/4b8b92da6f7692b0b2ed0e31c0511cd92d18afaf/lib/phoenix/controller/logger.ex)
- .callでリクエスト受付時のログを出力している
- Conn.register_before_send()にてレスポンス時のログ出力をコールバックで設定している
- request_idはPlug.RequestId(https://github.com/elixir-lang/plug/blob/master/lib/plug/request_id.ex)にてLogger.metadata()で設定。なるほど。これでどの場所のログでもrequest_idが付くわけだ。
- config.exsにて"config :logger"の"metadata: [:request_id]が指定されているので有効になる( https://github.com/phoenixframework/phoenix/blob/4b8b92da6f7692b0b2ed0e31c0511cd92d18afaf/installer/templates/new/config/config.exs#L24 )
- デフォルトだとdev環境ではformatが指定されておりrequest_idが付かなくなっている(https://github.com/phoenixframework/phoenix/blob/4b8b92da6f7692b0b2ed0e31c0511cd92d18afaf/installer/templates/new/config/dev.exs#L28)ので、dev環境でもrequest_idを出したい場合はdev.exsを修正する。
- PhoenixでのPlug.Loggerの設定場所(https://github.com/phoenixframework/phoenix/blob/4b8b92da6f7692b0b2ed0e31c0511cd92d18afaf/installer/templates/new/lib/application_name/endpoint.ex)
- ログだけあってPlugの中でも大分前の方に設定されている
サーバアプリでcontrollerのアクション後にログを出したい場合
- 最初"plug action"を指定してその後にPlugの設定を記述してみたが、これは古い方法で、少なくともPhoenix0.14.0では間違っている(https://github.com/ndruger/hello_phoenix/commit/c6d289c411fabafcc97d1c58afae8349348e5a64)
- Phoenix 0.14.0 だと"[deprecated] plug :action is no longer required in controllers, please remove it from HelloPhoenix.BooksController"の警告が出る。最新masterだとその警告が消えてる(https://github.com/phoenixframework/phoenix/commit/e6b792be398db71f4ffcddb94f66fde01bc62f3e)が、このPRのコメント( https://github.com/phoenixframework/phoenix/issues/888#issuecomment-127768123 )のコメントによるとPlug.Conn.register_before_send/2 を使うの正しい模様。
- register_after_actionが一時追加されたが消されている(https://github.com/phoenixframework/phoenix/commit/d85f59cc42157fffeb0b041a07ceed591ac0df30)
- Phoenix 0.14.0 だと"[deprecated] plug :action is no longer required in controllers, please remove it from HelloPhoenix.BooksController"の警告が出る。最新masterだとその警告が消えてる(https://github.com/phoenixframework/phoenix/commit/e6b792be398db71f4ffcddb94f66fde01bc62f3e)が、このPRのコメント( https://github.com/phoenixframework/phoenix/issues/888#issuecomment-127768123 )のコメントによるとPlug.Conn.register_before_send/2 を使うの正しい模様。
- register_before_sendで修正してみた( https://github.com/ndruger/hello_phoenix/commit/7b48d973415885141addf249b0f6584a68359d32 )
- コードの見た目がひどすぎる。Plugとタイミングを独立させて、Plug使う側が明示的にタイミングを指定したい場合もあると思うので、Plugをregister_before_sendに登録するマクロを作ってそれを利用するのが綺麗な形なのだろうか?
サーバアプリでuser_idの出力をmetadataを追加したい場合
- 下記のようにログイン時にput_sessionして、plugでget_sessionしてLogger.metadata()に設定して、default.conf.exsでloggerのmetadataにも入れればいい
scala祭り2014(9/6)をニコニコ動画で見た
起きたらほとんど終わってた・・・ので主に録画。
下記は、発表者がいっていることではなく私の感想。
A会場
Play Frameworkについて(仮)
- test
- 両方10になっているけど・・・。
- 非同期テストは一部Nodeの方が弱いって感じがする。延々と非同期処理を呼ぶ場合はq.jsなどでPromise化すれば奇麗にかけるけど、条件文が正解になる or タイムアウトになるまでチェックするようなことをしたい場合、scalatestだとeventuallyで簡単だけど、JS or coffeeだと気軽に書けない。
国技と Scala
- デザイナーがviewに直接手をいれる
- gitを使ってcloneして来て、branchを作って、ローカルで手を入れて修正&動作確認して、pull requestするの?そうだったら凄すぎる。デザイナー兼フロントエンジニアだね。
- Non-Stop Deployment
- LB、Nginxでの切り替えはどの言語でアプリサーバを書こうが定番。けど、RDBだとどうせマイグレーションで止まる。まあ、止めない方法もあるけど(追加されたデータ構造を1つのuserdata的なcolumに入れる邪悪な方法。MySQLでReplicationを利用して動作させながらマイグレーションする方法もあるけど未体験)
- それより、切り替えの途中は複数のバージョンのアプリサーバにリクエストが行く問題と、ブラウザを含む古いクライアントからの古いフォーマットのリクエストを新しいアプリサーバがどう処理するのかの問題に関して、Scalaを利用した場合の、Rails, Nodeでの実装より優れた点などがあるか知りたかった。jsonリクエストフォーマットをScalaで定義しておけば、型変換として変換を漏れなくできるのかな?
Webサービスの自動テストをどう行うか?
RailsやNode.jsを利用したWebサービスの自動テストをどのように行うかの現状の調査分まとめ。
随時更新。
Webサービスのテスト対象
- [クライアントアプリ]
- サーバアプリ
- サーバサイド実装部分(RailsやNode.jsを使って実装)
- Model
- 最近だとtower.jsなどにように、クライアントのModelと共通の場合がある
- View
- 最近だとtower.jsなどのように、サーバではほとんどviewがない場合がある
- Controller
- Model
- クライアントアプリで動くJavaScript部分
- Model
- 比較的テストがしやすい
- View/Controller
- テストが結構手間。UIのテストは基本的に面倒。
- Model
- サーバサイド実装部分(RailsやNode.jsを使って実装)
- サーバのデプロイツール
- capystranoのスクリプト
- サーバのインフラ構築ツール
- chefレシピ
テストの粒度とテスト手法
- サーバ内、クライアント内で閉じるテスト
- サーバとクライアントが連携する結合テスト
- 機能テスト
型チェックの弱い言語でのWebサービス開発において、なぜ自動テストが重要なのか?
Webサービスのリリース(ソフトウェア更新)の周期は短い
現在のソフトウェア・Webサービスでは、ユーザーのフィードバックを受けて機能追加・修正を行い、どれだけはやく次のリリースを行うのかが重要視されています。
パッケージアプリのリリース周期の短縮に関しては、Google PlayやiTuensに代表されるソフトウェアのアプリストアの登場により、ソフトウェア開発者がアプリの更新・配布を簡単にできるようになったことが要因の一つです。
そして、Saasとして利用されるようなWebサービスは、パッケージアプリのような配布の手間がないことに加えて、全ユーザーが同じ最新版を利用する形になるため複数バージョンのサポートのコストがないこともリリースが短くなる要因の一つです(Webサービスのリリースに関してはサービスの稼働率との関係もありますが・・・)。
このようなリリース周期が短い状況においては、リリース前テストという形で工数のかかる手動テストを行うと、リリース感覚が短いために開発工数の中でテスト工数が非常に大きな割合を占めることになります。
そのため、テスト実施に作業工数のかからない自動テストを充実させる必要があります。
もちろん、リリース前テストをすべて自動化できるかというと難しい点も多く、自動化できる部分とできない部分を見極める必要があります。
インタプリタ方式の型チェックの弱い言語の問題など
C/C++/C#/Java/Haskellでソフトウェアを開発する場合、強い型チェックの存在により、コンパイル時に存在しないメソッドの呼び出しなどはエラーとなるため、プログラムを動作させなくても多くのバグを見つけることができます。
これなら大規模リファクタリングも安心して実施できますね。
例) NekoクラスがmethodAメソッドを持たない場合コンパイルエラー
Neko neko = new Neko();
neko.methodA()
更に、JavaScriptに関しては実行時でさえ、オブジェクトのプロパティのアクセス時にそのプロパティが定義されてない場合も例外は発生せず、単にundefinedが返ります。
例) Nekoクラスがプロパティnameを持たない場合、bはundefinedになる(正確にはJavaScriptに言語上クラスはなくNekoは単なるコンストラクタでありスコープチェーンが・・・という話はここではしない)
var neko = new Neko(); var name = neko.name; // 1. ここでエラーにならない。bはundefined $('#test').text('height', name); // 1. ここでもエラーにならない。undefinedが'undefined'という文字
このような状況だと、バグはなかなか発見されなくなり、バグ発見時にも原因解明に多くの時間を費やすことになります。
バグの基本原則として、バグの原因となる修正・実装をした時からバグの発見までの時間が、長くなるほど修正コストが上がるので非常に残念な状態といえます。
自動テストを充実させてCIと統合し、個々の機能が正しく動くことを継続的に確認すると、デグレ等を早期発見することでことでバグに対するコストを大幅に削減することができます。
この問題に限定すると、下記のような改善・対策は可能です。
ただし、JavaScriptは言語的に他にも多くの落とし穴があり、jsHintなどを利用して問題の発生頻度を下げたとしても、自動テストでの品質確保はは必須といえるでしょう。
1. C++言語で利用するようなASSERT()関数を定義して、コード上の前提条件などのチェックを増やして、予期せぬundefinedを見つけやすくする
ASSERT()は失敗したら開発時にすぐに分かるようにします。また、自動テスト中にASSERT()が失敗したら、結果は失敗になるようにします。
例) 必須となる引数がない場合、ASSERT()を失敗させる
function Neko(params) { ASSERT(params && params.name); // params.nameを利用する処理 }
2. プロパティの取得・保存をメソッドでラッピングする
個人的にはMVCフレームワークのModelは基本的にこのくらいのチェックはしてほしい。堅固なModel最高。
例) getメソッドによるアクセサを作る
var neko = new Neko(); var name = neko.get('name'); // getメソッド内でthisにnameプロパティがない場合ASSERT()を失敗させる
3. プロパティの取得をECMAScript6 Proxyを使ってラッピングする
方向性は上記のメソッドのラッピングと同じですが、メソッド呼び出しではなくプロパティアクセスの形でチェックを実行できます。
4. TypeScriptを利用する
TypeScriptはJavaScriptへのコンパイル時に強い型チェックの実行がされるので、存在しないプロパティはコンパイル時にエラーになります。
機能の増加とモジュール化
各サービスのWebAPI、JQueryのPlugin、Node.jsのパッケージ、Rails利用時のGemなど、現在のソフトウェア開発は膨大に存在する個々のモジュールを組み合わせることで、非常に安価に機能の追加ができる時代になっています。
そのため、1つのWebサービスが持つ機能も非常に多くなっています。
また、社内・社外で利用する機能を、パッケージしたライブラリ(以下モジュール)にしたりWebAPIにして提供するということも頻繁に行われるようになりました。
つまり、下記の問題を解決する必要があります。
- 1. Webサービスが持つ膨大な機能をどうやってテストするのか?
- 2. 提供したいモジュールの品質をどうやって保つのか?
1に対しては、結合テストの自動テストで対応します。
このとき、Webサービスが持つすべての機能を網羅的に結合テストで行おうとすると、自動テストの非常に時間がかかったり、比較的コーディングコストの高い結合テストコードを大量に作って作業工数に問題が出ます。
そのため、テストの粒度のどこで品質を確保するのかは見定める必要があります。
2に対しては、LightWeight言語のモジュールといえばPerlのCPANだった時代から、パッケージ化されたライブラリには単体テストをつける相場が決まっています。
もし単体テストがなければ、そんなモジュールなんて怖くて使ってもらえませんし、問題発生時のサポートが大変です。
スマートフォンのブラウザでのアニメーションに関するツールのメモ
生成するhtmlコードに関する部分が中心。
まだ修正・追記をする予定。Adobe Edgeを追加予定。
- [2011/12/31 コメントで指摘をいただいたExGameの間違いを修正]
Swiffy v3.6
Flash(swf)をhtml5を使ったコンテンツに変換できるGoogleのwebサービス。ActionScript2まで対応。
Google Lab廃止から生き残ったし、アップデートもされているので、Googleも力を入れている模様。
生成するhtmlコード
- Flashの変換結果として大量のjsonデータが出力され、それがランタイム(runtime.js)によって実行される。
- Flashのアニメーションのオブジェクトの移動は、SVGのtransform属性のmatrixに変換している。相当重くiPhone4ではシンプルなコンテンツでないと厳しい。
- ベクタ画像はSVGに変換される
- javascriptの処理をFlashのaction scriptから呼び出したい場合、変換前のFlashでgetURL("javascript:void(alert('neko'))")などとする。下記のサイトを参考。
- hi-posi ≫ Blog Archive ≫ Swiffyを調べてみた。
- 画像はdataスキームに変更される。ゲームなどで画像を動的に入れ替えたい場合、名前などで適当に検索して見つけて入れ替えるスクリプトを追加する。
- SVGなのでAndroid2.xでは動かない。
Wallaby Technical Preview
Flash(fla)をhtml5を使ったコンテンツに変換できるAdobeのアプリケーション。
Swiffyとは異なりActionScriptには対応していない。
生成するhtmlコード
- シンプルなコード。javascriptで個々のアニメーションを記述せず、CSS Animation/CSS Transitionで書かれたアニメーションを、クラス変更で開始させる。
- 変形はwebkit-transformのmatrix(), scale()を利用。
- Swiffyと同じく、ベクタ画像はSVGに変換される
- jqueryが使われている。当然animate()関数ではなくセレクタの機能などの部分。
- webkitAnimationEndを契機に次の処理へと進めている。
- Swiffyのjsonの塊より生成されたコードがわかりやすいので、特定要素のクリックでのページ移動などのインタラクションを生成コードに追加するのはできそう。ただし、アニメーション動作の変更に介入するのはさすがに難しい。
Reel, ExGame
ReelはグリーのFlash(swf)のjavascriptランタイム。
ExGameはDeNAのFlash(swf)のjavascriptランタイム。
Sencha Animator1.0
CSS Transistion/CSS Animationを利用したアニメーション作成ツール。Adobe Flash Professionalに近い位置づけ。
ユーザーインタラクションも対応している。
アニメーションと簡単なインタラクティブクコンテンツの作成に利用できるが、スクリプトからの操作するIFがほとんどない現状ではゲーム作成などは難しい。
生成するhtmlコード
- シンプルなコード。Wallabyと同じで、javascriptで個々のアニメーションを記述せず、CSS Animation/CSS Transitionで書かれたアニメーションを、クラス変更で開始させる。
- 高速化のため、2Dの移動・変改でもtranslate3d(), scale3d()を利用している。
- 円などはdivでborder-radiusを指定している。
- 画像のプリロードの機能はないが、assets()フォルダの画像を一覧にして読み込むjsをビルドプロセスで追加するのは可能なので致命的にはならない。
- imgはdivで2回囲んでいる。1回はCSSの適応プロパティの他のオブジェクトと合わせるためと思うけど、2回でくるむ理由はなんだろう。
- 連続する動作をCSS Transitionで分けずにCSS Animationにしている。transitionEndで一瞬時に止まるのを気にしていると推測。timerでCSS Transitionを加えると微妙なタイミングに合成されちゃうし。
- 動かない状況もtimerで待たずに、css animationのtranslate()で同じ位置を記述している。
- アニメーションしながらのサイズ変更には2種類指定できる。
- How to resize an image [アーカイブ] - Sencha Forum
- resize
- width/heigthをCSS Animationで変更する。子孫は変更されない(イメージはimgをdivでラップしているので変更されない)
- scale()より遅いwidth/heightの変更を使うのは、下記のscale() + translate()のAndroidバグを避けるため?
- Issue 12451 - android - Using css transitions in webkit clears scale() transforms on non-animated objects for the duration of the transition - Android - An Open Handset Alliance Project - Google Project Hosting
- scale
- 結構"クラス名. *"みたいな比較的重いセレクタを利用している。まあ要素が少ないからいいか。
- ループ動作はシーンのリスタートで実現。-webkit-animation-iteration-countでしてないためか、わずかに引っかかる感じがする。
- Animation Loop [アーカイブ] - Sencha Forum