叫ぶうさぎの悪ふざけ

うさぎが目印のWebエンジニアが、得たことや思ったことを言の葉に乗せて叫ぶ場所です。

学習記録:12月18日(火):はじめよう!要件定義 Chapter-06 [準備編]企画を確認する(つづき)

これは 俺のインプットアウトプット記録 Advent Calendar 2018 の18日目のエントリーです。

ちなみにこのエントリー、最後に盛大なポエムというか、なんというかな話が入ります。そんな話はいらんわ、って場合は飛ばしてもらえればなあと思うんですが、本題よりそっちの方をエントリーにした方がよかったんじゃないかな…と思わなくもないので、もし何か思うところがありましたらば、忌憚のないご意見をいただけたらいいなあと思います。

閑話休題

本日は約4時間の研修を受けてきて、情報が溢れ気味でございます。が、間違いなく今後の仕事の仕方を変える内容でしたし、いかに僕らが 当たり前を具現化する仕事をしている のか、そしてそれを しょっちゅう忘れて頻繁に事故を起こす のかを思い知らされました。

研修内容をそのまま公開するわけにはいかないので研修レポートは書きません(手元にはしっかり残す)が、はじめよう!要件定義、を読み進めるにあたり、研修で学んだことなどは取り入れつつアウトプットにしたいと思います。

というわけで、前回の 学習記録:12月17日(月):はじめよう!要件定義 Chapter-05 要件定義、その前に & Chapter-06 [準備編]企画を確認する に引き続き要件定義の学習を進めます。

Chapter-06 [準備編]企画を確認する

昨日はこの章の途中までで終わっていました。企画書でゴール、つまり実現したいものを確認し、実現したいものからの逆算で「UI、機能、データ」を合意して進めていくわけですが、そのゴールが曖昧だとダメで、じゃあまとめるためにどんな項目があるのか、ということで以下の項目があればいいよ、まで進みました。

  1. プロジェクトの名称
  2. なぜこのプロジェクトをやるのか
    • 目的
  3. 何を
    • 目的達成のために作るもの
    • 作るものの説明
    • 作るものを利用する人
    • 利用する人が得られる便益
  4. どのように
    • 作るための体制
    • 期限

企画の内容を関係者が理解するための企画書

重要なのは企画を通すための企画書ではなく

  • 通った企画がいったいどのようなものなのか、を
  • 企画を実現するために作業する関係者、が
  • 理解するために必要な企画書

である、とあります。当たり前すぎてぐうの音も出ないんですけど、今まで多数の 企画を通すための企画書 を見てきましたし、そういう企画書ほど、 企画をするための企画書 だったりしたなあと思い返したりしました。

そもそも出発点は何かしらの情熱であり、それを実現するために前に進むための企画であり、その内容を共有するための企画書である。

だから、意思決定に対する「企画提案書」ではなく、実施が決まった企画の「決定報告書=プロジェクトそのものの仕様」が必要とあります。

つまり企画書を通す前の お願いします!の企画書 と 企画書を通した後にやる決定報告としての これをやります!の企画書=プロジェクト仕様書 が必要と理解しました。

RFPやプロジェクト計画書との違い

RFP支援の仕事もしたことがあるので、大変興味深い章です。要望を形にして、実現可能性や技術検討ができるようにするもの、くらいのふわっとした認識でした。

企画書が、RFP、いわゆる提案依頼書や、プロジェクト計画書と何が違うのか。

プロジェクト計画書から、マネジメント向けの情報を除外したサマリー

それが欲しいとあります。

  • 除外したいもの
    • 予算、リスクなど実務スタッフの担当領域外の情報
  • 不安や反発をなくす
    • プロジェクト仕様を知らないまま指示通りに作業しろ、と言われても…
    • 知らないことは先手を打つこともできない。プロなのに。
    • 何より人間は腑に落ちないことに不安や反発を覚え、手が止まりがち
    • 作業そのものが停滞しちゃうよね、と

企画書とは何か

プロジェクトについての紹介を、5分で手際よく事前知識のない人にできますか という問いかけが出てきます。

実務担当に不要な情報や、不安や反発を招きそうな内容だと、これから目指すゴールを紹介するのは難しいよな、と思います。

今から自分たちはこういうゴールを目指していくのだ と大雑把に理解できるために、 紹介するための企画書を作成 する。

そしてそれを共有する。 これが最初の材料 となる。

サンプル①:施設予約システム

サンプルとして、以下のプロジェクト仕様が掲載されています。僕なりに少し情報を足してみます。

サンプルには別紙参照の別紙がありませんが(そりゃそうだ)、それも含めてプロジェクト仕様書だと認識しました。で、そのプロジェクト仕様書を関係者で共有することで、自分たちが向かうゴールとその理由がわかる、ということかなと理解しました。

  • プロジェクトの名称
    • 施設予約システム
  • なぜ
    • 目的
      • インターネットを通じ、利用者が手軽に施設予約できるようにすることで、施設の稼働を活性化する
  • 何を
    • 目的達成のために作るもの
      • インターネットからの施設予約
      • 予約状況の確認
      • 実績データの他のシステムとの連携
    • 作るものの説明
      • 別紙参照(各機能の必要性とかUIとかかな)
    • 作るものを利用する人
      • 一般利用者
      • 窓口担当者
      • マネージャ
      • 経費部門
      • システム管理者
        • アカウント管理にシステム管理者を常に含めるのは重要
    • 利用する人が得られる便益
      • 別紙参照(フローや図があったりして別資料なのかな)
  • どのように
    • 作るための体制
      • 別紙参照(体制図が決まってないからかな)
    • 期限
      • 今年度中に完成
      • 新年度から運用開始

書籍にはもう1つサンプルがあったのですが、そちらは割愛します。ゲームを作るとなった場合にどうなるか、が書かれていました。

コラム:企画の良し悪し

企画もなしにいきなりソフトウェアは作れないよね、要件定義できないよね、狙いや企てのない取り組みはあり得ないよね、とあります。

まさにその通りで、企画の原点には情熱や思いから発する狙いや企てがあると僕も思います。

それは、趣味のプログラミング(他の趣味にも当てはまりそう)ですら、狙いや企てはある、と。そして、企画には良し悪しがある。

企画の良し悪しはどこに起因する?

利用者便益(ベネフィット)の観点から精査されているかどうか。

と述べられています。

成果と評価は違うとあります。

  • 成果はアウトプットであり、作り手が生み出す
    • 目玉焼きそのものは成果、しかし評価じゃない
  • 評価は受け入れる側が生み出す
    • 成果を受け入れ側がインプットし、そこから生まれる
    • 美味しい、いまいち、など
  • 評価の後は効果
    • 美味しければ嬉しくなったり幸せな気持ちになる
    • いまいちなら残念な気持ちになったり怒ったりする

この違いを認識せず、成果ばかりに目がいってしまい、評価や効果に対する狙いがあやふやなのが、筋の悪い企画であると述べられています。

効果の想定が曖昧

使い勝手のいいアプリを作る、という例で進んでいきます。

  • 使い勝手がいい、と評価するのはユーザーであり作り手ではない
  • ユーザーが評価した結果、どんな効果を狙うのか、が意外と曖昧
    • たぶん、職人文化を色濃くもつ日本人にすごくありがち
    • So What?(で?だからなに?) と問われたら回答できない

あるよなあそういうこと、って思いながら読んでました。

ストーリーを描けることが重要

  • 成果=例えば完成した「在庫管理システム」
  • 利用者が「仕事がしやすくなった!」という評価の先に…
  • 在庫回転率が向上するという効果が生じる
  • というストーリーが描けるものが良い企画

しかし実際にはストーリーに飛躍や断絶があって、実際の要件定義をする段になると、プロジェクトの目的に対して辻褄が合わない、矛盾した要件になってしまうよね、とあります。

重要なのは個別の正確性より全体の一貫性

個々に優れていても、例えば洗濯物を片付けたい、と言われ、いかに高性能かつ最先端の洗濯機を激推ししたとしても、おそらく以下の「洗濯」というプロセスに置いて、洗濯機は一部の、つまり個別の正確性の1つでしかないんじゃないかな、って考えました。

  • 洗濯物が発生するタイミング
    • 毎日、毎時、人、など多数かつランダム
  • 洗うと判断するタイミング
    • 定量に達したら?
    • 旅行などのイベントに関連する?
  • 洗うという行為
    • 洗濯物別に区分け
    • ネットに入れる
    • 順番を考えて実行する
  • 洗濯開始までの導線
    • カゴに放り込まれている
    • 仕分けする
    • ネットで包む
    • 洗濯機に入れる
  • 洗濯機を操作する
    • 洗剤を入れる
    • 柔軟剤をポケットに入れる
    • 水の量を設定する
    • 時間を設定する
    • 乾燥が必要か判断する
    • 乾燥のON・OFF
    • 洗濯実行する
  • 洗濯機が回る
  • 洗濯が完了する
  • 洗濯機から取り出す
  • 干す
    • ハンガーに通す
    • 洗濯バサミで止める
    • 洗濯棒にかける
    • 乾燥にかける
    • 陰干しにする
  • 乾いたか確認する
  • 乾いていれば取り込む
    • 定められた位置へ積む
    • 分ける必要があれば分ける
  • たたむ
    • しまう場所別にたたむ
    • 利用する人別にたたむ
    • 簡単なものからたたむ
  • しまう
    • タンスにしまう
    • クローゼットにしまう
    • 脱衣所にしまう
    • あるべき利用位置に設置する

思うこと

まさにその通りだなってのは前回にも思いを綴った記憶があるんですけど、仕事のための仕事を作る人っているよな、とも思いました。誰かのために、つまり利用者に便益をもたらすことから発進しているはずなのに、そこがすっぽり抜け落ちている。

利用者に便益をもたらす観点から考えずに、 企画を立ち上げなくてはならないからターゲットと市場を考えて、無理に企画を考案する なんてことあるよな、と。

得てしてそういう企画は利益にも結びつかず、便益をもたらす利用者の数も非常に限定的かもしれないなって思いました。

とはいえ、世の中の不便なことをちゃんと調べないと、企画も出てこない、ということも言えると思います。ゆえに、思いつきを徹底的に精査する、矛盾や無理のない内容であるかを突き詰める。

そうして初めて、企画としての実現可能性が見えてくるんだろうなって思いました。

やってみたいこと&やったこと

洗濯する、をちょっと考えても、これだけのプロセスとタスクと手順があり、しかもそれが天気や家族の健康状態、学校、イベント、ともすると気分にも左右され、かつ大物(布団カバーとか)があるか否かで分岐も変化するよなってことに気づきました。

また、今までずっと考えていて行動に移せなかった おとーさんとして1日を回すために経験すべきこと をどう認識するか。それって要件定義と同じ考えで形にできないかな、と考えたりしました。

で、24時から1時間ほど奥さんとずっと話してたんですけど、

  • 「家事育児、俺ができるようになるために経験したい、見える化したい」
  • (この間、色々やりとりあり、奥さんは辛抱強く僕の主張を聞いてくれている。眠いのに)
  • 「で、何がしたいねん。母親の代わりをしたいのか、手伝いたいのかわからないよ」
  • ( ゚д゚)ハッ!
  • (自分に問いかけたのち)「俺にできる1日の回し方を体験したい」
  • 「つまり、おとーさんとして1日を回したいってことね」

