情報系の凡才日記

エンジニアりんぐの試行錯誤とか参加したイベントとかについて書いていこうとおもいます。

脂肪を落とすためにパーソナルトレーニングに通いはじめたらいつの間にか筋肉に目覚めていた話

この記事は筋肉アドベントカレンダー2017の24日目の記事です。

概要

約2ヶ月パーソナルトレーニングに通ったので、得た内容を整理する。 以下のアジェンダで記事を書こうと思う。

想定読者

通い始めた動機

現状、自分には下記3点の悩みがあった

  • お腹周りの脂肪が辛い
  • 腰痛が辛い
  • 体力がなくて辛い。疲れが顔に出てしまう。

特にお腹周りには比類なき?コンプレックスがある。 お腹まわりの脂肪とは物心ついたときからずっと一緒に過ごしてきた。 これが自分がパンツ一枚で毎日体重計に乗るときに見る風景である。 山があり、そして三本の線がはいっている。 f:id:taisho6339:20140115131221j:plain

3年前、狂ったようにランニングをして2ヶ月で10kgほどダイエットした時も、 筋肉は全部落ちたのに腹回りの脂肪だけはずっとそばにいてくれた。 ここ最近この風景を見るのが辛くなってきた。

これらの悩みを解決するのはなんだろうかと考えた結果、 パーソナルトレーニングに通えばライザップのように劇的に変われるのではと思い、なんとなく通う決心をした。

どんなパーソナルトレーニングに通ったか

自分が通ったのは下記のような内容

  • 週二回 * 2ヶ月で126000のプラン(入会費3万円込)
  • 内容は姿勢の矯正、筋トレ、食事アドバイス
  • 糖質制限は一切なし

習ったこと

姿勢の矯正

立ったときの姿勢次第で腰への負担が変わってくる。 また、筋トレ時にもこの姿勢が悪いと怪我の原因になってくる。 そのため、下記のような内容を教わった。

  • 立ったとき、座ったときに骨盤の位置と肩甲骨の寄りをどこに設定するか。
  • そもそもどうやって骨盤を動かすのか、肩甲骨をコントロールするのか。

結果姿勢がよくなり、立っていても疲れにくくなった気がする。

正しい筋トレフォームの習得

筋トレにおいてフォームと呼吸は最重要項目である。 筋力的には最初から重い重量の負荷をかけることができる種目などもあると思うが、 軽い負荷でしっかりフォームを習得してからやることが大事だとか。 これらが正しく行われないと怪我のリスクになり、負荷も思ったようにかかってくれない。

トレーニングではよくあるBIG3(スクワット、ベンチプレス、デッドリフト)を教わって、 実際に動きを見てもらい都度フィードバックをもらって正しいフォームと呼吸を習得した。 また、筋トレ時にしっかり筋肉を可動させるためにどうやって筋肉をほぐすのかといったノウハウや、 自分で負荷を決めるときはどのように決めるべきなのか、セットメニューはどう組むかなども教わった。


【初心者】正しいデッドリフト講座【筋トレ】

個人的にここが一番パーソナルトレーナーがいることの価値だと感じた部分である。 一人で自分に適切な負荷で怪我のリスクなく実施するのは初心者にはハードルが高すぎる。

筋トレ後の身体の反応の見方

筋トレ翌日の自分の身体の反応をみることで前日のトレーニングを振り返ることができる。 ざっくりいうと下記のようなことを教わった。

  • 骨と関節の痛みがある => フォームが間違っている
  • 想定外の位置が筋肉痛になる => 想定外の筋肉に頼ってトレーニングしている
  • 筋肉痛がこない => 負荷が足りてない

などである。 これを得たことによって筋肉のPDCAを回せるようになった。

食事について

筋トレだけではお腹の脂肪を落とすには決め手に欠ける。 確実に落とすための施策として断続的ファスティングというものがある。 教わった内容でいうと、週一日だけ食事回数を5回にし、昼ごはん1回分以外はすべて液体食にする、というもの。 これによって消化器官を休め、インスリンが分泌されない時間を作って脂肪を燃焼させやすくするというものらしい。 実際に実践してみたが、平日にやると仕事のパフォーマンスがかなり落ちるので休日にやるのが良いと思う。 こちらは始めたばかりなので効果はまだ実感できていない。

結果的にどうなったか

はじめて約2ヶ月経ったが、 結果から言うとお腹周りは特に何も変わっていないように感じられる。 ただ、おっぱいは明らかに目に見えて大きくなった。

お腹の脂肪ではなくおっぱいの大きさに一喜一憂するようになった。

