情報系の凡才日記

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

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

まえがき

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

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

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

何を書くのか

特に今日リーン開発とは何か?といったレクチャーを事例を交えながら受けて、 じゃあエンジニアとしてどんな視点で何していかなきゃいけないんだっけ? ということを考えてみた。 より具体的には、 ユーザにとってより良いものであり、利益を継続的にあげていける素晴らしいプロダクトを作る環境を エンジニアの視点でどうやって作っていけばいいのか、という内容で記事を書いてみる。 結局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で。。。

「エンジニアとしての生き方」を読んで、働くことについて考える

最近、一週間ごとに一冊本を読むことを習慣にしてます。(´・ω・`)
今週は、中島聡さんの「エンジニアとしての生き方」という本を読んでみました。

Amazon.co.jp: エンジニアとしての生き方 IT技術者たちよ、世界へ出よう! (インプレス選書): 中島 聡: 本



NTT研究所、マイクロソフトを経て世界で活躍されている方だけあって、ものすごく率直で過激な意見の内容が印象的な本でした。日本は全然ダメ、国内に留まらず海外へ出て活躍していこう!みたいなことをとても推してましたね、、、
海外か、、、、、お外こわぃ、、、、、、、

それはさておき、ここでこの本の個人的に印象に残った部分を挙げて一度自分の中にある「働く」ことに対する考え方を整理しておこうと思います。


一番大切なのは「好きだから頑張れる」
(出典:中島聡(2011) 『エンジニアとしての生き方』 インプレスジャパン

 社会的地位だとか、学歴を活かしてとか給料とかそういうものでやりたくない仕事、楽しめない仕事をやるのはもったいない。自分のしたいことが会社の利益につながる、という意味でベクトルがマッチしていることが大事で、例えば残業させられる、ではなくそれが苦にならないような仕事につくべし。みたいな内容でした。

これ、今まで悩んでたことに大して直球な内容・・・・・・・・
自分は今、やりたいことに挑戦できる仕事か、安定してお給料もそこそこなお仕事かで結構迷ってました。
今自分が飛び込もうとしてるお仕事って、常に勉強したり努力重ねていかなければならないし、変化の大きい世界なので、のほほんと暮らしてたら間違いなく置いてかれるわけでして、、、、
今後その中で頑張っていくとしてモチベーション保ち続けられるのか、結果出せるのかっていうのが100%自信がない、、、、
あとせっかく良い大学入ったんだからもっと給与が高くて安定した仕事があるんじゃないかとか、、、(夢物語かも)


とまあこんなことを考えて色々悩んでたんだけど、なんだか迷いが晴れてきたのかなと思います。
この本読んで。というか元々心決まってたのかも、、、思えば最初から自分が何をしたいのか?っていうのを常に考えて就活してきてましたし、、、、
元々自分は「生きることを目的にして生きていたくない、それくらいなら死にたい」を常に心の中に掲げているので、たとえお金たくさんもらっても、安定してても、この先の人生で長く関わらなければならない仕事っていうものをつまらないと思って過ごしたくないと思ってて。
だから、単に大手の内定を目的にした就活の風潮とか、内定貰った企業の知名度とか規模とか、社会的地位とかで比較されるのもめっちゃ違和感覚えてました。
だからES何社も出して選考受けまくる、とかしないで実際に働いてる人の声とかを個人的に聞きに行ったりして、一つ一つの企業の仕事内容について理解深めた上で、働きたい企業を絞ったりしてきました。(働いてみないとわからないことのほうが多いと思うけど)
つまり結局は最初から自分の心は決まってたんですね。。。。。


結論!

自分のやりたいと思った仕事で、達成したいとおもった目標のためにがんばる!
で、だめだったらその時は思い切って死のう!笑


\( 'ω')/ウオアアア

【アルゴリズム+Ruby】Rubyで単体テスト 【test-unit】

備忘録。
イナリサーチRubyで実装しつつ単体テストを行ってみました。
使用したテストフレームワークはとりあえずtest-unitで。。。

テストケースは、

・通常の探索でヒットする場合
・通常の探索でヒットしない場合
・数字じゃないオブジェクトを与えた場合(例外テスト)

です。
とりあえずてきとーです。

require 'test/unit'

class Searcher

    def self.binary_search( x , left , right , array )

        while left <= right do
            mid = (left + right) / 2

            if array[mid] == x then
                return mid
            end

            if array[mid] < x then
                left = mid + 1
            else
                right = mid - 1
            end
        end

        return nil

    end

end

class SearchTest < Test::Unit::TestCase

    @@array = [1,2,3,4,5,6,6,8,9,10]
    
    def testHitSearch
        ans = Searcher.binary_search( 9 , 0 , @@array.length-1 , @@array)
        assert_equal(8,ans)
    end

    def testMissSearch
        ans = Searcher.binary_search( 34 , 0 ,@@array.length-1 , @@array)
        assert_equal(nil,ans)
    end

    def testillegalArgument
        begin
            Searcher.binary_search( "String" , 0 ,@@array.length-1 , @@array)
            flunk('Failed')
        rescue 
        end
    end
end

実行結果

Run options: 

# Running tests:

Finished tests in 0.004678s, 641.2997 tests/s, 427.5331 assertions/s.
3 tests, 2 assertions, 0 failures, 0 errors, 0 skips

ruby -v: ruby 2.0.0p247 (2013-06-27 revision 41674) [universal.x86_64-darwin13]


おー、、、、
、、、、、はい。
ちゃんとすべてのテストが通りました。

今回はクラス変数、クラスメソッド、Javaでいうtry-catchにあたるbegin構文なんかもついでにおぼえました(。・・。)
明日もがんばります。