ってことを話してました。かなり要約すると。このあいだの1時間、奥さんはすごい忍耐力と言語力で僕に接してくれたと思います。

我が家は僕が外貨を稼ぎ、奥さんが専業主婦です。当然役割も意識も求められるものも違う。

僕は外貨を稼ぐためにタスクを見える化し、確実にこなして成果に繋げ、評価してもらう。その結果として対価をいただく。

では奥さんは?

常に変動する要素に対し、分単位、ときに秒単位で判断し、行動している。毎日命がけで。その行動の元となる情報は天気だったり子供の健康状態だったり控えている学校行事だったりするし、ご飯をどのくらい食べたかで次のやることにも影響してくる。

これらを、家の中にあるあらゆる要素、あらゆる外的要因、あらゆる子供の状態をインプットとして無限の分岐から判断を下して行動する。

僕とは根本的にやってることが違うわけです。

で、その認識が僕にはない。なぜならそこまで全部判断するような一気通貫の1日を回しているわけではなかったから。

でも、知りたい。なぜか。できるようになりたい。なぜか。奥さんが1日家を空けても回るようにしたい。なぜか。奥さんが入院したら回らないから?それだけじゃない。俺にできることを増やしたい。なぜか。奥さんが大変そうな、辛そうなことを減らしたい。減るのか。減らない。それに意味はあるのか。意味はあると思う。経験を積むために協力してもらうことはできないか。それは可能といえば可能。

こんな問答に付き合ってくれて、以下のことがわかりました。

  • 1日のゴールは娘が時間内にご飯を食べ、明日のために19時台に寝ること
  • ゴールに到達するためには、日によって選択肢が全く違うこと
  • 正解は何もないこと
  • おかーさんの代わりは絶対にできないこと
  • 部分的な家事育児の積み重ねの経験は必要なこと
  • 経験から、部分の前後関係に気づけるようになること
  • 連鎖していくことで、イレギュラーな分岐に対応する能力が上がること(おかーさんほどではない)

他にもたくさん話したし、おかーさんの家事育児は本当に命がけで休みがないです。だからこそ話の途中では非常に厳しく固い雰囲気だなって僕が感じる場面もありました。

命がけだから当たり前の話し方をしてるんですよね。それは奥さんにとっては当たり前。

でも僕はその当たり前を本質的に知るまでに至っていなかった。部分的にやっていただけだった。

それがわかり、厳しいわけでも固いわけでもなく、淡々と解説して、先を読み、僕の話を聞いてくれ、それに答えてくれている。

で、上記のことがわかった、というか初めて共有できたんですね。

そして、なんでそんなこと急に、しかもこの寝る直前に言ったのか。という話になって。

そういうことが考えられるくらい、気持ちに余裕ができてきたのかもね

って言ってくれたのがすごく嬉しかったし、今の僕の状態を奥さんも喜んでくれている、ということもわかりました。

実際、11月に入ってから、僕はお腹を壊していません。それまでは何かある都度、ひどい腹痛に10年くらい悩まされてきましたが、それが初めてピタリと止んでいるんですよね。(なので、根っこの体調そのものは非常に良好です)

そんな話から、生活や環境を今よりもっとよくしていくにはどうしようか?来年度からPTA役員だから家にいてほしいスケジュールはなるべく早く共有するからサポートよろしくね。そういえば洗濯機そろそろやばいよね。2月になったら最終決断しようか。そういえば食洗機ってどう?便利は便利、でもたまに傷がつくのよね。えーまじで。ほらほらこんな感じ、だから使うときは洗えてもお気に入りの食器はやめようね。そうだね、大事な子たちだもんね。そういえばソファを占領している大きなぬいぐるみ(すみっこぐらしのプライズ、つまりゲーセンから連れて帰ってきた子たち)のおうちどおしようかしらね?壁に固定する家具を選ばなくてわ!そういえばクリスマスはお揃いのちっこいバッグでいいかな?娘も欲しいって言ってたから共同で使うかな。それはいいわね。

などなど話は飛躍したし、要件定義について学習した結果の何気ない(と思っていた)問いかけが、奥さんに負担を強いてしまったんですけど、少なくとも僕は 家事育児が全然わからない。俺は雰囲気で部分的にやっている 状態から 命がけでやってるし代わりはできないし、おとーさんとして考える ってことはわかったし、それによって 24時間臨戦態勢のおかーさん をたまの1日でも休んでもらえるために僕にできること、をより具体的に考えることができるようになったし、あとは経験を積もう、って意識になれました。

要件定義から大きく話は逸れましたし、家事育児はそもそも要件とかそういう次元ではないので、安易に仕事っぽく話した結果の責任は僕には負えませんが、僕としては言葉にできないくらいの出来事に繋がったりしました。

仕事の思考で家事育児をやろうとすると破綻するのはわかったし、根本的に違うのもいったんはわかったし、最終的に言えることは、僕の奥さんはやっぱり最高だな。

この人に命を預けるって決めてからもう10年以上経っていますが、様々な環境の変化についていけていなかった自分がいたんですよね。それはきっと自分にとっては負い目に近かったんじゃないかなって今では思います。

今年は色々あったし、 おとーさんとしての1日を回したい なんて話、奥さんにとっては「めんどくさい話だな!」って一言で片付けられてしまわれかねない。手伝いって意識じゃ全然ダメだし、やりたいって言った以上はアテにするわけだから、依頼したら100%やれるもんじゃないと依頼できないし、依頼するんじゃなく行動をみて自分で判断できないと本当はだめ、ってこともあります。

けど、僕の気持ちは汲んでくれて、僕自身は前に進むことができた。あとは行動で示すしかないなって気持ちを新たにして、今日は寝ようと思います。

( ˘ω˘ )スヤァ

学習記録:12月18日(火):はじめよう!要件定義 Chapter-06 [準備編]企画を確認する(つづき)

これは 俺のインプットアウトプット記録 Advent Calendar 2018 の18日目のエントリーです。

本日は約4時間の研修を受けてきて、情報が溢れ気味でございます。が、間違いなく今後の仕事の仕方を変える内容でしたし、いかに僕らが 当たり前を具現化する仕事をしている のか、そしてそれを しょっちゅう忘れて頻繁に事故を起こす のかを思い知らされました。

研修内容をそのまま公開するわけにはいかないので研修レポートは書きません(手元にはしっかり残す)が、はじめよう!要件定義、を読み進めるにあたり、研修で学んだことなどは取り入れつつアウトプットにしたいと思います。

というわけで、前回の 学習記録:12月17日(月):はじめよう!要件定義 Chapter-05 要件定義、その前に & Chapter-06 [準備編]企画を確認する に引き続き要件定義の学習を進めます。

Chapter-06 [準備編]企画を確認する

昨日はこの章の途中までで終わっていました。企画書でゴール、つまり実現したいものを確認し、実現したいものからの逆算で「UI、機能、データ」を合意して進めていくわけですが、そのゴールが曖昧だとダメで、じゃあまとめるためにどんな項目があるのか、ということで以下の項目があればいいよ、まで進みました。

  1. プロジェクトの名称
  2. なぜこのプロジェクトをやるのか
    • 目的
  3. 何を
    • 目的達成のために作るもの
    • 作るものの説明
    • 作るものを利用する人
    • 利用する人が得られる便益
  4. どのように
    • 作るための体制
    • 期限

企画の内容を関係者が理解するための企画書

重要なのは企画を通すための企画書ではなく

  • 通った企画がいったいどのようなものなのか、を
  • 企画を実現するために作業する関係者、が
  • 理解するために必要な企画書

である、とあります。当たり前すぎてぐうの音も出ないんですけど、今まで多数の 企画を通すための企画書 を見てきましたし、そういう企画書ほど、 企画をするための企画書 だったりしたなあと思い返したりしました。

そもそも出発点は何かしらの情熱であり、それを実現するために前に進むための企画であり、その内容を共有するための企画書である。

だから、意思決定に対する「企画提案書」ではなく、実施が決まった企画の「決定報告書=プロジェクトそのものの仕様」が必要とあります。

つまり企画書を通す前の お願いします!の企画書 と 企画書を通した後にやる決定報告としての これをやります!の企画書=プロジェクト仕様書 が必要と理解しました。

RFPやプロジェクト計画書との違い

RFP支援の仕事もしたことがあるので、大変興味深い章です。要望を形にして、実現可能性や技術検討ができるようにするもの、くらいのふわっとした認識でした。

企画書が、RFP、いわゆる提案依頼書や、プロジェクト計画書と何が違うのか。

プロジェクト計画書から、マネジメント向けの情報を除外したサマリー

それが欲しいとあります。

  • 除外したいもの
    • 予算、リスクなど実務スタッフの担当領域外の情報
  • 不安や反発をなくす
    • プロジェクト仕様を知らないまま指示通りに作業しろ、と言われても…
    • 知らないことは先手を打つこともできない。プロなのに。
    • 何より人間は腑に落ちないことに不安や反発を覚え、手が止まりがち
    • 作業そのものが停滞しちゃうよね、と

企画書とは何か

プロジェクトについての紹介を、5分で手際よく事前知識のない人にできますか という問いかけが出てきます。

実務担当に不要な情報や、不安や反発を招きそうな内容だと、これから目指すゴールを紹介するのは難しいよな、と思います。

今から自分たちはこういうゴールを目指していくのだ と大雑把に理解できるために、 紹介するための企画書を作成 する。

そしてそれを共有する。 これが最初の材料 となる。

サンプル①:施設予約システム

サンプルとして、以下のプロジェクト仕様が掲載されています。僕なりに少し情報を足してみます。

サンプルには別紙参照の別紙がありませんが(そりゃそうだ)、それも含めてプロジェクト仕様書だと認識しました。で、そのプロジェクト仕様書を関係者で共有することで、自分たちが向かうゴールとその理由がわかる、ということかなと理解しました。

  • プロジェクトの名称
    • 施設予約システム
  • なぜ
    • 目的
      • インターネットを通じ、利用者が手軽に施設予約できるようにすることで、施設の稼働を活性化する
  • 何を
    • 目的達成のために作るもの
      • インターネットからの施設予約
      • 予約状況の確認
      • 実績データの他のシステムとの連携
    • 作るものの説明
      • 別紙参照(各機能の必要性とかUIとかかな)
    • 作るものを利用する人
      • 一般利用者
      • 窓口担当者
      • マネージャ
      • 経費部門
      • システム管理者
        • アカウント管理にシステム管理者を常に含めるのは重要
    • 利用する人が得られる便益
      • 別紙参照(フローや図があったりして別資料なのかな)
  • どのように
    • 作るための体制
      • 別紙参照(体制図が決まってないからかな)
    • 期限
      • 今年度中に完成
      • 新年度から運用開始

書籍にはもう1つサンプルがあったのですが、そちらは割愛します。ゲームを作るとなった場合にどうなるか、が書かれていました。

コラム:企画の良し悪し