定量面でいうと、ギリギリ10回こなせる重量で、

  • ベンチプレス 20kg => 40kg
  • スクワット 20kg => 45kg
  • デッドリフト 20kg => 50kg

になったのでしっかり筋肉はついてきていると思う。 姿勢がよくなって腰痛もだいぶ緩和され、以前より疲れにくくなった。

また筋トレ、体づくり自体が楽しくなり、 副次的な効果として以下のような変化があった。

振り返り

2,3ヶ月で劇的に体型を変えるなら食事制限(糖質制限)つきのところでないと効果がでないと思った。(当たり前かもだけど) 自身でトレーニングして体を変えていくための知識の習得としてはありだが、 短期間で痩せたいなどの効果をだしたいならおすすめはできない。 だが、長い目でみてずっと健康でいたい、老けたくないなどと思うのであれば、 過度な食事制限つきのものではなく、しっかりゆっくり筋肉をつけて健康的な体型になっていったほうが良いのではとは思うので、 結果的には自分にはあっていたのかなと思う。

結論としては、目的をダイエットではなく筋トレに置くのであれば選択肢としては最適であり、 短期間で痩せたいなら糖質制限付きトレーニングを受けるのが良いと思う。

2017年12月版 Androidアプリの課金テスト手順

この記事はリクルートエンジニアアドベントカレンダー17日目の記事です。

目的

Androidアプリ課金について、ネットの情報も古く、網羅的な情報がないので整理する。

  • テスト課金の方法
  • テスト課金時にローカルでDebugする方法

課金のテストについて

ここでは、実際に決済させずに課金処理を確認するための手順を紹介する。

やらなくてはいけないこと

  1. Googleアカウントを作成
  2. 作成ユーザをテスター登録する
  3. α版 or β版アプリを公開する
  4. 実際にテストをする(要クレジットカード)

Googleアカウントを作成

普通に作成します。

作成ユーザをテスター登録する

作成したGoogleアカウントで決済無しのテスト課金を行うための設定を行う。

1.Google Play Developer Consoleにログインする。

2.テスト対象のアプリを選択する。

3.左側のメニューより、リリース管理 > アプリのリリースを選択 f:id:taisho6339:20171222000925p:plain

4.アルファ版 or ベータ版を管理を選択 f:id:taisho6339:20171222001111p:plain

5.リスト作成を押し、適当な名前のリストを作成し、テスターにしたいアドレスを入力(複数ある場合はCSVも可)し、保存 f:id:taisho6339:20171222001306p:plain

ここまででGoogle Play Developer Console 上の設定は完了。

6.PCまたはAndroid端末のブラウザで登録したアカウントでログインする。 ※他のアカウントでログインしている場合はログアウトしておく

7.上記手順で登録したアカウントでログインした状態で 下記のオプトインURLを開き、テスター登録を有効にする。 「これでテスターになりました」と表示されたらOKです。 f:id:taisho6339:20171222001605p:plain

以上にてアカウントの設定は完了。

α版、β版アプリを公開する

課金のテストを行うためには、GooglePlayストアにアルファ版もしくはベータ版公開する必要がある。 メニューのリリース管理からアルファ版 or ベータ版を管理と書かれたボタンを選択し、通常のアップロード手順と同様にapkをアップしリリースする。

注意点

  • targetSDKバージョンを上げてα、βにアップしてしまうと本番もあげないといけなくなるので注意。

公開範囲について

  • クローズドとオープンという公開方法がある。

    • クローズドは上記で作成したアカウントリストに公開する。
    • オープンは、実際にベータ版アプリが別途ストア公開される。だれでもテストに参加できる。
  • クローズドα、クローズドβの同時公開はできない。

    • クローズドα、オープンβのように公開範囲が異なる場合のみ、αとβの同時公開が可能。
  • 参考

実際にテストを行う

実際に公開したα、βのapkがストアで公開されたら、アプリをダウンロードし、各々アプリの課金の操作を行う。

注意点

  • 下記画像のように実際に課金しない旨がダイアログに出ないと実際に課金される。 f:id:taisho6339:20171222002301p:plain

  • テスト課金は返ってくるjsonレスポンスが本番と一部異なる。

    • 具体的にはorderIdという購入のトランザクションのIDが返ってこない。
    • アプリケーション側でorderIdをチェックするような実装になっていると決済処理はできてもAPIでこける。

実際のjson

{
    "autoRenewing": true,
    "developerPayload": "fa0iojf9032v.aknuf8923jaofewf-021h389vm",
    "packageName": "アプリパッケージ名",
    "productId": "test.1month.billing",
    "purchaseState": 0,
    "purchaseTime": 1471945711111,
    "purchaseToken": "mkildfilhdifncioicbofdgg.AO-J1Oy3t6iaEORwlA3MkhUPmc8b6Ypk-KSsDU9dRMDCbMBgNXJ5GnpKm2kPIA07QqlMlad2bzqdKOm5eYOVRPOmuSvjDQhgdbUFs7Em-idcp5IT6kAFtbtxbSuPJvkWoazmADn06yE6bpfgAVfdOnMm-ywc-R1HSg"
}
  • テスト課金は購入商品の有効期限が短縮される。

    • 1ヶ月 = 1日
    • 買い切り商品は変化無し。
  • 継続課金はユーザが明示的にストアでキャンセルしない限り永遠につづく。

ローカルでデバッグしたいケース

通常アルファ版やベータ版に上げるのはリリースビルドであること、ストアにあげないと課金処理が実行できないことからデバッグはできない。 しかし、実際に課金テストをしているとローカルでブレークポイントを貼ってデバッグしたい需要があるはず。 下記条件が揃っている場合にデバッグが可能となる。

  • ローカルでデバッグビルドで起動した時に、アルファ版 or ベータ版に上げたapkと使用している署名が一致している
  • デバッグビルド時にアルファ版、ベータ版に同じパッケージ名、versionName、versionCodeのapkが公開されている

つまり諸々の情報を同じにして、リリースビルド用の署名をデバッグでも用いるようにしてあげれば良い。

Androidデバッグ証明書にリリース用証明書を使う

今日リーン開発を知ったエンジニアが考える最強のプロダクト開発環境のつくりかた

まえがき

以前こんな記事を書いたが結局転職した。

入社してからずっと目をそらしてきたズレについて

そして転職して一週間たったので、 中途受入講義を受けたり、社内のいろんな方とお話させていただいて得た知識を自分の中で体系的にまとめてみる。

何を書くのか

特に今日リーン開発とは何か?といったレクチャーを事例を交えながら受けて、 じゃあエンジニアとしてどんな視点で何していかなきゃいけないんだっけ? ということを考えてみた。 より具体的には、 ユーザにとってより良いものであり、利益を継続的にあげていける素晴らしいプロダクトを作る環境を エンジニアの視点でどうやって作っていけばいいのか、という内容で記事を書いてみる。 結局DevOpsとかって目的じゃないよ!手段にすぎないよ!ちゃんと組織の方針みて改善してこうね! っていうお話。

良いプロダクトってそもそもなに??

  • ユーザに継続的に使ってもらえる => つまりユーザの課題を継続的に解決できている。(ユーザ目線)

  • 収益構造が成立していて、継続的に利益をあげていける(企業目線)

などなど...

そのためにどんなチームになれればいいのか

企画者、開発者一体で仮設検証を高速にまわしていける組織になること!

それって具体的にどういうこと?

以下の考え方に準じる。

  • すべてのビジネス企画は思い込みであり仮設である。
  • はじめから企画をフルで開発するのではなくその企画が本当に開発する価値のあるものなのかを実証したうえで開発する。これにより無駄を排除する。

  1. DAU増加を期待して、ある機能A(開発工数は1人月とする)を考える。 => (仮設)
  2. 最初から機能Aをフルで開発するのではなく、機能Aを呼び出すダミーボタンを用意し、10%のユーザに表示。(ボタンを押すと鋭意開発中!と表示する) => (検証)
  3. 一定期間様子をみて、10%のユーザがそのボタンをどれだけ押したのかを計測。実際に機能開発をするかを判断する。

これにより、検証の結果全然使われないような機能だとわかった場合、1人月分の工数を無駄にせずに済む。 こうして、仮説をたてて、検証をして、学びを得て次に活かすというサイクルを高速に回していける組織を目指す。

詳しくは、このスライドを参照すると良い。 リーンスタートアップ概論

どんな環境を作っていけばいいのか

じゃあどうやってそんな組織作っていくんだ? というところだが、これには2つの観点からアプローチしていく必要が有り、 下記図のように組織的な観点と開発環境的観点があると思っている。 f:id:taisho6339:20160517230217j:plain

以下で具体的に説明していく。

組織環境

チームとしてどういう状態にしていくかを考える。

  • 目指すべき姿の理解。これは企画サイド、開発者サイド両方でともに、仮説検証サイクルを回して事業を運営していく組織にしていくことの合意がとれている状態。

  • 仮設の実証プロセスの定着。 そもそも顧客は?その顧客設定でOKなの?顧客ってどんな課題抱えてんの?その課題ってなにやったら解決すんの? その施策の効果が出てるってどうやって判定すんの?競合優位性ってどこだっけ?どうやって儲けるの?