企画もなしにいきなりソフトウェアは作れないよね、要件定義できないよね、狙いや企てのない取り組みはあり得ないよね、とあります。

まさにその通りで、企画の原点には情熱や思いから発する狙いや企てがあると僕も思います。

それは、趣味のプログラミング(他の趣味にも当てはまりそう)ですら、狙いや企てはある、と。そして、企画には良し悪しがある。

企画の良し悪しはどこに起因する?

利用者便益(ベネフィット)の観点から精査されているかどうか。

と述べられています。

成果と評価は違うとあります。

  • 成果はアウトプットであり、作り手が生み出す
    • 目玉焼きそのものは成果、しかし評価じゃない
  • 評価は受け入れる側が生み出す
    • 成果を受け入れ側がインプットし、そこから生まれる
    • 美味しい、いまいち、など
  • 評価の後は効果
    • 美味しければ嬉しくなったり幸せな気持ちになる
    • いまいちなら残念な気持ちになったり怒ったりする

この違いを認識せず、成果ばかりに目がいってしまい、評価や効果に対する狙いがあやふやなのが、筋の悪い企画であると述べられています。

効果の想定が曖昧

使い勝手のいいアプリを作る、という例で進んでいきます。

  • 使い勝手がいい、と評価するのはユーザーであり作り手ではない
  • ユーザーが評価した結果、どんな効果を狙うのか、が意外と曖昧
    • たぶん、職人文化を色濃くもつ日本人にすごくありがち
    • So What?(で?だからなに?) と問われたら回答できない

あるよなあそういうこと、って思いながら読んでました。

ストーリーを描けることが重要

  • 成果=例えば完成した「在庫管理システム」
  • 利用者が「仕事がしやすくなった!」という評価の先に…
  • 在庫回転率が向上するという効果が生じる
  • というストーリーが描けるものが良い企画

しかし実際にはストーリーに飛躍や断絶があって、実際の要件定義をする段になると、プロジェクトの目的に対して辻褄が合わない、矛盾した要件になってしまうよね、とあります。

重要なのは個別の正確性より全体の一貫性

個々に優れていても、例えば洗濯物を片付けたい、と言われ、いかに高性能かつ最先端の洗濯機を激推ししたとしても、おそらく以下の「洗濯」というプロセスに置いて、洗濯機は一部の、つまり個別の正確性の1つでしかないんじゃないかな、って考えました。

  • 洗濯物が発生するタイミング
    • 毎日、毎時、人、など多数かつランダム
  • 洗うと判断するタイミング
    • 定量に達したら?
    • 旅行などのイベントに関連する?
  • 洗うという行為
    • 洗濯物別に区分け
    • ネットに入れる
    • 順番を考えて実行する
  • 洗濯開始までの導線
    • カゴに放り込まれている
    • 仕分けする
    • ネットで包む
    • 洗濯機に入れる
  • 洗濯機を操作する
    • 洗剤を入れる
    • 柔軟剤をポケットに入れる
    • 水の量を設定する
    • 時間を設定する
    • 乾燥が必要か判断する
    • 乾燥のON・OFF
    • 洗濯実行する
  • 洗濯機が回る
  • 洗濯が完了する
  • 洗濯機から取り出す
  • 干す
    • ハンガーに通す
    • 洗濯バサミで止める
    • 洗濯棒にかける
    • 乾燥にかける
    • 陰干しにする
  • 乾いたか確認する
  • 乾いていれば取り込む
    • 定められた位置へ積む
    • 分ける必要があれば分ける
  • たたむ
    • しまう場所別にたたむ
    • 利用する人別にたたむ
    • 簡単なものからたたむ
  • しまう
    • タンスにしまう
    • クローゼットにしまう
    • 脱衣所にしまう
    • あるべき利用位置に設置する

思うこと

まさにその通りだなってのは前回にも思いを綴った記憶があるんですけど、仕事のための仕事を作る人っているよな、とも思いました。誰かのために、つまり利用者に便益をもたらすことから発進しているはずなのに、そこがすっぽり抜け落ちている。

利用者に便益をもたらす観点から考えずに、 企画を立ち上げなくてはならないからターゲットと市場を考えて、無理に企画を考案する なんてことあるよな、と。

得てしてそういう企画は利益にも結びつかず、便益をもたらす利用者の数も非常に限定的かもしれないなって思いました。

とはいえ、世の中の不便なことをちゃんと調べないと、企画も出てこない、ということも言えると思います。ゆえに、思いつきを徹底的に精査する、矛盾や無理のない内容であるかを突き詰める。

そうして初めて、企画としての実現可能性が見えてくるんだろうなって思いました。

やってみたいこと

執筆中

学習記録:12月17日(月):はじめよう!要件定義 Chapter-05 要件定義、その前に & Chapter-06 [準備編]企画を確認する

これは 俺のインプットアウトプット記録 Advent Calendar 2018 の17日目のエントリーです。

さて、明日は 徹底的に要件定義について学ぶ研修 があり、その教材の元になっているのが、この はじめよう!要件定義 という書籍だったりします。

ですので今日はMySQLはいったんおやすみし、前回の 学習記録:12月10日(月):はじめよう!要件定義 Chapter-03&Chapter-04 に引き続き要件定義の学習を進めます。

Chapter-05 要件定義、その前に

というわけで前章までは

  1. UI
  2. 機能
  3. データ

を決める、という流れで、実際に詳細を見ていきますというところで終わっていました。

UI定義という工程

UIが決まった、というゴールに到達するには、何をどうすればいいかと問われます。

どんな材料を使って成果物(ゴール)に向かうのか。それをまずUI定義から始めるということかな、と理解してます。

要件定義の旅への出発準備

目玉焼きという成果を出すには卵という材料が必要なのと同じく、定義されたUIという成果を出すにも材料が必要と書かれています。

そこで材料を揃えるための要件定義の旅、その出発の準備をするとあり、要件定義そのものではないとあります。

要件定義を行うために必要な材料を揃えるための作業がしばらく続くとあり、僕自身、要件定義を「何を持って完了とするか」を曖昧なまま今まで来てしまったので、非常に楽しみな内容です。

現実のプロジェクトあるある

要件定義と称して、要件定義の準備を行なっているケースが非常に多い、とあります。

よって、これから出てくる準備段階を要件定義としてやってしまっているってことは、要件定義の前工程である準備を先送りした事実の現れである、という理解を僕はしました。

そんなプロジェクトは好ましい状態じゃないよね、ということで次に続きます。

Chapter-06 [準備編]企画を確認する

僕は企画の部署に所属していたことがあるのでなんとなくわかるのですが、要件の前に企画が必ずあるんですよね。なのでそのことかなと思いつつ読み進めてみます。

ゴールを確認する

ソフトウェアを作る、というゴールを確認すると、依頼する・作るからには、思いつきだけじゃない、 企画意図が明確に定義されている はずとあります。

本当にその通りだと思いますし、思いつきだけで作ったプロダクトで成功した物を僕はみたことがありません。

以前、事業コンテストをきっちり行なっていた会社でも、思いつきだけではなく、役員全員に対しプレゼンをし、利益の可能性、市場の状態、人員確保、スケジュール、損益分界点など、裏付けの情報を含めてしっかりやっていました。

また、そうじゃないと予算など確保できないよね、とあり、その通りだよなと思います。

で、ソフトウェアはその企画意図を達成できるものじゃなきゃいけないし、企画意図から外れた要件を定義してしまったら、いくら要件定義通りに作っても納得が得られない、ということになるとあります。

当たり前の話ですけど、新規事業でも、受託の要件定義でも、できてない場面たくさんあるし、たくさん見てきたなー、と思い出します。

企画書を確認できない=ゴールの定義が不明瞭

企画確認は企画書を見るのが手っ取り早い。しかし現実では見ることができない場面がある、とあります。

  • 社内秘なので企画書を外部に見せられない
  • そもそも企画書がない

大雑把にいうとこの2つですとあり、そうだよなって思います。

重要なこと

企画書が見られない場合、それに代わるものが存在しない、つまりゴールが不明瞭である状態が問題であるとあります。

不明瞭とは、これを見ればわかるよ、という状態が得られないこと。それにより

  • 毎回口頭で解説を受けることになる
  • 記録に残らない
  • 時間の経過で簡単に変わってしまうことになる
    • 口頭の内容がブレる
  • 説明が面倒で端折る

ことで、結果として内容理解が関係者でバラバラになる。それぞれの「今回のゴール」がバラバラになり、理解の個人差が混乱を招くとあります。

全くその通りだし、ゴールが曖昧なままなのは、社内の他のチームから見ても不安になりますし、「何を目的にして、何を利益に還元するのだろう」と疑問にも思います。

次は「企画書を作成するためにまとめる項目」が具体的に出てきます。

企画書を作成するためにまとめる項目

バラバラになる問題は、プロジェクトマネジメントの問題で、要件定義の作業の問題ではないとあります。そりゃそうですよね。仕組みや組織の問題ってことでいいのかな。

しかし材料を揃えないといけない。揃わないと不明瞭な要件定義のまま進むことになる。

ゆえに、関係者全員がひと目で「理解を共有できる」企画書を作る必要があり、その最低限の項目が列挙されています。

  1. プロジェクトの名称
  2. なぜこのプロジェクトをやるのか
    • 目的
  3. 何を
    • 目的達成のために作るもの
    • 作るものの説明
    • 作るものを利用する人
    • 利用する人が得られる便益
  4. どのように
    • 作るための体制
    • 期限

この程度で構わない、と文中にありますが、この程度が全然できてないの多いよなーと思ってたら、次の文に このようなサマリーが存在しないプロジェクトが実に多数見受けられます とあってわかりみが深かったです。

なので、企画会議に出た人以外は、企画意図を理解する手がかりがないまま進んでしまう、つまり 企画者が後工程に対して理解不足である とあります。

これ、エンジニアでもマーケターでもディレクターでもなんでも、職種に関係なく、理解不足な場面あるよなって思いましたし、企画意図って上述の項目全部に理由があるはずで、それが 解説できなかったらその時点でその企画はダメなんだろうなあ と思いました。

僕が思うこと

名前って大事だよなって思います。業務システムで曖昧なまま進むのをみたことありますが、呼び方ひとつ取っても曖昧で、なんというか情熱というか、気持ちが入りにくいんじゃないかなって思ったりします。

目的はもっと大事というか、これ企画する一番最初にあるよねって思いますし、 目的ないのはただの趣味 だよなって思ったりもします。

また、目的達成のために作るものは何で、その内容はどんなもので、利用する人、つまりターゲットだと思いますが、そのターゲットはどんな人たちなのか。

で、その ターゲット=利用する人が何を得られるのか。押し付けじゃないよね、使って幸せになれるよね、って話だよな って思いながら読みました。

この辺に 無理なこじつけがある場合は、企画そのものに無理がある んだろうなあ、と思ったりもします。

また、企画といってもゼロスタートのサービスじゃなく、 既存サービスの新機能にも同じことが言える と思います。

以前、人材系のサービスに関わっていたときのプロジェクトマネージャは非常に優秀な人で、 各部署で企画が立ち上がったら片っ端からエンジニアを派遣し、スピーディーに実現可能性について即答できる状況を作った りしてました。