といったような各項目について、しっかり検討し、実証していく。(一度実証して終わりではなく、状況はかわっていくものなので都度更新していく必要がある) これについては便利なツールとしてリーンキャンバスという考え方があるらしい。 具体的にどうやって実証してくんだよ(マジギレ)って方は、上のスライドを見てみてほしい。 正直実務でやった経験が乏しいので私もわからない。

開発環境

開発環境としてどういう状態を目指していくかを考える。 これについては以下2種類に大別できると考えられる。

仮説検証を回していくために必要

  • ログ収集基盤
  • 各データの可視化。CVRやPVなど。
  • データを見るための指標。各施策に対してデータをどう見ていくかの指標定義。
  • A/Bテストやライブテスト、フューチャートグルを実行できるような環境
  • ユーザをクラスタリングするための仕組み。 => ある特徴を持つユーザをグループ化してそのグループに対してだけ特定の施策を出してみるとかを行うため。

とかとか。

高速に品質を担保して開発していくために必要

  • CI/CD
  • 自動化テスト
  • 自動デプロイ
  • 静的解析
  • 品質指標

  • インフラのコード化 + インフラCI

  • 仮想化
  • バグや課題管理の仕組み
  • ChatOps

などなど。。。

サービスの成長曲線と開発に必要なことの優先順位

まず前提として、サービスには成長のフェーズというものがある。 立ち上げ期、成長期、安定期といったような。 そして当然ながらそれぞれのフェーズにおいて、必要なものは変わってくる。 優先順としては次のように考えている。

  1. 組織環境
  2. 仮説検証のための開発基盤
  3. 高速で品質を担保していきながら開発する基盤

サービス立ち上げ期においては、まず組織としての目指すべき姿とマインドを共有していくことが大事。 これさえ共有できてれば、検証などは極端な話人力で計測してしまっても良い。 DropBoxのように、先にこんなもの作るよーとユーザに訴求して、プロダクトがないのに先に登録だけさせ、 登録ユーザ数をみてから開発し始めるといったアプローチも有効であるため、必ずしも開発環境として便利な仮説検証基盤が整っている必要もない。

成長期に入ってくると、仮説検証をより高速に、頻繁に回す必要がでてくるため、 開発側で便利な環境を整えてやるのがよい。 そして、随時高速に品質を担保しながら開発していくための仕組みを整えていく。

当然だが、必ずこの順番で順々にすすめていく、という話ではない。 CI/CD、テストコードなどは簡単なものでも早い段階で可能なら入れておくべきだと思う。 その辺は各サービスによるんだと思う。

結論

立ち上げにがちがちにCI環境など開発環境を整えても要求スピードを担保できない。 逆に成熟しきったサービスにマインドから導入するのはかなりの苦労が必要。 DevOps的な整備とかも普段の開発も組織ゴールに根ざしている必要があり、なんとなくイケてないから、という理由で改善していくものではない。 よってサービスのフェーズに合わせて必要なもの、優先するものを選択、改善していくことが重要。 DevOps、普段の開発も目的ではなく手段。 CI推進とか単体だけでみるのではなく組織の目指す姿という大局的な視点で見て、 本当に今必要なのかどうか見極めながら改善していくことが重要。

感想

今まではエンジニアとして開発環境を整備しようとか開発プロセス改善しようにも何からすべきか、 どう説得すればいいのかというのがまったくイメージできず、 常にエンジニアだけの視点で自己満足なことしかいえなかったが、 こうして体系的にまとめてみることでひとつの判断指標を得ることができた。 経験が全然伴っていないのでこれが正しいとはまったく思わないが、 ある程度この考えに根ざして組織貢献できたらいいなと思う。

入社してからずっと目をそらしてきたズレについて

※最初に断っておくと職場やそこの人への愚痴などでは一切ありません。 客観的な職場の現状と自分のキャリアの希望のズレに言及した記事になります。

本記事について

現在大手Webサービス会社に新卒入社して7ヶ月経った。 だが、入社初期からずっともやもやしていて目をそらしてきたものがあるのでここで一旦言語化して整理したい。

記事の概要

ざっくり言えば、 「入社一年目はインプットが大量に必要だと思っているが自分が求めるインプットではなかった。自分の今後のスキルアップを考えたら今の環境にいるべきではない気がするが、今の環境で結果を出せていない事実もあるのでどうするのがベストか決めあぐねている」といった内容の記事を書く。

自分が職業エンジニアとしてやりたかったこと

自分は情報技術が好きである。 何かしらの大きな課題を前にしてそれを技術で解決することに憧れている。だから入社前はデータ分析職を希望した。よくわかっていないながら、データを分析して課題と解決方法を考えて、数学的、技術的に解決することに魅力を感じていたからだ。

だがその希望は通らずにサービス開発をするエンジニアとして配属された。サービス開発については前々からやってみたいと思っていた分野ではあったし、多くのユーザに実際に使われているプロダクトなのでより実践的な課題を解決できると前向きに捉えていた。 今後は、「サービス開発する上で立ちはだかるどんな技術的障害をも解決できるすごいエンジニア」になりたいと考えるようになった。よって企業としてアプリやWebサービスの開発に取り組むことで具体的に以下の技能を身につけることができることを期待した。

自分が期待していたサービス開発で学べること

  • 大勢のユーザからアクセスされた時にでも耐えられるインフラ設計ノウハウ
  • 安定したシステム運用のために必要なセキュリティ対策、監視運用
  • 質の高いアプリ、システムをリリースする上でどのように品質を担保するのか。どのように試験するのか。
  • チーム開発に最適化された効率のよい開発プロセス
  • 大勢のユーザから使用されるアプリを作るにはどのようにニーズを分析するのか。またその結果をどう活かすのか。
  • 保守性が高く、堅牢なソフトウェアを設計、実装するためのノウハウ
  • 他に自分が知らない知識

だが現実はそうではなかった。

期待と現実のギャップ

  • どうあるべきなのが正しくて、どういうテストケースを実行するのかなど確立されたテストプロセスは存在しない。「とりあえず動かしてみてなんとなく良さそうだからOK。」自動化テストなども存在しない。

  • ほぼウォーターフォール。降ってきた案件を単純に消化するだけ。

  • ログデータ分析の基盤が整っておらず、施策をうつにしても効果の試算や結果のレビューなどが存在しない。企画職が考えてこちらが実装するだけなので、「どんな効果を予想した施策で、その結果どうなるのか」が見えない。これでは開発プロセスを改善していくことが難しい。

  • 堅牢で保守性の高いソフトウェアとか夢。実態は、「謎の5000行のUtilクラス」、「意味もないネストの深い継承」、「5000行にも渡る何をやっているのか分からない共通クラス」。OOPデザインパターンを理解している人自体が少ない。

  • とりあえずなんとなく動くものをなんとなくリリースしているように見える部分がちらほら。

  • アクセス捌けなくなってきたらとりあえずサーバ台数追加で解決してきた。(もう少し分析などしっかり行ったうえで対策を打つべきだと思っている)

  • セキュリティは外部専門部署から指摘されたことをこなすだけ。こちら主体で考えて対策したりといったことはあまりない。 監視はしているが、どんな監視項目を設定するかなどの議論はなく前任者が設定した項目を完全に意味を把握することなくそのまま引き継いでいるものが多い。

まとめると技術力のある他社が実際に当たり前にできていること、考えていることがほとんどできていない。 エンジニアリングでの課題解決より受動的な開発が多い。

現実を前にした今の自分の気持ち

課題は自分で解決して変えていけよ、という話なのかもしれない。 でも インプットなくしてアウトプットが出るだろうか。 なんでも経験した範囲で取り組めるわけはないというのは理解できるが、 これらの課題を解決できるノウハウを持った「できるエンジニア」が近くに存在しないことは、 入社一年目でいろんなものを吸収する必要のある自分とマッチしているのか、というのは甚だ疑問である。

もちろん学ぶものがまったくないわけではなくて、チームとのコミュニケーションの取り方や、開発をすすめる上でのスケジュールや工数の考え方、外部との調整の仕方など多くのものを学ばせてもらった。だが、それらは技術力ありきで必要なものだと思っている。技術力なくしてそれらだけあっても、それは「エンジニア」ではないというのが自分の考えだ。自分は「エンジニア」になりたい。 「エンジニア」になりたいのに仕事を通してまず「技術」を吸収できないのがすごくもどかしい。

はっきり言えば転職をしたい。 だがほとんど今のチームで成果をだせていない自分が転職できるのか、するべきなのかというのも疑問である。。。 いち早く成果を出して転職をするのがベストなのだろうか・・・ 焦りだけが積もっていく。

追記(11/18)

思った以上にいろんな方に読んでいただけて驚いた。 厳しいコメントもいくつかいただけて嬉しい。 このような記事の書き方だと自分がなにもせず待っているかのように感じられる方も多いと思うが、 記載したような課題を自ら解決するべく動いているし、自主的な技術勉強を怠ってはいない。(足りているとは言いがたいけれど) いままでは「何も整備されていないということは一から自分で作って学んでいける」と思って取り組んできた。 実際それによって良くなりかかっている課題もある。