エンジニアだからといって企画、要件定義に関わらなくていいてことは全くなくて、むしろそこから関わることで、熱量や背景、歴史、目的、つまり 企画意図が正しく伝わり、同じ方向のゴールをみてプロジェクトが進められる んだろうなって思います。

読んでみて

ずっと自分の中にあった 思いつきだけじゃない、様々な根拠に裏付けられた企画意図 があるのが大前提だよな、という思いが、ここで見事に解説されていて、頷きしかないなって思いました。

そして、世の中にはそういった、思いつきだけで突っ走っては消えていくサービスが多いよな、ということも思いました。

それが良い悪いはさておき、思いつきだけで走るのは博打以外の何者でもなく、それが道楽ならいいですけど、利益をあげる必要がある場所で開発に関わるなら、 勝算のある博打を打つ 必要があるよなって強く思いました。

また、自分の今までの事業や企画に対する思いが間違えていなかった。それを確認できただけでも、読んでみて得られることは大きかったです。

次以降、読み進めるのが非常に楽しみですし、明日から始まる研修が楽しみで仕方ありません。

というわけで今週は要件定義週間になりそうです!

学習記録:12月16日(日):【MySQL】frmファイル欠損、ibdファイル存在、テーブル構成を推測したい【リストア不能】

これは 俺のインプットアウトプット記録 Advent Calendar 2018 の16日目のエントリーです。

結論から言ってしまうと、テーブル修復でエラーになっていたのは .ibdファイル がそもそもなかったからでした。おそらく、MacBookのストレージ容量不足でファイルを退避させた際に、なぜか .frmファイル を一緒に退避させなかったみたいですね(遠い目)

というわけで、振り返りつつ、どうにか .ibdファイル を直接読むことはできないものか、ともがいてみます。

昨日まで

昨日は MySQL 5.7.19 の環境をマイナーバージョン指定で作ろう、と思い立ったものの、おそらくソースからの make install じゃないと無理では…ということで、もともと使っていた環境に、エラーのあったテーブルをリストアし、mysql_upgradeを再実行すればいいかな、と思っていました。

なんと .frmファイル欠損

が、いざリストアしてみると肝心のテーブルがない…。あ、テーブル個別でバックアップ取っていたな、と思ってzipファイルを開くと…なんと .ibdファイルそのもの

.frmファイル がテーブル構造を表すファイルで、 .ibdファイル が実データを表すファイル。これではテーブル構造がわからぬ…しかも前回、公式にしたがって DROP TABLE しているので構造がわからない。

うーむ困った…。

`.ibdファイルを直接読んで、レコードの状態をみることはできないものか。

と探していると、 innodb_ruby というツールを提供しているかたを発見。

wiki に書かれている通りにインストールし、使ってみました。

innodb_ruby

以下の手順でインストールしました。

インストール

# バックアップを取っていたと思ったらibdファイルだけだったディレクトリで作業
$ pwd
/Users/mamy1326/dev/vagrant/mysql57/var/lib/mysql/mamy1326/innodb_ruby
$ sudo gem install innodb_ruby
Password:
Fetching: bindata-2.4.4.gem (100%)
Successfully installed bindata-2.4.4
Fetching: digest-crc-0.4.1.gem (100%)
Successfully installed digest-crc-0.4.1
Fetching: innodb_ruby-0.9.15.gem (100%)
Successfully installed innodb_ruby-0.9.15
Parsing documentation for bindata-2.4.4
Installing ri documentation for bindata-2.4.4
Parsing documentation for digest-crc-0.4.1
Installing ri documentation for digest-crc-0.4.1
Parsing documentation for innodb_ruby-0.9.15
Installing ri documentation for innodb_ruby-0.9.15
Done installing documentation for bindata, digest-crc, innodb_ruby after 3 seconds
3 gems installed

GitHubから諸々取得

$ git clone https://github.com/jeremycole/innodb_ruby.git
Cloning into 'innodb_ruby'...
remote: Enumerating objects: 2663, done.
remote: Total 2663 (delta 0), reused 0 (delta 0), pack-reused 2663
Receiving objects: 100% (2663/2663), 16.79 MiB | 483.00 KiB/s, done.
Resolving deltas: 100% (1451/1451), done.
naosama-mac:mamy1326 mamy1326$ cd innodb_ruby
naosama-mac:innodb_ruby mamy1326$ innodb_space -s ../
c_log.ibd    innodb_ruby/ 
naosama-mac:innodb_ruby mamy1326$ innodb_space -s ../c_log.ibd system-spaces
name                            pages       indexes     
/Library/Ruby/Gems/2.3.0/gems/innodb_ruby-0.9.15/bin/innodb_space:206:in `block in system_spaces': undefined method `pages' for nil:NilClass (NoMethodError)
    from /Library/Ruby/Gems/2.3.0/gems/innodb_ruby-0.9.15/bin/innodb_space:211:in `system_spaces'
    from /Library/Ruby/Gems/2.3.0/gems/innodb_ruby-0.9.15/bin/innodb_space:1976:in `<top (required)>'
    from /usr/local/bin/innodb_space:22:in `load'
    from /usr/local/bin/innodb_space:22:in `<main>'
$ cd innodb_ruby

innodb_space 実行

藁をもすがる気持ちで実行してみます。 なお、実行コマンドは wiki と、 日々の覚書 mysqlディレクトリーに知らない.ibdファイルがある in MySQL 8.0.0 を参考にさせていただきました。

  • -f オプション
    • 対象はibdata1ではなく、テーブル個別のibd
  • 対象ファイル
    • c_log.ibd ファイルに対し読み込みを実行する
  • page-dump
    • innodb_rubyが理解できるほとんどの構造体の表現を含むページの内容をインテリジェントにダンプします
    • 直訳ですけど、page単位でdumpしてくれる…のか?
    • -p 5 が5ページ分のdumpってことかな?
  • -T オプション
    • 指定されたテーブル名を使用します、とのこと。データベース名とテーブル名を指定します