だが正解を知らない、指針が見えない課題が多すぎて、思うように進捗と成果が出せていないのは事実だし、 勉強会などで積極的に活動している”うまくいっているほう”の若手エンジニアの話を聞くとどうも焦りを感じてしまう。 情熱プログラマーにも書いてあったが、「自分が一番の下手くそであれ」というのは確かな正義だと自分は思っている。 レベルの高い環境が自分のスキルアップ促進に影響するのは間違いないし、同じ姿勢でも環境によって成長速度が変わってくると思う。

端的に言えば、能力値の低い自分では0から学んで自分で解決していくのはなかなか難しいので、 良い環境で周りの技術を盗んでスキルの底上げをしたい。 ということなのだと思う。

「知識ゼロから学ぶソフトウェアテスト」を読んで

「知識ゼロから学ぶソフトウェアテスト」を読んだので、まとめ兼書評的なものを書いてみる。

この本を読んだ目的

いま自分が所属する開発チームには以下のような課題がある。

  • 手動テストはあるが、そのテスト項目の決め方にガイドラインのようなものがない。(何をテストするのかが決める個人の裁量によって決まっている)

  • 手動テストなので人によってテストの質が違う。

  • 自動化テストなどがまったくない。

  • APIに至っては、レスポンスの目視チェックとクライアント側を開発するときに作りながらチェック。

このような状況なので、僕のようなプロダクトの仕様を把握しきっていない新人にとってはバグを生み出しやすく、またテストも不十分な状態でリリースされてしまう問題がある。

まずは、自分がテストによってどうやって品質を担保するのかをちゃんと知ろうと思い以下ブログを参考に読んだ。

新卒ソフトウェアエンジニアのための技術書100冊

内容について

前半

前半は、ホワイトボックステストブラックボックステスト、同値分析、境界値分析、ディシジョンテーブルなど既知の内容だったので特に学びにはならなかった。 また、独自に「探索的テスト」なるものを提唱していたが、 テストスキルの高い人が、プロダクトを触りながらテストを行うというもので、そのスキルの高い人がいない現状なのであまり興味を惹かれなかった。

後半 -非機能要求テスト-

まず非機能要求で担保するべきなのは、

  • パフォーマンス
  • 機密性
  • 信頼性

の3つだそうだ。

パフォーマンスのテスト

パフォーマンステストで見つかるバグは最悪(最悪設計のし直しが発生する)なため、なるべく最初の方にやることを推奨される。

このテストを行う上で重要なのは、まずはパフォーマンスの定義を明確にすることで、例えば「1分以内に20MBのデータを処理できる」など。ただし、「1分で20MB処理できるけど、30秒だと1MBしか処理できない」といったケースも考えられるので、様々な状態やケースでテストするべきであるとのこと。

また、パフォーマンステストは以下の手順で行うと良いらしい。

1 設計が間違っていないかの確認

データベーステストなどの場合、DBとデータが用意できた時点でそこにアクセスするプロトタイプを作り、処理能力が要求に合致しているかをテスト。

2 パフォーマンスベンチマーク

実際に開発されたソフトウェアがパフォーマンステストできる状態になったら即要求に照らし合わせてテスト。

3 パフォーマンス回帰テスト

開発していて、変更などがあった段階で、変更によってパフォーマンス低下が発生しないようにすぐテストする。

4 最終確認

5 本番のデータなどになるべく近い環境でテスト

機密性のテスト

セキュリティのテストのこと。 攻撃手法はどんどん増えていくのでいたちごっこ。 ツールとか使うといいかもね、というお話。

信頼性のテスト

信頼性とは、「ある条件下で安定して要求された機能を果たす能力」らしい。その指標としてMTBFというものが使われる。 これは、平均故障時間と呼ばれるものらしく、どのくらいの時間ソフトウェアを使用するとバグやハングアップ、リブートなどが発生するかの平均時間。

Web系の会社でこういうのちゃんと測ってリリースしてるところってあるのだろうか・・・

今後自分がどうしていくか

テストの質がばらついているのと、何をテストするの?というのが曖昧なので、まずはテストのガイドラインなんかを作ってチームに浸透させるのが当面な目標なのかな・・・

ガイドラインについて

ガイドラインとしては以下の内容がちゃんと伝わればいいのだろうか。。。

  • なんでテストしなくちゃいけないのか
  • 何をテストしなくちゃいけないのか
    • 機能テスト
      • 正常ケース
      • 異常ケース、例外
    • 非機能テスト
      • セキュリティ
      • パフォーマンス
      • 信頼性

導入に関する懸念点

  • ガイドラインを明確にしたうえで、どうやってチームに定着させていくか。
  • あまり複雑にしすぎると、障壁が高い。
  • 決めるのはいいが、全部一気にやらせるより一部分だけやらせていくのはどうか。