で、dumpした結果。正直よくわかりませんな(遠い目

$ innodb_space -f ../c_log.ibd -T mamy1326/c_log -p 5 page-dump | less
#<Innodb::Page::Index:0x00007fe6b10dcb78>:

fil header:
{:checksum=>816151722,
 :offset=>5,
 :prev=>nil,
 :next=>nil,
 :lsn=>42947405534,
 :type=>:INDEX,
 :flush_lsn=>0,
 :space_id=>139}

fil trailer:
{:checksum=>816151722, :lsn_low32=>4292699870}

page header:
{:n_dir_slots=>3,
 :heap_top=>274,
 :garbage_offset=>0,
 :garbage_size=>0,
 :last_insert_offset=>265,
 :direction=>:right,
 :n_direction=>4,
 :n_recs=>11,
 :max_trx_id=>0,
 :level=>2,
 :index_id=>106,
 :n_heap=>13,
 :format=>:compact}

fseg header:
{:leaf=>
  <Innodb::Inode space=<Innodb::Space file="../c_log.ibd", page_size=16384, pages=559616>, fseg=6>,
 :internal=>
  <Innodb::Inode space=<Innodb::Space file="../c_log.ibd", page_size=16384, pages=559616>, fseg=5>}

sizes:
  header           120
  trailer            8
  directory          6
  free           16096
  used             288
  record           154
  per record     14.00

page directory:
[99, 181, 112]

system records:
{:offset=>99,
 :header=>
  {:next=>125,
   :type=>:infimum,
   :heap_number=>0,
   :n_owned=>1,
   :min_rec=>false,
   :deleted=>false,
   :length=>5},
 :next=>125,
 :data=>"infimum\x00",
 :length=>8}
{:offset=>112,
 :header=>
  {:next=>112,
   :type=>:supremum,
   :heap_number=>1,
   :n_owned=>8,
   :min_rec=>false,
   :deleted=>false,
   :length=>5},
 :next=>112,
 :data=>"supremum",
 :length=>8}

garbage records:

records:
{:format=>:compact,
 :offset=>125,
 :header=>
  {:next=>139,
   :type=>:node_pointer,
   :heap_number=>2,
   :n_owned=>0,
   :min_rec=>true,
   :deleted=>false,
   :length=>5},
 :next=>139}

{:format=>:compact,
 :offset=>139,
 :header=>
  {:next=>167,
   :type=>:node_pointer,
   :heap_number=>3,
   :n_owned=>0,
   :min_rec=>false,
   :deleted=>false,
   :length=>5},
 :next=>167}

{:format=>:compact,
 :offset=>167,
 :header=>
  {:next=>181,
   :type=>:node_pointer,
   :heap_number=>5,
   :n_owned=>0,
   :min_rec=>false,
   :deleted=>false,
   :length=>5},
 :next=>181}

{:format=>:compact,
 :offset=>181,
 :header=>
  {:next=>195,
   :type=>:node_pointer,
   :heap_number=>6,
   :n_owned=>4,
   :min_rec=>false,
   :deleted=>false,
   :length=>5},
 :next=>195}

{:format=>:compact,
 :offset=>195,
 :header=>
  {:next=>209,
   :type=>:node_pointer,
   :heap_number=>7,
   :n_owned=>0,
   :min_rec=>false,
   :deleted=>false,
   :length=>5},
 :next=>209}

{:format=>:compact,
 :offset=>209,
 :header=>
  {:next=>223,
   :type=>:node_pointer,
   :heap_number=>8,
   :n_owned=>0,
   :min_rec=>false,
   :deleted=>false,
   :length=>5},
 :next=>223}

{:format=>:compact,
 :offset=>223,
 :header=>
  {:next=>237,
   :type=>:node_pointer,
   :heap_number=>9,
   :n_owned=>0,
   :min_rec=>false,
   :deleted=>false,
   :length=>5},
 :next=>237}

{:format=>:compact,
 :offset=>237,
 :header=>
  {:next=>251,
   :type=>:node_pointer,
   :heap_number=>10,
   :n_owned=>0,
   :min_rec=>false,
   :deleted=>false,
   :length=>5},
 :next=>251}

{:format=>:compact,
 :offset=>251,
 :header=>
  {:next=>265,
   :type=>:node_pointer,
   :heap_number=>11,
   :n_owned=>0,
   :min_rec=>false,
   :deleted=>false,
   :length=>5},
 :next=>265}

{:format=>:compact,
 :offset=>265,
 :header=>
  {:next=>153,
   :type=>:node_pointer,
   :heap_number=>12,
   :n_owned=>0,
   :min_rec=>false,
   :deleted=>false,
   :length=>5},
 :next=>153}

{:format=>:compact,
 :offset=>153,
 :header=>
  {:next=>112,
   :type=>:node_pointer,
   :heap_number=>4,
   :n_owned=>0,
   :min_rec=>false,
   :deleted=>false,
   :length=>5},
 :next=>112}

次の課題

まずもってテーブル構造を、レコードから推測できないことにはリストアは不可能そうです。

しかしせっかく .ibdファイル を読み込むところまできたので、できる限りのことをしてみようと思います。

これで自由にレコード読めるようになったら面白いじゃん?

せっかく便利なツールを作ってくれている人がいるし、個人的に中身を直接読んでみたいと常々思っていたので、趣味的に願ったり叶ったり。

アップグレードはしばし棚上げして、 .ibdファイル の読み方を学習してみたいと思います。

もしこのエントリを読んでくださっているかたがいらしたならば、おそらく面白くないんじゃないかなあ…と思いながらも、自分自身はやっていて楽しいのでこうしてエントリにしているわけでございます。

1歩ずつ地道に進めてみて、結果までたどり着き、誰かしらの有益な情報になればいいなあ、と思いながら、やれるところまでやってみようと思います。

で、もしダメなら諦めて、くだんのテーブルは捨ててアップグレードを進めたいと思います。

アップグレード時にテーブル修復が失敗していたのも、そもそも .ibdファイル がなかったからで、ないならないで、消して進めれば本題はクリアできると思いますので。

というわけで、明日も引き続き .ibdファイル と戯れたいと思います!

開雲見日

これは #jobchanger 転職 Advent Calendar 2018 の16日目のエントリーです。

「雲を開きて日を見る」と読み、不安などの雲が吹き払われ、希望を見出すという意味を持つようです。

「開雲見日」は『後漢書』列伝六十四上袁紹伝で公孫瓚が言ったこととして四字熟語として記録されているようです。なんとなく今の気分を四字熟語で検索したら三国志に行き着いた。いずれ諸子百家を原文から読んでみたいし、史記も原文から読んでみたいと思っているので、何かのご縁かなこれは。

そういえば高校時代は四字熟語辞典を買って、授業の合間に読んでたなあ。

という趣味の話は置いといて。

僕は今年転職したのですが、退職にまつわる話は 2017年に引き続き退職しましたよっと のエントリーにまとめました。

なので、

  • じゃあ転職先はどうなのよ
  • どんなことして転職に至ったのよ
  • そこまでに何をしてどう分析したのよ
  • 転職して1ヶ月振り返ってみてどうよ

ということを、僕の働き方への思いも込めて 盛大なポエムとして 綴りたいと思います。これから転職する人、しようとする人にも有益な情報になるといいな、と思っています。

前職での転職の機運

前職の評価制度や人事制度など、企業がステップを踏む段階で必ず起こり得る大き目な変更がありました。

そこで結果としてリモートワークが一切できない状態になり退職したのは上述のエントリーの通りです。

働きかたの前提

僕はもともと、通勤ほど無駄なことはないと公言してましたし、家庭や働き方の事情もリモートがないと実現できないことは入社時に伝え、そこが僕からのMUST要件の1つであることは労使で合意済みでもありました。

オフィスと自宅の使い分け

僕個人としては使い分けたい大きな理由があったので、集中する時間は自宅で、必要なMTGや夕会はオフィスで、とうまく切り替えて利用していたのが、2018年5月くらいまででした。

前提と使い分けができなくなりそう…?

で、制度の変更後の内容がなかなか出てこなくて、色々と聞き及んだ話を総合すると「様々な経営側の要件にマッチしないとリモートが適用されなくなる」ということだけはわかりました。

そこで自分の可能性について、以下を元に分析し、デッドラインを早々に引きました。

  • 企業が求める人材像
    • カルチャーへのフィット率なども含む
  • 制度変更にいたる経緯の推測
  • 声の大きい人の発言の分析
  • リモートワーク、裁量労働、フレックスの一般的な定義と企業側との認識の違い
  • 絶対に譲れないポイントとデッドライン

結論

リモートワークができないなら退職。この結論を出したのは、7月でした。(確か)

しかし退職エントリーにも書いたんですが、メンバーには恵まれていたんですよね。特に技術面でのステップアップに関しては、在籍していてやる気がある以上、成長を続けられる。

結論は出しつつも、自分の感情としてはできれば続けたい。

そんな思いと、求められる人材像へのアンマッチを解消できないまま、日々は過ぎて行きました。

悩んだ時期

そんなに長くなかった です。感情に左右されることは道筋を誤らせる。

結論はもう出ているし、自分の特性もわかっている。奥さんと娘との対話もできていて、意識の共有、3人であったかく生きていく ことに対するシンプルかつ強い意志の再確認、これらは揺るぎない。

俺は家族と自分の幸せのために働いている。

それ以外にも理由はありますが、この根底の大前提は何があっても揺るがない。

退職を決断したのは8月中旬でした。

いざ転職へ動き出す

とはいえすぐに転職先が見つかるわけではないし、アテがそんなに多いわけじゃないし、Twitter転職とかガラじゃないし。

できれば僕のことを前々からよく知る人と一緒に働きたい。 働く上での思いを共有できている人と一緒に働きたい。

会社員であることに全くこだわらないのは、退職エントリにも書きましたが、働き方の多様性を認め合った上で、コミットメントしていく最良の方法を話し合える柔軟さがあるところで働きたい。

相談した人は1人だけ、現職の代表でした。

転職の条件

僕はどこかにも書きましたが、以下のことをすごく大事に考えています。なぜなら、子供の頃から、大事な時に親がいないことにずっと疑問を持ち続けていたからです。

おはよう。いただきます。いってらっしゃい。おかえり。ごちそうさま。おやすみなさい。が当たり前に言い合える

他人の働き方や家族や生き方を否定するわけでもなんでもないです。ただただ僕が30年以上抱き続け、変わることのなかった大事な大事な自分の中の柱です。

しかしこれを実現するには、いくつかのハードルを超えなくてはなりませんでした。

実現するために必要だったこと

箇条書きにしてみます。

リモートワーク必須

  • 必要な場合のみオフィスや客先などへ集まる
  • 突発はオンラインMTG
  • でも大事なコミュニケーションは集まろう

希望する報酬額

具体的な話は今度会ったときにでも聞いてくださいましー。

いただく報酬に対するコミット方法の確立

これが一番の悩みでもありました。が、相談したところあっさり解決してしまったんですよね。あー、こういう考え方の人がいて、信念をしっかり持っていて、人が幸せになるってどういうことが本質的に共有しあえるんだなって思ったりしました。

とはいえコミットメントを続けていくには、以下の解決すべき課題があると考えていました。

1日を分割して考える

  • 午前、午後1、午後2、と、家族や家事育児に合わせて時間を配分
  • うまく切り替えられるよう家族の理解を得る
  • うまく切り替えられるよう自分を訓練する

コミュニケーション方法

  • お互いのパーソナル的な部分の共有
    • 知った上で互いをフォローしあえる関係性
    • 何が無駄で何が重要かの意識の合わせ方
  • Slackなどでの密なコミュニケーション
  • 遠方でも問題のない仕事の進め方
  • 仕事以外での親睦の方法

成果の出し方

  • プログラミングだけではない
  • 要件定義、設計も含む
  • お客さん対応も必要
  • インフラの知識と経験も必要
  • それらを案件ベースでどう発揮するのか
  • 発揮した結果の評価を相互にどう確認するのか

報酬と稼働時間の考え方

  • 稼働時間は長ければいいってもんじゃないけど…
  • 状況次第ではきつい月もある
  • 稼働しない時は月に100時間程度
  • でも多いときは200時間とか普通に超える
  • それらを仕事とリソースと要件に応じて柔軟に実行できる環境作り

慣れるまでにお互いどう動くのか

いきなり触るシステムを十分に把握して動くにはやはり時間がかかります。しかしその目安は案件や人によって違ったりもします。

誰しもスーパーマンじゃない。

じゃあ軌道に乗るまでどう動くのか。どこまで会社や一緒に仕事する人に求めていいのか。そこが不安でもあり、どう解決していくかはっきり見えていませんでした。

実現するために解決したこと

とにかく相談しました。事前にかなり濃密にDMなどで話をしたし、じっくり腰をすえて面と向かって話し込んだりしました。

振り返ってみると、そこで一番重要だったのは、代表である人と お互いの考えや思い、なぜ働くのか、自分の、お客さんの、仲間の幸せとは何か の共有と共感、そして 幸せに向かうための優しさと厳しさ の共有でした。

それを踏まえた上で、先の課題をどう解決し、コミットメントできているか綴ってみます。

リモートワーク必須

解決というか、最初からそうだったので悩む必要は一切ありませんでした。

どうしても集まる必要がある時、お客さんとのMTG、研修。これ以外は全部リモートです。

リモートなので、面と向かっている時以上に細かく会話する場面がありますけど、それが自然にできる環境にあると思いますし、自然にできています。

なんか常にみんな笑ってるか、つらいよーっていうと「無理しない」って返ってきたりします。

分報チャンネルの少人数版があるのはとても大きいなあ。

1日を分割して考える

結果から言うと、1ヶ月以上経過した現時点で、非常にうまく回っています。

1. 午前、午後1、午後2、と、家族や家事育児に合わせて時間を配分

できてますね。午前は業務に対し動けないことも多いのですが、動かなくてはならない業務に対しては、動けなかったことは今のところはないはずです。

僕は奥さんの家事育児を手伝うレベルでしかないのですが、ガチで家事育児しているお母さんもいらして、業務を遂行できない時間帯がその日によったりします。(僕もそういうときあります)

そこは、Slackの「今何してる、これから何する、進捗どう?チャンネル」で常に発言・共有される ので、状態と進行状況が全員把握できているので、すごくうまくみんなを知りつつ仕事が回っています。

2. うまく切り替えられるよう家族の理解を得る

子供が生まれる前、将来的に今の生活にするのはずっと目標でした。なので13年前のフリーランス時代前期に 完全に自分の営業やツテで、100%自宅で仕事をする というのを2年間実行したことがありました。

その時に奥さんに対し、僕の集中時の状態、できればオンラインで声かけ、などなど、僕なりの働き方を実践して、生活に取り込んだことがそのまま活きました。

また、娘ともちゃんと話し、 集中する部屋にいるときはノックしてから とか どうしても用事がある時はおかーさんにお願いしてSlackで など、これまたうまく家族の理解を得ることができています。

3. うまく切り替えられるよう自分を訓練する

家族の理解を得られただけでは片手落ち。自分を訓練する必要もあります。

なので僕の方からも 出来るだけ家族の前で仕事をする 訓練をしましたし、今も訓練してますし、おかげで「集中をある程度保ったまま家族と会話する」ことができているように思えます。

大事なのは 割り込みを当たり前と思って行動する ことです。子供からの問いかけ、奥さんからの依頼、突然のピンポン(宅急便とかね)、業務の電話、などなど。 家族の前にいる時は割り込みOK と意思表示することで、イラっとすることもないし、家族との時間と仕事、どっちも標準以上にコミットできてるんじゃないかなって思います。

実装の合間に宿題をみて採点する、教える、とかはほぼ毎日だったりします。

また、たとえひとりの状態であっても自宅にある様々な誘惑(ゲーム、漫画、小説、など)に負けない方法は自分なりに確立できちゃいました。

方法は簡単で 「我慢しない」 です。

人の集中力なんてたかが30分程度しか続きません。

「あーゲームしてぇなー」って思ったら、それは休憩のサインだし「あーヤベェ眠い」って思ったら、それは肉体と精神が休息を求めているサインなんですよね。

なので、そういう場合は時間を決めて15分〜30分程度ゲームしたり漫画読んだりするし、合間に2時間の仮眠などを入れています。

ただ、 睡眠に関しては「連続6時間、1日8時間以上確保」が大前提 ではあります。

コミュニケーション方法

結論からいうと、全員リモートですが、現時点でなんの問題もないです。顔を合わせている時と何も変わらない。

みんながみんなを 「仕事だけじゃなく生活面でもフォローし合う気持ち」が共有できている し、先ほどのSlackチャンネルでそれが体現されているんですよね。

で、そこでパーソナルな部分がよく見えますし、みんな話してくれる。会社の人に対して、という感じではなく、「自分を知ってほしいし、そのために相手を知りたい」と思って発言・行動するし「感情を無理に抑制しない」し「無理してそうだなって思ったら全員から休めって言われる」し。

家族に対する感覚にかなり近いんじゃないかな。

あったかい環境ができてるなあって思うし、そこに絶対の安心感と安定感を感じるし、それがあるからこそ自分の立っている地面が安定するなって思えるし、そこから馬力を出してコミットするところまで繋がってるんだなって思います。

こういうコミュニケーション、クラフトマンソフトウェアさんのTweetで見かけた雰囲気にすごく似ているなって思ったりもします。れおりんさんとsuinさんのSlackでの会話を思い出しました。

成果の出し方

ただ実装してればいいってもんじゃない。それはどの職場に行っても同じだし、できることは多くなっていく。

僕の場合、 OOPを実践できるようになってきた のはとてもいいタイミングで、これはもう ぺちオブのおかげ なんだけど、それが業務に活かせている。そんな喜びと成果が繋がってるんですが、とはいえそれだけじゃない。

代表が要件定義のプロなので今まで一手に引き受けていたんですけど、それを僕やもう一人のメンバーと一緒にできるような体制づくりや研修、学習方法を考えて実践している最中だし、僕自身も代表と一緒にお客さんのところへいき、要件をヒアリングし、議事録をとる。代表がIFDAM図と機能一覧をガッと書き起こし、僕がレビューし、内容を互いに把握する。

来週は僕も研修を受けるので、年内(年始かなあ)にはIFDAM図を書いてるでしょうし、そうなればより要件定義から実装、運用まで一気通貫でできるようになる。

より 成果をあげられるようになる自分が想像できる んですよね。

また、技術支援として、AWSMySQLDNSの知見を活かす場面も少しながら出てきました。

今までやってきたことが無駄じゃなかったし、成長してたんだなって実感するし、コミットに繋がるし、評価もしてもらえている。

成果の出し方については代表としっかり振り返りしないといけない ですが、認めてもらえているということははっきりわかるので、今後も続けていくぞって気持ちです。

報酬と稼働時間の考え方

一言でいうと 柔軟ですし、明快です 。なので悩まずに済みます。コミットメントに応じて、です。

というか代表が働きすぎです。それは転職相談した時からずっとわかっていて、僕がJOINしたあかつきにはできれば半分は持ちたいなあ、と思っていた部分でもありました。

じゃあどう柔軟かというと、月単位での話じゃないんですよね。みんな複数案件に関わっていて、 日によって忙しさも違ってくる

納期前は多忙になるし、落ち着けば稼働時間も減る。それだけじゃなくて、お互いの状態に起因する時間や業務密度も非常に柔軟です。もちろんみんなすごく頑張ってるし、これからも頑張らなきゃいけないんだけど、それがもっとも効率のいい状態で頑張れているよね、って思うし、もし頑張れていないって個々人が思っているなら、それなんでだろ?って考えあうこともできる。

パーソナルなことや思いを共有できている からこそ、これは実現できてるんだろうなあ、と思います。

で、これは稼働時間の話で、1日の稼働時間も週単位も月単位も柔軟で一定じゃないですよ、それでもみんな責任持って結果出しているし出せる環境ですよって話なんですが。

報酬の考え方も非常にシンプル です。現在進行中の案件からいただいている受注額に対し、 自分がどれだけコミットできているか。

それにより決まります。これはJOINする前からそういう話をしっかりしていて、実際に時給単位に換算するとこうだよ、月にこの時間働きたいならこういう金額、もっと稼ぎたいなら自分で仕事を取ってきて相談、などなど、稼働も報酬も柔軟に相談できる環境にあります。

当然、一定以上の力量がないと自分の希望が実現できないとは思いますけど、じゃあ 力量をどう伸ばすか、何をしていきたいか、の相談も柔軟 にできているし、そのためにはどんな仕事を取っていくことを考えるのか、などの話もできています。

責任やコミットの上にある話ではありますが、みんなの状態や状況に応じて動くことができるのは、すごく柔軟で安心するなあと思います。

慣れるまでにお互いどう動くのか

これも事前に期間を決めました。ソースコードをざっとみて、システムや要件を解説していただいた上で、例えば この案件は2週間で立ち上がってくれれば上々 などの話を具体的に話し合います。

自分のスキルレベル、慣れた道具、慣れない部分に関しては正直に相談しますし、足りない部分はできる人がやりつつ、できるように進めていく、なんてことが日常的に実行されています。

先の要件定義の話もそうですし、そこに起因するレビューや研修は、まさに足りないところを成長させてくれるために、会社がしてくれることの1つです。

気軽に相談連絡報告できる雰囲気が常にある、っていうのもすごくいいなあと思います。

転職先

転職エントリーでも触れましたが 合同会社ねこもり です。ちなみに肩書きは えんじにゃー です。いやまじで。

現在新しい名刺を作ってもらってるので、次にお会いする方にはお渡しできるかな。

転職してみて ー生活編ー

1日を3分割して考える

僕の人生目標の1つに 生活と仕事の融合 があります。それを実現するために最適なのは、1日を3分割で考えることでした。

午前

  • 送り迎え、家事などがある
  • それ以外の時間で業務をする

午後1

  • お昼を食べて午後の仕事
  • 14時台のお迎えを挟んで17:30くらいまで業務

午後2

  • 17:30にお風呂、ご飯、寝かしつけ〜21:00くらいまで
  • 21:00-23:00に業務
  • 23:00-24:00は学習時間
  • 24:00-26:00に業務
  • 就寝

分割して働いてみて1ヶ月

これにより、家事育児と仕事を切り替えながら、例えばリビングでノートPCで仕事しながら娘の宿題をみたり、お昼食べながら奥さんと会話したり、気分転換に洗濯物畳んだり、 家族と自分のペースと仕事をうまく1つにできています。

おかげで、家族との時間を満足に過ごしつつ、仕事もコミットメントできています。代表からの評価もいただけていて、今の働き方で大丈夫みたいです。

転職してみて ー仕事編ー

CodeIgniterでの開発がもっとも大きな業務です。そのほかにインフラ構築、開発技術支援、要件定義見習い(?)、などが主な業務ですが、 今後は業務範囲が増えそう です。

増えるといっても、僕自身は開発から離れる気はないし、今後も20年は技術を追い続けていくし、成長も続けていく。

いわゆる一般的な管理職や上流工程に特化した人になる気は無いし、今後はインフラの方も力を入れて業務に関わりたいよ、というお話を代表としています。

それは僕のやりたいことと成長戦略とコミットメントの三位一体で出せることを具体化したことでもあるんですが、その意見を尊重して、今後の活動計画の1つとして考えてくれてます。

また コミットメントに対し、すごく感謝してくれて、やってるこっちが嬉しくなる んですよね。

フレームワークはただの道具だし、どれ使っても特に関係ないと僕は思ってます。前職で使っていたLaravelと、現職で使っているCodeIgniterはどっちも好きです。

で、ちょうどOOPの学習に本格的に入ることができたので、今はとにかく単一責務の原則に集中して、メンテしやすいコードをウンウン唸りながら書いてたりもします。 拡張に開いていて変更に閉じている、開放閉鎖原則など、OOPの一部を僕の持てる力で可能な限り 実装していく喜びを感じて いたりもします。

まだまだできてないところのほうが多いですけども。

仕事面に関しては、まだまだ発展途上。これからもインプットアウトプット続けていくぞ、って思いが減ることがないです。

やっていくぞっと。

これから転職する人へ

僕なりの考えですからね?

転職回数はマイナス要因にならない

転職って 明快な理由があればOK だと思っていて。例えば僕は転職して会社員になったのが6回、フリーランス時代にSESを利用して現場を変わったのが20回以上、職歴はある程度mergeするものの、かなり長くなります。

が、それぞれ全てに理由があり、重要なステップアップや酷かった理由は包み隠さず面談、面接で伝えてきました。

なので、 転職回数がマイナスになることはない ということをまず伝えたいです。

自分の幸せ

家族とどう過ごしたいのか。自分の心や気持ちが痛むのはどんなときなのか。どんな生き方をしたいのか。仕事の成果として何を世の中に提供したいのか。

それらは全て自分の幸せになると思います。

そして、その 自分こそが幸せでないと、働く意味がなくなってしまう といつも思っています。

僕の中で大事なことなので何回でも言います。

おはよう。いただきます。いってらっしゃい。おかえり。ごちそうさま。おやすみなさい。が当たり前に言い合える

僕はこれが自分の幸せの大前提です。

大事な柱はこれだけではもちろんなくて、お客さんが便利になった、よかったって思えるものを提供するのが大前提でもあるし、一緒に働く人に感謝されることも大前提の1つです。

でも、根っこは1つ。自分なんですよね。

自分が幸せじゃなくちゃ、好きな人も幸せにできない。

僕はいつもそう思っています。

自分が幸せな状態ってなんだっけ?ってずっと思い続けていきたいなって思っています。

おわりに

退職エントリに続いての、転職エントリとその後の振り返りを書いてみました。

なんか完全にポエムになっているような気もするんですが、ちゃんと振り返りもしましたし、 今回の転職に当たっては自分の内面と徹底して対話 をしました。

また、 家族とも対話しましたし、代表とも対話 しました。

その結果、僕の求めることと、代表の求めることが一致していることがわかりましたし、それは今のコミットメントに確実に繋がっています。

互いに求めることが100%になることは絶対にないと思いますけど、だからこそ100%に近づけるにはどうしたらいいんだろ、近づけて行きたいな、何も行動しなかったらパーセンテージは減ってくだけだよな。

そんな、人としての当たり前のことができる場所で、安心して働くことができています。

あと、繰り返しますが、このエントリは前職を否定するものではありません。 退職・転職するには決定的な理由が必ずあり、それはどこかが必ず合わなくて行われる行為 です。

そこを 正確かつ詳細に掘り下げ、検討・分析し、行動する。これって普通に当たり前のことだと僕は思っています。

ですので、忌憚なく思ったことをほとんど繕うことなく話したと思います。思うんだよなあ。

そして、今まで、今、これからに感謝を忘れないように。これから人生(家族・生活|仕事|それ以外)、 心が痛い思いをしないよう、楽しんで行きたい なって思います。

さあこれからだ。

学習記録:12月15日(土):【MySQL8.0アップグレード】5.7.19→5.7.24→8.0.11 アップグレード手順【5.7.24 アップグレード後編-MySQL 5.7.19の環境を新規に作ってみる】

これは 俺のインプットアウトプット記録 Advent Calendar 2018 の15日目のエントリーです。

昨日の振り返り

昨日のエントリーを出して間も無く、yoku0825さんに考察していただき、ログ( /var/log/mysqld.log )を遡った結果、エラーを起こしていたテーブルの .ibd ファイルが最初からなかったことが判明したので、ちょっと遠回りだけど以下の方法で再実行してみようと思います。

今後の方針

  • 5.7.19 の環境を作る
  • リストアする
  • .ibdファイルが揃っていることを確認する
    • 今回エラーのあったテーブルにSELECTできることも確認する
  • 5.7.24 へアップグレードする
  • 結果を確認する

んで、無事に 5.7.24 になったら、8.0.11 へさらにアップグレードしてみる計画です。

MySQL 5.7.19の環境を構築する

手順は以下を想定しています。

  • vagrantでubuntu18.04の環境を作る
  • MySQL 5.7.19 をインストール
  • データをリストア
  • MySQL 5.7.24 にアップグレード
  • エラーが出ないことを確認

昨年7月に vagrant で作った際は、リストアするデータが大きすぎて vagrant のデフォルト容量である 4GB をオーバーし、リストアできませんでした。

そこで、容量を 40GB まで増やして boxを作成し、リストアしました。が、昨年やったときはすごくめんどくさかった(イメージファイルを変換したり色々やった。正直覚えておりません…)です。しかし今はデフォルトで100Gあるのでそのままやります。

新しい vagrant box を作成

まっさらから作っていきます。Dockerでやればいいと思うかたもいらっしゃるとは思うんですが、今回の主題は

MySQL 5.7.19 から 5.7.24 にアップグレード したのち MySQL8.0.11(またはもっと最新)にアップグレード

することです。Dockerでそれをやる方法を少なくとも僕は知らないし、手軽に色々いじり倒したいので、vagrantを採用しています。

ここら辺はちゃんと理解してないんですが、主題とは逸れるので掘り下げずに進めます。

バックアップ

忘れずに以下をバックアップします。

  • Vagrantfile
  • my.cnf
  • データベース

box作成

ubuntuで作っていきます。

$ cd ~/dev/vagrant
$ mkdir mysql8.0
$ cd mysql8.0
$ vagrant init bento/ubuntu-18.04
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
$ vim Vagrantfile
$ cat Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "bento/ubuntu-18.04"

  # ポートとIPアドレスの設定
  config.vm.network "forwarded_port", guest: 80, host: 8080
  config.vm.network "private_network", ip: "192.168.33.10"

  # マウントするディレクトリ
  config.vm.synced_folder "./vagrant", "/vagrant"

  # メモリ容量(6G)
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "6144"
  end
end
# マウントするディレクトリ忘れずに
$ mkdir vagrant

vagrant up でbox作成

ポートとか他のboxとぶつかってないか確認忘れずに。ぶつかると以下のエラー出ます。

ポートフォワードのエラー

ついうっかり他からコピーしてきた時のあるあるですかね。俺たちは雰囲気でvagrantを利用している。

==> default: Setting the name of the VM: mysql80_default_1544881511628_84089
Vagrant cannot forward the specified ports on this VM, since they
would collide with some other application that is already listening
on these ports. The forwarded port to 8080 is already in use
on the host machine.

To fix this, modify your current project's Vagrantfile to use another
port. Example, where '1234' would be replaced by a unique host port:

  config.vm.network :forwarded_port, guest: 80, host: 1234

Sometimes, Vagrant will attempt to auto-correct this for you. In this
case, Vagrant was unable to. This is usually because the guest machine
is in a state which doesn't allow modifying port forwarding. You could
try 'vagrant reload' (equivalent of running a halt followed by an up)
so vagrant can attempt to auto-correct this upon booting. Be warned
that any unsaved work might be lost.

vagrant up でbox作成

$ vagrant up
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'bento/ubuntu-18.04' could not be found. Attempting to find and install...
(中略)
==> default: Mounting shared folders...
    default: /vagrant => /Users/mamy1326/dev/vagrant/mysql8.0/vagrant
$ vagrant status
Current machine states:

default                   running (virtualbox)

The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.

vagrant box の中で諸々更新

ubuntu18.04.1 のboxができました。次は諸々更新。

$ vagrant ssh
Welcome to Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-29-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sat Dec 15 13:56:05 UTC 2018

  System load:  0.0               Processes:           90
  Usage of /:   2.8% of 61.80GB   Users logged in:     0
  Memory usage: 3%                IP address for eth0: 10.0.2.15
  Swap usage:   0%                IP address for eth1: 192.168.33.10


0 packages can be updated.
0 updates are security updates.


$ sudo apt update -y
(中略)
$ sudo apt upgrade -y
(中略)
# 途中GUIが立ち上がり、キーボードについて聞かれるので適切に選択する、主に言語配列かな
(中略)
update-initramfs: Generating /boot/initrd.img-4.15.0-29-generic
vagrant@vagrant:~$ 

aptitude インストール

ubuntuのパッケージ管理ソフトウェアのaptitudeをインストールしておく。どうやら16.04あたりからデフォルトでインストールされないようになってるらしい。

$ sudo apt-get install aptitude
Reading package lists... Done
(中略)
update-alternatives: using /usr/bin/aptitude-curses to provide /usr/bin/aptitude (aptitude) in auto mode
Processing triggers for libc-bin (2.27-3ubuntu1) ...
vagrant@vagrant:~$ 

MySQL 5.7.24 のインストール

マイナーバージョンの指定の仕方がわからず。5.7系で最新の 5.7.24 をインストール。make installしかないのかな?

$ mysql --version
-bash: mysql: command not found

# パッケージを確認する
$ sudo aptitude search ^mysql-.*5.7
p   mysql-client-5.7                                                               - MySQL database client binaries                                                          
p   mysql-client-5.7:i386                                                          - MySQL database client binaries                                                          
p   mysql-client-core-5.7                                                          - MySQL database core client binaries                                                     
p   mysql-client-core-5.7:i386                                                     - MySQL database core client binaries                                                     
p   mysql-server-5.7                                                               - MySQL database server binaries and system database setup                                
p   mysql-server-5.7:i386                                                          - MySQL database server binaries and system database setup                                
p   mysql-server-core-5.7                                                          - MySQL database server binaries                                                          
p   mysql-server-core-5.7:i386                                                     - MySQL database server binaries                                                          
p   mysql-source-5.7                                                               - MySQL source                                                                            
p   mysql-source-5.7:i386                                                          - MySQL source                                                                            
p   mysql-testsuite-5.7                                                            - MySQL 5.7 testsuite                                                                     
p   mysql-testsuite-5.7:i386                                                       - MySQL 5.7 testsuite

# 必要な物を選んでインストール
$ sudo aptitude install -y mysql-client-5.7 mysql-client-core-5.7 mysql-server-5.7 mysql-server-core-5.7
The following NEW packages will be installed:
(中略)
Processing triggers for ureadahead (0.100.0-20) ...
                                         
vagrant@vagrant:~$ mysql --version
mysql  Ver 14.14 Distrib 5.7.24, for Linux (x86_64) using  EditLine wrapper

マイナーバージョンアップの再現どうするよ

現時点でマイナーバージョン指定のインストール方法がわからず(あんまり指定してインストールすることないもんなあ)

マイナーバージョンアップを実体験して成功させる、のも主目的の1つなので、昨日使っていた環境に対し、以下を実行してみます。

  • データベース削除
  • リストア
  • mysql_upgrade 実行

前の環境に戻って作業

先ほどバックアップはとりましたので、順番に実行していきます。

vagrant に対する操作

一応快適に操作したいので、今作った環境は止めて、前の環境で作業します。

$ vagrant halt
(中略)
$ cd ~/dev/vagrant/mysql57
$ vagrant up
$ vagrant ssh

データベース削除&作成

リストアの前に削除&空のデータベース作成します。

$ mysql -uroot -p mysql
Enter password: 
mysql> drop database mamy1326;
Query OK, 40 rows affected (0.58 sec)
mysql> create database mamy1326;
Query OK, 1 row affected (0.00 sec)

リストア

$ mysql -uroot -p mamy1326 < mamy1326.sql
Enter password: 

時間切れ

ここで今日の学習時間オーバー。15GBくらいのリストアなので、そこそこ時間かかります。

一応問題なくテーブルはリストアされていて、くだんの大きなテーブルも順調にサイズが増えているので、待てばリストアされるでしょう。

ここはリストアを待って、引き続き日が変わってから(になると思う)作業を続けたいと思います。

感想

久しぶりにリストアとかやるんですけど、去年散々やったのでこの辺は覚えてるもんですね。

あと、今までマイナーバージョンまで指定(というか意識)してインストールしたことなかったので、やり方がわかりませんでした。

マイナーバージョンが最新のならサクッとインストールできるんですけどね(当たり前)

ここら辺、検証したいわー環境個別に作りたいわー、っていうニーズは確実にあるはずなので、方法を探したいところです。

幸い前の環境は削除してないので、そちらで作業を続け、バージョンアップについての知見を得られ、アウトプットできたら、素直にMySQL 8.0の環境を普通に作って今後の検証作業とスライド作成など進めようかな、って思っています。

ただ、yoku0825さんにいただいたご恩を返すには、バージョンアップを成功させることが必要。これだけはしっかりやっておきたいと思います。

よっし引き続きやるぞー。

学習記録:12月14日(金):【MySQL8.0アップグレード】5.7.19->5.7.24->8.0.11 アップグレード手順【5.7.24 アップグレード後編-エラーを調べる】

これは 俺のインプットアウトプット記録 Advent Calendar 2018 の14日目のエントリーです。

結論からいうと、どうも サイズの大きなibdファイルが失われている ようです。結果、データファイルが読み取れず、アップグレードのチェック時にエラーとなっていた模様。

今回はそのエラーを /var/log/mysqld.log から、なるべく1つずつ調べていきます。

昨日の振り返り

趣味なので振り返りからやっていきます。

/var/lib/mysql/mysql_upgrade_info ファイルが書き込めなかった

昨日はパーミッションの関係で、以下のファイルが書き込めなかったのを解決し、そのさきへ…というところで止まっていました。

Could not create the upgrade info file '/var/lib/mysql/mysql_upgrade_info' in the MySQL Servers datadir, errno: 13

12月15日(土) 1:36 追記

最強の外部API神であるお豆腐さん が今日と昨日のエントリーをみてくれて、なんとまとめてくださった…あなたが神か(神です)。本当にありがとうございます!

とある豆腐のエラー考察(未完)

で、 /var/lib/mysql/mysql_upgrade_info ファイルが書き込めなかった の正解を引用します。

さすがやで…根拠をインクルードファイルで提示までしてくださる…。というわけで、 mysql_upgrade 実行ユーザーが vagrantユーザーで、/var/lib/mysql への書き込み権限を持たなかったため でした。(あってるかな?)

これもっかい最初からやり直そうかなって思ってます。

/var/lib/mysql/ パーミッション変更し、mysql_upgradeを再実行

で、パーミッションを変更してmysql_upgradeを実行し、ファイルが出力されるところまで実行しました。

$ sudo chmod 775 /var/lib/mysql
$ ls -lda /var/lib/mysql
drwxrwxr-x 7 mysql mysql 4096 1213 22:53 /var/lib/mysql
$ mysql_upgrade -uroot -p
Enter password: 
(中略)
Upgrade process completed successfully.
Checking if update is needed.

バージョン情報のテキストファイルだった

で、結果としては 5.7.24 のアップグレードのバージョンが出力されるファイルだったようです。

$ cat /var/lib/mysql/mysql_upgrade_info
5.7.24

それから

とはいえ本題のエラーはまだこれからでした。

Tablespace is missing for table

で、続いて昨日は以下のエラーが出て、特定のテーブルが5.7.19から5.7.24へのアップグレードされる段階でエラーを出力していました。ちなみにMySQL自体はアップグレードができています。

$ mysql_upgrade -uroot -p
(中略)
mamy1326.c_log
Warning  : InnoDB: Tablespace is missing for table mamy1326/c_log.
Error    : Tablespace is missing for table `mamy1326`.`c_log`.
error    : Corrupt

そこで今日は、このエラーの原因を究明、解決し、テーブルを復旧するところまで進めたいです。

試しにSELECT

MySQLの起動はできたので試しにSELECTしてみましたが、同じエラーになります。 というわけでこれは趣味。丁寧に調べていきます。

mysql> select * from c_log limit 1;
ERROR 1812 (HY000): Tablespace is missing for table `mamy1326`.`c_log`.

/var/log/mysqld.log エラーログを見る

困った時のエラーメッセージ。素直にエラーログをみます。

該当部分を抜き出し

今回のテーブルの部分のみ抜き出してみました。 色々出てますので、1つずつ調べてみます。趣味ですので。

2018-12-14T13:21:28.160781Z 2 [ERROR] InnoDB: Failed to find tablespace for table `mamy1326`.`c_log` in the cache. Attempting to load the tablespace with space id 139
2018-12-14T13:21:28.160847Z 2 [ERROR] InnoDB: Operating system error number 2 in a file operation.
2018-12-14T13:21:28.160856Z 2 [ERROR] InnoDB: The error means the system cannot find the path specified.
2018-12-14T13:21:28.160862Z 2 [ERROR] InnoDB: Cannot open datafile for read-only: './mamy1326/c_log.ibd' OS error: 71
2018-12-14T13:21:28.160868Z 2 [ERROR] InnoDB: Operating system error number 2 in a file operation.
2018-12-14T13:21:28.160873Z 2 [ERROR] InnoDB: The error means the system cannot find the path specified.
2018-12-14T13:21:28.160880Z 2 [ERROR] InnoDB: Could not find a valid tablespace file for `mamy1326/c_log`. Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting-datadict.html for how to resolve the issue.
2018-12-14T13:21:28.160996Z 2 [Warning] InnoDB: Cannot calculate statistics for table `mamy1326`.`c_log` because the .ibd file is missing. Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting.html for how to resolve the issue.

Failed to find tablespace for table mamy1326.c_log in the cache. Attempting to load the tablespace with space id 139

直訳すると以下になります。

キャッシュ内のテーブル mamy1326.c_logのテーブルスペースを見つけることができませんでした。スペースID 139で表スペースをロードしようとしています

何のことやらさっぱりです。 グーグル先生に頼っても「クラッシュしたんで復旧してや」って記事ばかり。俺はこのエラーメッセージの意味と原因を知りたいんじゃああああああ!

と思うけど他にもエラーメッセージがたくさん出てるので次々調べてみます。

Operating system error number 2 in a file operation.

これも直訳します。

ファイル操作中のオペレーティング・システム・エラー番号2。

ざっくりとしかわからへんがな(´・_・`)

次調べましょう。

The error means the system cannot find the path specified.

これも直(ry

エラーは、システムが指定されたパスを見つけることができないことを意味します。

お、これは前のエラーと繋がってることを意味しそうです。何かパス間違ってるんかな。ibdファイルかな。うーん。

しかし my.cnf へのパスの情報はこれくらいしか設定してない。

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

とりあえず次のエラーを調べます。

Cannot open datafile for read-only: './mamy1326/c_log.ibd' OS error: 71

おおおおっ。これは…ッ!ibdファイルが開けない…ッ!パーミッションか…ッ!

突然のJOJO風、失礼しました。取り乱しました。

やっとエラーメッセージみただけでわかりそうな感じになってきたので、ファイル確認します。

$ sudo ls -la /var/lib/mysql/mamy1326/c_log.ibd
ls: /var/lib/mysql/mamy1326/c_log.ibd にアクセスできません: そのようなファイルやディレクトリはありません

テーブルの実体ファイルがないじゃない。ちなみに定義ファイルはありました。

Could not find a valid tablespace file for mamy1326/c_log. Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting-datadict.html for how to resolve the issue.

結局のところ、最後のエラーメッセージで、公式をみてトラブルシューティングをするべし、とありがたくも指摘までいただけているのでみていくことにします。

というかこれ、アップグレードしようとして、ファイルでかすぎて変換できなかったんじゃないかな、と今の時点で予測を立ててます。

公式を参照する

公式の 14.19.3 InnoDB データディクショナリの操作のトラブルシューティング を参照します。(内容は全て翻訳機にかけた内容です)

序文

テーブル定義に関する情報は、.frm ファイルと InnoDB データディクショナリの両方に格納されます。.frm ファイルをあちこちに移動したり、データディクショナリの操作の最中にサーバーがクラッシュしたりすると、これらの情報のソースに整合性がなくなることがあります。

frmファイルにテーブル定義、ibdファイルがデータディクショナリ、という認識です。これがクラッシュしたら整合性取れなくなるよと最初に言われています。

データファイルを開くことができません。

公式の前半部分に、今回のエラーメッセージズバリの内容が書かれていました。innodb_file_per_tableパラメータはデフォルトでONになっているので、表領域は共有ではなく個別領域です。その表領域である .ibd ファイルが欠落しているよと言われます。

innodb_file_per_table (デフォルト)有効にした場合、次のメッセージが起動時に表示されることがあります ファイルあたりのテーブル 表領域のファイル(.ibdファイル)が欠落しています。

はい、その通りでした。サンプルのエラーメッセージも今回のものとほぼ同じです。

[ERROR] InnoDB: Operating system error number 2 in a file operation.
[ERROR] InnoDB: The error means the system cannot find the path specified.
[ERROR] InnoDB: Cannot open datafile for read-only: './test/t1.ibd' OS error: 71
[Warning] InnoDB: Ignoring tablespace `test/t1` because it could not be opened.

で、解決方法としては、DROP TABLEしなさいと書かれています。

これらのメッセージに対処するには、DROP TABLEステートメントを発行して欠落しているテーブルに関するデータをデータ辞書から削除します。

DROP TABLEしてみる

.ibd ファイルが欠落した理由は今のところわかっていませんが、幸いこのテーブルはバックアップがあります。そこで素直に公式に従い、DROP TABLEしてみます。

ちなみにログインした結果から、 Server version: 5.7.24-log MySQL Community Server (GPL) が確認できます。

$ mysql -uroot -p mamy1326
Enter password: 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.24-log MySQL Community Server (GPL)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> DROP TABLE c_log;
Query OK, 0 rows affected (0.02 sec)

無事DROP TABLEすることができました。

テーブル定義も消えてますね。

$ sudo ls -la /var/lib/mamy1326/c_log.*
ls: /var/lib/mamy1326/c_log.* にアクセスできません: そのようなファイルやディレクトリはありません

次の課題

DROP TABLEしたものの、こいつを復元するのはどうやって?がまだわかっていません。

バックアップからリストアするんだろうな。ということでリストアするとは思います。

今回はここまで

さて、いったん学習時間としては時間切れ。引き続き明日調べていきます。

それにしても5.7.19で構築した環境にテスト的に大きめなデータを入れた状態で、マイナーバージョンアップしただけでもこういうことが起きる。いい経験をしているなーと思います。

現段階での予測では、以下の状態だったのかもしれないなあと思ったりしてます。

  • vagrantは40GB
  • テーブルスペースの総容量は20GBちょっと
  • ストレージの空き容量は4GB程度
  • なんらかの理由でデータファイルを消した
    • 手で消してた?
  • またはmysql_upgrade実行時に復元できなかった
    • 容量不足?

12月15日(土) 2:10 追記

/var/log/mysqld.log を遡ってみると前から起きているエラーがあった。

  • そもそもibdファイルを作成できていなかった?
    • 過去のmysqld.logを遡ったら Cannot open datafile for read-only: './mamy1326/c_log.ibd' OS error: 71
    • そもそも去年の7月に環境作ったとき、ディスクフルで書き込めてなかった
      • 2017-07-07T22:01:02.800765Z 3 [ERROR] /usr/sbin/mysqld: The table 'c_log' is full
    • よってvagrantのbox容量を40Gに拡張したのち、リストアしていた
      • しかしそれでもibdファイルは正しく作られていなかったか、どこかで消えていた
      • 2017-09-21の時点でも同じように、ibdファイル読めないよ(ないよ)と言われていた
      • 2017-09-21T13:53:39.939744Z 0 [ERROR] InnoDB: Cannot open datafile for read-only: './mamy1326/c_log.ibd' OS error: 71
  • ログには別のエラーも出ていたが、MySQLの起動には成功していた
    • 例えばこれ
    • 2018-04-29T13:07:39.271664Z 3 [ERROR] InnoDB: Failed to find tablespace for tablemamy1326.c_login the cache. Attempting to load the tablespace with space id 139
    • このエラー出てる場合、MySQLの起動に失敗する事例しか検索できなかったけど、なんでだろう…
  • ibdファイルがないため、統計情報の計算ができません、と言われているので、この時点で欠落していた
    • 2018-04-29T13:08:18.405618Z 3 [Warning] InnoDB: Cannot calculate statistics for tablemamy1326.c_logbecause the .ibd file is missing. Please refer to http://dev.m ysql.com/doc/refman/5.7/en/innodb-troubleshooting.html for how to resolve the issue.

つまり、 アップグレード実行時に .ibdファイルが欠落していた ことがわかりました。

今後の進め方

幸いバックアップデータがあるので、リストアしてもう一度実行してみようと思います。

今度は、全てのibdファイルが揃っていることを確認した上で。

で、ストレージ容量不足なのか、データが悪いのか、順番に切り分けしてみようと思います。

いやーでも手動でibdファイルは消さないと思うんだよなあ…。

12月15日(土) 2:15 追記

最初から .ibd ファイルがなかったことが判明したので、ちょっと遠回りだけど以下の方法で再実行してみようと思います。

  • 5.7.19 の環境を作る
  • リストアする
  • .ibdファイルが揃っていることを確認する
    • 今回エラーのあったテーブルにSELECTできることも確認する
  • 5.7.24 へアップグレードする
  • 結果を確認する

んで、無事に 5.7.24 になったら、8.0.11 へさらにアップグレードしてみる計画です。

さて、明日もやるぞ!