余談

ブログ書いてる途中で結構面倒くさくなった。

入社後5ヶ月を過ごしてみて

入社後5ヶ月を過ごしてみて

本記事の目的

今の会社に新卒入社してから5ヶ月経ったので、現在抱えてる思いや課題意識を整理するために日記のようの書き綴ってみる。(社外秘が多いので具体的には書けません。。。)

今までやってきたこと

新卒研修(4月)

技術研修などではなく、ビジネスマナーやコンプライアンスや企画研修。内容が暑苦しかったり、やたらコミュニケーション取らせようとしたり、人が苦手な自分には若干うざい研修だったが、ディスカッションの進め方やアイデアの出し方など勉強にはなる部分は多かった。

データの配信スクリプトのリニューアル

アプリや、Webページのコンテンツに使用する元データをサーバに配信する仕組みをレガシーなものからリニューアルした。シェルスクリプトなんかを駆使して書いてた。

スマホ版Webページのリニューアル

スマホ版のWebページのデザインリニューアルにともなって、フロントのPHP部分の対応を行ってた。 ガイドラインなんかが多く、最初仕上げた時はそこに全然マッチしたものになっていなくて何度もやり直した。

Androidアプリの機能追加、改修

Android版アプリの機能追加や、細かなバグ修正を行ってた。 レガシーな部分やセキュリティ的にやばそうな部分が多くフラストレーションを溜めながら頑張ってた。

大規模な機能追加(バックエンド、アプリ両方)

大規模な機能追加にともなって、APIの開発とAndroid版アプリの開発に携わった。 APIは新規に開発するものだったので、「オブジェクト指向のこころ」などで勉強したデザインパターンをふんだんに応用してみた。 オブジェクトを「継承」ではなく「移譲」することによってカプセル化する という思想をベースに設計した結果、かなり拡張性や見通しの良いコードになった。 その思想、設計をその機能の開発チーム全体に適用できたのも幸いだった。

また、アプリ側はそのままではとても機能が追加できる状態ではなかったので、機能追加に関わる部分をすべてリファクタリングした。 (大体3週間位工数かかった) TabをActivityで切り替えるような古い設計から、Fragmentに置き換えたり、重い処理を非同期処理にしたり、一つのActivityに3つの画面の管理が書かれていたりしたので分離したりした。 DBの更新が行われたらActivityに通知を行ったりしたかったので自前でObserverパターンを適用してみたりもしたが、ここはRxJavaなどを使ってみてもよかったのかもしれない。。。(ここくらいしかちゃんと理由づけして導入するチャンスはなかったかも)

自分の評価ポイント

  • 新規API開発時に、開発を仕切ってる先輩に設計思想を説明して全体のルールとして適応できたのは良かった。
  • 何かをチーム全体に適応したいとき、人を選んでその人から説得するのは大事だとおもった。

自分の課題ポイント

  • 開発スピードは早かったが、品質の担保がまったくできていなかった。仕上げて突っ込まれたり、あとから問題になるケースが多かった。

  • 人に何かの判断を仰ぐとき、自分はきくだけで自ら提案をすることが少なかった。次からはある程度自分で仮説や提案を作ってから聞きに行きたい。

  • チームの人すべてが、先進的で向上心のあるエンジニアなわけではない。 だから、プロダクトを良いものにするために他社が普通にやっているようなことも(自動化テストや、より良い設計で開発してもらうことなど)、どう説得すればやってもらえるのかをしっかり考えて動かなくてはならない。

まとめ

チームで開発している以上、自分が技術力をつけるだけじゃだめで、コミュニケーション能力を駆使してチームを動かすことが大事なのだということを痛感した。 そしてここでいう「コミュニケーション能力」とは、

  • チームを動かすための説得力、交渉力
  • 簡潔に物事を伝えられる説明力

のことで、これらを技術力と並行して磨いていきたい。

【Android】MenuTabのFragmentの遷移を自前のスタックで管理する

はじめに

概要

仕事の開発の方でタブメニューを使っていて壁にぶつかったので備忘録として残しておきます。
トピックとしては、「Tabメニューの一つのタブで、Fragmentの遷移をさせた時の管理」でぶつかった課題とその解決策について記します。

具体的なエラー

Tabに紐付いたFragmentから、別のFragmentに遷移させ、BackStackに前の状態を積んだ時に、特定ケースで何故かアプリが落ちるといった問題に悩まされました。

成果物

問題解決の成果物としてTabのFragment遷移管理を簡単にするためのモジュールを作ったので公開しておきます。
(お粗末ですが。。。)
使い方はREADMEを見てくれれば。。。
https://github.com/taisho6339/tab_fragment_operation

問題にぶつかったケース

たとえばこういう設計のタブメニューの画面を作ります。

f:id:taisho6339:20140701214608p:plain

つまり、


・一つのActivityにタブのコンテンツとしてFragmentをぶら下げる。
・さらにそのFragmentから何らかのタイミングで別のFragmentに遷移させる。
・遷移は、Fragmentから一旦Activityにコールバックして、Activityで管理する。

といった仕組み。

ぶつかった問題

  1. まずFragmentA-1が開いている状態で、FragmentA-2を呼び出す。
  2. 親のActivity側で、コンテナをFragmentA-2にreplaceする。
  3. 呼び出す前の状態を保存するためにaddToBackStackを呼ぶ。
  4. タブを切り替える。
  5. 再び元のタブに戻る(この時点でFragmentA-2に帰る)
  6. バックキーを押して、FragmentA-2を呼び出す前の状態に戻す。
  7. 落ちる。

エラーログは、

java.lang.IllegalStateException: Fragment already added

こんな感じのが・・・

問題の考察

フレームワーク側のTabを管理するコードを読んでみるとわかりますが、

https://code.google.com/p/android/issues/attachmentText?id=40035&aid=400350000000&name=FragmentTabHost.java&token=WHVg3x7dbNNznLcPPSwWxnin_X0%3A1367343846708

タブを切り替えた時に、タブに紐づけてあるFragmentのインスタンスがnullだと新しく生成し、スタックにaddするという制御を行っています。
つまり、

  1. 親のActivity側で、コンテナをFragmentA-2にreplaceした時点でFragmentA-1のインスタンスが消える。
  2. タブを切り替えてからまた元のタブに戻る
  3. 消えていたFragmentA-1のインスタンスを再度生成
  4. FragmentA-2をattach
  5. バックキーを押すと、FragmentA-2を呼びだす前の状態にロールバックするために、FragmentA-1を再生成しスタックに積もうとする
  6. が、すでに3で蘇らせているのでバッティング(同じバックスタックに同じFragmentのインスタンスは積めない)

という問題っぽい。

解決策

バックキーによるロールバック時、タブの切り替え時にインスタンスを自動で復旧させてることで、バッティングしてしまっているので、

FragmentManagerのBackStackではなく自前でスタックを用意して管理する

ことで回避できるのではないかと考えました。
つまり、それぞれのタブに対してスタックを紐付けておいて、タブそれぞれでFragmentの遷移を管理しようってお話しです。

というわけで汎用的なモジュールを実装してみました。
https://github.com/taisho6339/tab_fragment_operation

仕様

・FragmentからFragmentに遷移した時に、バックキーで元の状態に戻れるようにする。
・タブのルートまで言った時にさらにバックキーを押すとActivityを終了させる。

ようはこれを満たせばいいわけです。

実現方法

・TabInfoというデータクラスを作り、Fragmentを積むスタックを持たせる。
・格タブにTabInfoをタグとしてくっつけておく。(これでTabInfoがタブから取得できる)
・FragmentからFragmentに遷移するときは、このTabInfoの持つスタックに積む(現在表示されているFragmentが一番上にくる)
・バックキーを押したら、スタックをポップして、その時の一番上のFragmentをコンテナに差し込む
・タブ切り替えは切り替え先のタブのスタックの一番上のFragmentをアタッチ

こんな感じ。

Tabを使うActivityで、

  @Override
    public void onBackPressed() {
        if (backControl())
            return;
        try {
            super.onBackPressed();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }

    private boolean backControl() {

        TabInfo tabInfo = (TabInfo) getCurrentTab().getTag();
        Stack<Fragment> stack = tabInfo.getBackStack();
        if (!stack.isEmpty()) {
            stack.pop();
            if (stack.isEmpty()) {
                finish();
                return true;
            }
            Fragment newFragment = stack.peek();
            mManager.beginTransaction().replace(mFragmentContentId, newFragment).commit();
            return true;
        }
        return false;
    }


また、ActionBarのTabを使ったので、TabListenerの実装クラスに、


 @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
        Stack<Fragment> stack = ((TabInfo) tab.getTag()).getBackStack();
        Fragment fragment = null;
        if (stack.isEmpty()) {
            fragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(mContentId, fragment);
            stack.add(fragment);
        } else {
            fragment = stack.peek();
            ft.attach(fragment);
        }
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
        Stack<Fragment> stack = ((TabInfo) tab.getTag()).getBackStack();
        if (!stack.isEmpty()) {
            Fragment fragment = stack.peek();
            ft.detach(fragment);
        }
    }

詳しくはgithubで。。。