ytake blog

Web Application Developer

エンジニア的3ヶ月で16キロダイエット!

久しぶりのブログ投稿ですが、
今回は健康的なダイエット生活についてお届けします。
8月から10月末まで、一応期間を作ってストイック気味にダイエットをしていました。
エンジニアの自分が実際にこの3ヶ月でやってきたことを記念に残しておこうと思います。

結論からいうと、
3ヶ月で16キロ減量し(84キロから68キロ)、
BMIは5マイナス(26.8から21.7)、体脂肪は7.5%ダウン(25%から17.3%)、
骨格筋率は5%アップ(33%から38%台へ)、体年齢は15歳若返る(48から33)

という成果になりました。

ちなみにジムには通いませんでした。
やってしまえば気合でなんとかなる、という性格なので自宅とランニングでなんとかしました。

コロナで変わってしまった生活環境

コロナなどの影響で外出する機会が減ってしまい、
太ってしまった方、逆に痩せた方、様々な方がいると思います。

自分は去年ヘルニアの手術(ヘルニコア注射ですが)をやったり、
調子が悪くなったりで肉体的にも外に出る機会が少し減ったりしていました。

今年は年明けから間も無くコロナということでそれまでの生活から大きく変わってしまいました。

その一つに出勤の移動がなくなった、という方も多いと思います。
外に出る機会が減ったため、仕事をする上では大変楽なのですが、
千葉北部の隅っこに住んでる自分としてはこの通勤が、意外といい運動になっていたことがわかりました。

そう、年末から今年の7月中旬にかけて10キロ以上太ってしまいました。

自分は身長177センチなんですが、10キロ以上太って84キロ台に。
BMIでいうと26.8になるので、肥満1度となります。

オフラインで久しぶりに会う方には、「あれ、ytakeさんひとまわり大きくなった?!」と
ほぼ必ず言われていました。

はい、ひとまわり大きくなりました。
Lサイズの服を着るとお腹がだいぶ気になる状態だったのでXLを着るという状態でした。

ダイエットするぞ!

大きくなりつつ、たまたま病院で血液検査などをしていた時に
脂肪肝になりつつあるので気をつけてと言われることも多くなり、
減量しなきゃまずいな、と思いつつなかなかできませんでした。

そんな中、ダイエットするぞ!となった決定的なものは、
昔から聴いていたアーティストの現在の姿をYoutubeでたまたま観ていた時に、
当時スマートでカッコ良かったのに、今はこんなデカい体に・・・・
と。
(ちなみに観ていたのは、元Sepulturaのマックス・カヴァレラ)

歳を取ると大型化する人は海外アーティストに多く、
年齢や健康を考えたらやるしかない!ということで
区切りの良い8月からダイエットをすることにしました。

痩せるために大事なこと

個人的にやると決めたら絶対にやらなきゃ気がすまない性格なので、
痩せると決めたら目標を決めて絶対にやり遂げる、というのが
一番良かったのかも、と思っています。

明日できることは明日でいいやぁ、と思うこともありますが、
人間は1キロ痩せるのに7000kcal必要と言われるので、
明日に回したところで何もプラスにならないので、
とにかく毎日義務的にやる、ということを常に意識して取り組んでいました。
幸いにしてコロナ禍ということもあって、呑みに行ったり通勤で疲れてやる気がー、
などということは一切ありませんでした。

途中から義務的にやっていたものが生活習慣へと変わっていく意識があり、
1ヶ月半超えたあたりから毎日体を動かすのが楽しくて仕方ありませんでした。
ランニングなんかは今後も継続して行うと思います。

それでは以下、この3ヶ月でやったことを記載していきます。

食生活を変える

減量の基本といえる食生活。
今回は炭水化物抜きダイエットとか、
所謂食事制限だけでするダイエットはしませんでした
明らかにリバウンドすることもわかっていたのと、
体重減少とともに筋肉も基礎代謝も落ちていくので、
筋トレは必ずやる、と決めていたので食事は最低限のものは取る様にしました。

食生活で大きく変えたのは、
摂取カロリーを意識した食事メニューにする、でした。
意識したのは炭水化物は1日に一食は取る様にして、
とにかく基礎代謝以上には絶対に取らない、ということでした。

その中でも晩飯のメニューはダイエット、筋トレの定番メニューにすることが多かった...。

ただ食事制限だけのダイエットにするつもりはなかったんですが、
結果的に食事制限していた、という形になっていました。

1日の食事は

  • 朝はオイコス一個と小さいアンドーナッツ(子供向けの)1個
  • 昼はオイコスとウィダーinゼリー(エネルギー)
  • 夜は野菜、サラダチキン、茹でたまご またはご飯とおかずの何か

という具合でした。
食事のみのカロリーを計算すると大体食で800kcal以下という日がほとんどでした。
当然腹が減るんですが、
お腹が減ると脂肪を使ってエネルギーに変える、という体の仕組みを使って、
空腹になったら筋トレをして空腹感を紛らわせて食事量を少し減らす、という具合です。

筋トレを毎日欠かさず

体重とともに筋肉と基礎代謝が落ちていくので筋トレは必須でやっていました。
上記の食生活改善もこの筋トレのおかげで改善しやすかった、というのもあります。

そんな毎日の筋トレメニューは以下のものをやっていました。

  • 腹筋100回
  • ダンベルカール(左右100)
  • サイドレイズ(20 2セット)
  • ダンベルショルダープレス(20 2セット)
  • 背筋100回
  • バックランジ(20 5-10セット)
  • プランク(30-60秒)
  • レッグレイズ -> オルタネイトレッグレイズ -> リバースクランチ -> V字クランチ(30秒やって20秒休んで最後まで)
  • 腕立て伏せ(80回)

回数があるのはその日の限界くらいまでやるので、多少可変させてやっていました。
これを毎日やり、ある程度体が慣れた1ヶ月半後くらいにHIITを追加しました。

「HIIT」とは「High-Intensity Interval Training(ハイ・インテンシティ・インターバル・トレーニング)」の略。高強度インターバルトレーニングのこと

HIITは以下のものを毎日やっていました。

  • バーピー -> スクワット -> スクワット&ジャックス -> マウンテンクライマー

上記のものを「30秒全力でやって30秒休んで最後まで」を4セットやります。

筋トレだけで消費できるカロリーは高が知れているので、
HIITを追加することで室内でできる筋トレと有酸素運動を加えた形になるので、
4セットくらいで大体150kcal消費できる様になります。

これらを在宅ワークという環境を使って、昼休みにやります(やっています)。

有酸素運動も毎日欠かさず

大きく体重を減らせたのは有酸素運動を毎日やっていたから、というのも一つ理由としてあるかなと思います。
有酸素運動といえばランニングですが、最初からランニングはやりませんでした。
というか最初にランニングをやっていましたが、肺活量も持久力も最初からあるわけではなく、
途中で走れなくなることも多かったので、
まずは最初に肺活量と持久力を鍛えることにしました。

どうやって肺活量と持久力を鍛えたのかというと、
それはエアロバイク!
エアロバイクはながらでやることができる有酸素運動として有名ですが、
ながらでやることは辞めました。

カロリー消費と肺活量、持久力を鍛えたかったので、
例えば動画を観ながらやると心拍数は大して上がらず、消費カロリーも大したことありません。
効率よくやせるには心拍数の維持と、時間です。

そこでエアロバイクは週ごとに心拍数と時間を上げていく、
というストイックな形式でやることにしました。
最初の1週間は心拍数150で30分続けることから始めました。
2週間後は心拍数150で40分、
その翌週は心拍数150で50分、
8月末あたりは心拍数150で60分になっていました。

心拍数150で60分やると、60分で大体600kcal以上は消費できる様になります。
最初の頃は音楽を聴きながらやっていましたが、
自分の呼吸ペースと合わなくなるとあまり調子が良くない、ということがわかり
無音で60分やることに。

9月は心拍数167くらいで60分漕ぐ、というペースに。
所謂ハードペースというペースになり、60分で大体800kcalくらい消費になり、
体力的にも余裕がでてきて60分以上を毎日やり、
1日エアロバイクだけで1000kcalくらい消費する様になりました。

このくらいまでいくとランニングに切り替えてももう問題ありません。

そこで、ランニングに移行する前の9月の後半は
エアロバイク50分とウォーキングに切り替えました。
ウォーキングといっても心拍数140台で歩くため、ほぼ競歩みたいな感じになります。

ウォーキングをしながら走るコースの下見をする、という具合ですね。
エアロバイクは天気に左右されずにできるので大変良いんですが、
部屋の中でしかも集中してやるので途中から飽きてしまいます。
9月末からランニングにしたのは丁度良かったかもしれません。

Apple Watchはワークアウト時に心拍数が常に確認できるのでかなり重宝しました。
ダイエットする方は購入しましょう!

10月からはランニングに移行し、雨の日だけエアロバイクにすることにしました。
ただ2ヶ月経過すると、体重がすでに10キロ以上減っていたこともあり、
予定よりも痩せすぎてしまうので少し消費カロリーをコントロールしました。

ランニングは1キロ7分ペースからはじめ、
徐々に早くしていき、今現在は1キロ5-6分くらいのペースになっています。
走る距離は6キロからはじめ、現在は10キロに。
減量目的でランニングする方は、はぁはぁする手前のペースを維持するのがいいかなと個人的に思います。
自分はエアロバイクを毎日2ヶ月やってからランニングに切り替えたので、
かなり早めに走っても全然息が上がらなくなりました。

毎日やっているとこの辺の体の変化がわかるので、モチベーションにも繋がります。

プロテイン

プロテインは9月中盤から飲むことにしました。
飲んでいたのはSAVASのアスリート ウェイトダウン ヨーグルト風味!

ヨーグルト風味とありますが、実質きな粉みたいな感じです。
ソイプロテインは吸収がゆっくりということもあり、
寝る前30-60分前に飲むように。
これは就寝時の成長ホルモンが分泌されるピークに合わせた時間になっています。

プロテイン飲んだら太る!という方もいるかも知れませんが、
1日の摂取カロリーによります。

たくさん食べながら痩せる、というそんな虫のいい話はありません。
諦めて食事制限と有酸素運動と筋トレをしましょう。

所謂チートデイはつくらない

ダイエットの記事を見るとチートデイというものについて書かれていることが多いですが、
基本的に体重が減らなくても食事に気をつけて筋トレと有酸素運動を欠かさずやっていれば、
停滞期が来てもその後減っていきます。

10日間ほど所謂停滞期らしいものがありましたが、
体重は毎日減っていくものではなくて、一週間くらいの期間で減少傾向にある、
という感じでわかるものなので、
一週間くらい減らなくても焦らず、そしてチートデイというものには頼らない方がいいです。
食べすぎてリバウンドしてしまった、というのはよくある話です。

自分はかなり速いペースで体重を落としていったので、
9月中盤から後半にかけて減りにくい期間がありましたが、
ちょうどこの時期あたりにHIITを導入した期間でもあり、
減りにくい期間が過ぎたら一気に落ちていきました。

結果

上記の食生活の見直し、
1ヶ月あたり大体5キロくらい減量し、
結果3ヶ月で16キロ減量になりました。

現在コロナ禍ということもあり、運動不足はいろんな方が感じていることだと思います。
エンジニアという職種についているので、
在宅ワークの時間を使うことで効率的に運動不足を解消することができる!
という事がわかった3ヶ月でした。

体全体の肉が1週間ごとに減っていくのがわかるので大変楽しかったです。
減量中に取り組んでいたものは習慣化しているので(ランニングなど)今後も継続してやりながら
健康的で元気なエンジニア生活を送っていこうと思います。

ダイエットしたい!という方は是非参考にしてみてください。

スターフェスティバル株式会社にジョイン! &仲間を募集中!

f:id:ytakezawa:20200906102102p:plain

近況のお話です。

スターフェスティバル株式会社

9月より、
元メルカリCTOでもあるsotarokが現在CTOとして務めている
スターフェスティバル株式会社にジョインさせていただくことになりました。

プロダクト開発に舵を切ったばかりのところで、
且つエンジニアリング組織としては刷新したばかり、
様々な文化ややり方、環境、技術的な部分もまだまだこれから大きく変わろうとしている段階で、
これまでのCTO経験やテックリード的な動きや経験が
活かせる職場でもあり、
システム的にもいろいろこれから整えていく、まさにそんなフェーズで面白そうと思い
ジョインさせていただきました。

自身は事業ドメインについて現在理解を深めているところです。
(ドメイン駆動開発をするため)

直近では大きな課題をいくつか抱えているので、
そう云った問題解決にコミットしつつ、エンジニアをもう1段階、2段階へと底力を上げながら、
強い組織作りにもコミットしようと考えています。

アイスタイルでCTOとしてやってきたこととあまり変わりませんが、
エンジニア組織としてはまだまだかなり小さいので、
伸び代がかなり大きい段階です。
こうしたフェーズに参加できるのはとても楽しくもあり、
数年後を考えるとどう云った形に成長しているのか、ワクワクする環境です。

仲間を募集中!

さてさて、そんなスターフェスティバル社ですが、
当然これからプロダクト開発へ力を入れていきますので、
インフラ(現AWS)や、フロントエンドエンジニア(Vue、TSなど)、
バックエンドエンジニア、プロダクトマネージャー、モバイルなど
様々なエンジニアを募集しています。

バックエンドは現在PHPやNode.js(TS)がメインではありますが、
言語にこだわるよりも、適材適所で技術選択ができるエンジニアの方は
かなり活躍できる場だと思います。
(GoやRust、もう少しシステムが大きくなればScalaなど(?))

一緒に文化作りやチームビルディング、自動化、改善などを行いながら
楽しくエンジニアリング組織を盛り上げてくれる、そんな仲間を強く求めています!

ちょっと興味がある、カジュアルに聞いてみたい、詳しく知りたい、などありましたら
竹澤まで気軽に連絡いただければと思います!

是非一緒にやりましょう!

現場からは以上です。

近況のご報告

一年の半分が過ぎました。

近況の話

ヘルニアの治療に続き、
体にガタがきてしまいしばらく大人しくしていました。
しばらく休ませてくれた会社、関係者に感謝致します。

完全に近いくらい復活しまして、
知人の会社の手伝いをしながらいろんなことをやってました。

自分で機械学習の処理をイチから全部実装したり、
CQRSを応用した様なものを多数作ったり、
相変わらず複数言語を多用した開発スタイルを取りながらEKSでのサービス運用だったり、
なぜかPythonからScalaへの移行をやったり etc...

そんでもって一年の半分が過ぎたということで、
働き方を大きく変えることにしました。

アイスタイルのCTOを退任させていただき、また社員としてではなく、
ちょっと異なるポジションで技術面で関わらせていただくことになっています。

という近況の報告でした。

今後どこかに社員として転職するのかとかは今時点では特に決まっておりません。

しばらくは好き勝手に何かしようと思っていますが、
何か面白そうな話などがありましたらTwitterやFacebookなどでお気軽に話しかけてください。

最近Twitterの方でも呟きましたが、
最近おもしろいダイレクトリクルーティングが減ってきているのでお待ちしております。

なお干し芋リストはありませんので、呑みにでも誘ってくださいませ!!!!!!

HHVM 4.50リリース!

HHVM 4.50

現地時間3/24に最新のHHVM4.50がリリースされました。
これに伴い4.44のサポートが停止に。
現在サポートされるバージョンはHHVM 4.45–4.49です。
なおLTSは4.8、4.32です。

$ hhvm --version

でHipHop VM 3系が表示される方はもうそのバージョンを使うのは辞めましょう。
かなり別物になっています。

変更点ハイライト

HHHVMのphp.iniに以下のものが追加されました。

hhvm.hack_arr_is_shape_tuple_notices

use function var_dump;

<<__EntryPoint>>
async function mainAsync(): Awaitable<void> {

  $dict = dict['a' => 'c'];
  var_dump($dict is shape());
}

今まではfalseが返却されていましたが、これを実行するとnoticeが発生する様になります。

Notice: Hack Array Compat: dict is shape in path/to/file.hack

もう一つは、Enumについて。
というかこの機能初めてしりました・・・

use function var_dump;

<<__EntryPoint>>
async function mainAsync(): Awaitable<void> {
  $l = new Latest();
  $l->builtinEnum();  
}

class Latest {
  protected vec<arraykey> $vec = vec[];
  public function builtinEnum(): void {
    $this->vec = vec[FOOBAR::BAZ];
    var_dump($this->vec);
  }
}

/* HH_FIXME[2053] */
class FOOBAR extends HH\BuiltinEnum<arraykey> {
  const BAZ = 4;
}

自分でEnumのクラスを作れたんですね・・・。
covariantになった様です。

Breaking Changes

PHPに詳しい方はよりPHPっぽさがなくなるように感じる変更がいくつか。

マジックメソッドの__get, __set, __isset, __unsetがTypecheckerから削除されました。
Typecheckerの特性を考えると当然かもしれません。
これらのマジックメソッドは将来ランタイムからも削除されるそうです。
つまり使えなくなります。

Future Changes

array() リテラルが削除されるそうです。
以前からHack Arrayにないもの(PHP array特有のもの)は削除します、とありましたので、
いよいよ削除されます。

hhvmのpjp.iniに hhvm.hack.lang.disable_array=trueを指定するか、
.hhconfigに disallow_array_literal=true でその挙動に変更できます。

したがって4.50で.hhconfigは以下のモノにしておくと良さそうです。

assume_php = false
enable_experimental_tc_features = no_fallback_in_namespaces
ignored_paths = [ "vendor/.+/tests/.+" ]
safe_array = true
safe_vector_array = true
disallow_assign_by_ref = true
unsafe_rx = false
disallow_array_literal=true

コードを記述してみましょう。

use function var_dump;

<<__EntryPoint>>
async function mainAsync(): Awaitable<void> {
  $l = new Latest();
  $l->disallowPHPArray();  
}

class Latest {

  public function disallowPHPArray(): void {
    var_dump(array(1 => 32));
  }
}

上記のコードを実行すると以下のエラーで実行できなくなります。

Naming[2083] Array literals are no longer legal; use varray or darray instead
   --> index.hack
 15 |     var_dump(array(1 => 32));
    |     

警告に出る様にarrayではなく、darray, varrayなどのHack Arrayにすると回避できます。

    var_dump(darray[1 => 32]);
    var_dump(dict[1 => 32]);

この場合、コレクション的な操作を行ったりするのでdictにするのが一番いいでしょう。

現場からは以上です。

腰椎椎間板ヘルニアで入院とヘルニコア

現在進行形で入院中です。

 

f:id:ytakezawa:20190622163108j:image

 

一昨年の年末にも椎間板ヘルニアで10日間程入院していましたが、

結果、今回は前回ヘルニアになった椎間板と別な椎間板でした。

坐骨神経痛は痛い

2019年4月頃から左のケツの下から  

太腿の横から前、

左のふくらはぎ、足首が痛み出し

前回の坐骨神経痛よりも痛くなる

ヘルニア持ちでない方はわからないかもしれませんが、

筋肉痛のちょっと質が違うやつがずっと続く感じ

 

そんななか

6月頭にデータセンターで物理層と闘いがあった。

(コレはまた今度どこかの機会で)

 

重いものは持っていないのに、

何故か翌日から歩くのも立つのも無理なくらい激痛に。

思えばこの時に救急車呼んでおけばよかった…が、

前回入院時に痛み止め服用しながら安静にしてたなと、

だがしかし一向に痛み引かずに1週間続く。

 

手すり等につかまりながら歩けるようになり、

日常生活を送るのに不自由ないというレベルではないけど少し回復。

 

前回入院時と違って痛みの引きが遅いと思い、

近所の総合病院に行こうと思っていたところ

車に乗ろうにも痛みがひどく、

動けない事から救急車で運ばれる事に。

 

搬送先に近所の総合病院を希望しましたが、

ベッド空きなし、ということで

前回と同じ総合病院へ

そしてそのまま入院となりました。

 

前回と違うヘルニア

入院後直ぐにMRI。

痛過ぎて20分耐えれるかどうか、自分自身との戦い

MRIの中でイテーイテー言ってましたw

 

結果、前回のヘルニアは靱帯を突き破ったもので、

痛いけど痛み止め飲みながら安静(保存療法)にしていると、

マクロファージ(白血球の一つ)がよしなに対応して回復するタイプでした。

 

が、今回は靱帯を突き破らないタイプのヘルニアで、

安静にしててもあまり良くならないタイプでした。

オブジェクト指向的にいうと開放/閉鎖原則に違反したもの

開放/閉鎖原則 - Wikipedia

 

リファクタリング不可!という事で、

手術しかないかも、という結果に

手術以外の選択肢

手術でもよかったんですが、

コレ以外に去年からできるようになった、

ヘルニコアっていう注射をやってみますか?

という話に。

https://www.seikagaku.co.jp/ja/news/news-8922458318854098739/main/0/link/20180731.pdf

 

靱帯を突き破っていないタイプしかできなく、

一度しか投与できないものだそうで、

コレでダメなら手術ですねぇ、というものですが

試しにやってみる事にしました。

 

椎間板への注射は痛い

手術室ではなく、レントゲン室というか、

CTを取りながら背骨の横のあたりから

長い注射針を刺して投与する様でした。

 

うつ伏せになり注射の対象箇所に

マーキングされていました。

この時うつ伏せで足を伸ばす為、坐骨神経痛が痛かった…

 

そして背中に局部麻酔の注射。

噂には聞いていたけど、奥に差し込んでいくほどに

痛くなり 思わずイタタタタと声が

注射等にはかなり強いタイプなんですが、痛かった。

その後ヘルニコアの注射を刺して対象の椎間板の髄核へ、

つまり椎間板の真ん中に到達する様に

CT取りながら徐々に針を入れていくわけですが、

麻酔は皮膚表面くらいにしか効かないため、

背骨付近にまで到達する頃にめちゃくちゃ重い痛み!!!!!!

 

予想していた痛みとベクトルが違う痛みに襲われ、

局部麻酔の注射よりも痛い!

 

ずっとイタタタタタ

全く我慢できない痛み、というわけではないんですが、

重い痛みが背骨、腰付近に発生し、

下半身は坐骨神経痛でひたすら痛い!

 

痛いしかありませんが、

投与後少しして針が抜かれ一安心。

その後ベッドに戻り横になり昼飯を完食。

投与後は安静以外特にないので、

全身麻酔の手術よりは体への負担がありません。

効果は個人差がありますが、

1-2週間後に効果が出始めて数ヶ月後に完治に向かっていくそうなので、

しばらくは通常の痛み止めを飲みながら安静にする予定です。

 

ヘルニコアはどこでもできるの?

実は全国どこでもできるわけではないようです。

ある程度の設備があるとかがあるようで、

救急車で希望した最初の搬送先ではできませんでした。

それどころか比較的近所の総合病院は全部ダメ!

エンジニアでヘルニア持ちは結構多いので、

手術ではなくて注射で済むかもしれない、

それを試してみよう!という方は

事前に調べるか、医師に相談してみましょう!

 

あとこのヘルニコア、結構高額なので

限度額適用認定証を忘れずに。

 

限度額適用認定証をご利用ください | お役立ち情報 | 全国健康保険協会

 

現場からは以上です。

HHVM/Hackの開発環境を用意してみよう!(HHVM4.0以降対応)

HHVM4.0以降?

f:id:ytakezawa:20190610021605p:plain

ご存知の通り、HHVM4.0以降PHPのコードを実行させることができなくなり、
HHVM/Hackの開発環境周りも大きく変化しています。

今回は最新のHHVM4.8(LTS) が動く環境をDockerで構築する方法を紹介します。

ネット上多くの記事はHHVM3系で、
しかも3.15などの古い記事が多く現在のバージョンとは大きく異なりますので、
注意してください。
現在はCentOSなどへのインストールはサポートされていません。
(CentOSベースで構築している記事は、ほとんどすべてが古いHHVM環境です)
AWSやオンプレ環境で構築する場合は、Ubuntu18.04などで構築してください。

Dockerで環境構築

今回紹介する環境はHHVM4.0以降のみ対応になっています。
せっかくなので新しいバージョンで構築しましょう。

fastcgi or proxygen

HHVMの動作方法として、fastcgiかproxygenを選択できます。
PHP-FPMと変わらないような使い勝手が良い場合は、fastcgiを利用すると良いですが、
HHVMで用意されている多くの機能が利用できません。

proxygenを利用すると、
NginxなどのWeb Serverを利用せずに、
Goなどと同じようにアプリケーションサーバライクにHackを実行することができます。

こちらを利用すると、HHVMのAdminサーバ機能や、
Hackのコードをコンパイルして動かすモードが利用できます。

フロントにNginxを配置してproxygenにupstreamするなども対応できます。

上記の違いを踏まえてHHVMで提供されているDockerコンテナも二種類あります。

hhvm/hhvmはUbuntuベースのコンテナで、
Nginxなどのコンテナを組み合わせて利用する場合はこちらを選択できます。

hhvm/hhvm-proxygen
NginxがなくてもWebアクセスで、Hackのコードが実行できますので、
特にWebサーバが必要なければこちらだけで環境構築が整います。

今回は、hhvm-proxygenを使って環境構築をしてみましょう。

Dockerfileでcomposerインストールを記述しておくと、スムーズです。

FROM hhvm/hhvm-proxygen:4.8-latest

RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive
RUN apt install -y dnsutils iputils-ping net-tools

RUN hhvm --version && php --version
RUN cd $(mktemp -d) \ 
 && curl https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN rm -rf /var/www

HHVMのphp.iniは下記の設定にしておきましょう。
hhvm-proxygenコンテナのデフォルトでは80ポートでアクセすると、
proxygenと通信することができるようになっていますが、
ポートを変えたい場合は、下記にある通り hhvm.server.port で変更します。

xdebug.enable = 1
date.timezone = Asia/Tokyo

hhvm.log.header = true
hhvm.debug.server_error_message = true
display_errors = On
html_errors = On
error_reporting = 22527

hhvm.server.fix_path_info = true
hhvm.server.type = proxygen
hhvm.server.port = 18080
hhvm.log.use_log_file = true
hhvm.server.source_root = /var/www/public

hhvm.php_file.extensions[hack]=1 
hhvm.jit=1

hhvm.server.default_document = "index.hack"
hhvm.server.error_document404 = "index.hack"
hhvm.server.utf8ize_replace = true
hhvm.log.file=stderr

hhvm.admin_server.port=19001
hhvm.admin_server.password=SomePassword

hhvm.admin_server.portはAdmin Server利用時のポートで、
hhvm.admin_server.passwordはAdmin Server利用時に必要なパスワードです。

それぞれ環境に合わせたものを設定します。

次にいくつかのミドルウェアを組み合わせてみる、などを行いたい場合は
docker-composeで利用できるようにしておくと良いでしょう。
下記はdocker-compose.yml例です。

version: '3'
services:
  hhvm:
    build:
      context: ./docker/hhvm
    volumes:
      - .:/var/www
      - ./docker/hhvm/hh.conf:/etc/hh.conf
      - ./docker/hhvm/php.ini:/etc/hhvm/php.ini
      - ./docker/hhvm/server.ini:/etc/hhvm/server.ini
    command: hhvm --mode server -vServer.AllowRunAsRoot=1
    restart: always
    tty: true
    container_name: hhvm
    ports:
      - 18080:18080
      - 19001:19001

docker-compose.ymlが置いてあるディレクトリを /var/www に配置し、
HHVMのphp.iniに hhvm.server.source_root/var/www/public にしていますので、
publicディレクトリにindex.hackファイルがあれば、
アプリケーションスクリプトのファイルとしてproxygenで実行されます。

HHVM4.0からは、Hackのファイルに .hack が利用できるようになり、
これまでの <?hh タグと続けて記述していた // strict と同じ厳格モードがデフォルトとなります。
.hack を利用する場合は、 <?hh タグは記載せずにソーソコードを記述しましょう。

これで開発・動作環境が整ったのでコンテナを起動することで、
Hackの開発環境が整います。

エディタ

Hackを開発する時のエディタは
現在Visual Studio Code + Hack Pluginの組み合わせがデファクトスタンダードです。

code.visualstudio.com

marketplace.visualstudio.com

HHVMにはLanguage Serverあり、この Hack for Visual Studio Codeと連携してサポートしてくれます。
PHPStormの様にuse文(import)を自動で書いてくれたり、などはありませんが、

コードジャンプは当然ながら、
引数のチェックやメソッド・関数のリファレンスなども当然あり、
コード補完やLintなども対応してくれます。

開発のためのLinterやCheck Styleなどのライブラリの使い方や、
実行方法がわからなくても代わりに実行してくれますので、
設定以外のタスクを記述したり、PHPDocを書いたり、
といった準備をすることはあまりありません。

HackではPHPDocを大量に記述せずとも、 静的言語のコンパイラなみの厳格さでコードを記述する必要がありますので、
PHPDocの書き方で補完のされ方が異なる、という事は一切ありません。

ライブラリ

とはいえエディタをフル活用するにはASTなどのライブラリを事前に入れておく必要がありますので、
下記のライブラリをcomposer.jsonに含めておきましょう。

HHVM-AutoloadとHack Standard Library(hsl)は、
ほとんど必須のライブラリと云ってもいいくらいものです。

オプショナルなものとして、下記のものも利用することが多いです。
hsl-experimentalは、将来的にhsl、またはHHVM本体で実装・追加予定のもの、
という立ち位置が強く、ファイルシステム・リソース操作などはhsl-experimentalにあります。

商用などでは利用せずに開発時に利用するものとしては以下のものが一般的です。

  • HackTest / A unit testing framework for Hack
  • FBExpect / A Hack library for writing unit tests expressively
  • HHAST / Mutable AST library for Hack with linting and code migrations

HackTestは、PHPサポートが切れる前にPHPUnitから移行ができる様に準備されていたもので、
FBExpectはアサーションなどが含まれます。
HackTestを使ってFBExpectでアサートをする、という組み合わせになります。
asyncでテストメソッドが実行されますので、
ひと昔前のHackUnitなどの利用は必要ありません。

HHASTはLinterなどの機能を提供しているもので、
Visual Studio Code + Hack Pluginと連携して利用できます(単体でも可)

Hack専用のhh_autoload.jsonなども事前に用意しておく必要があります。
2018年の情報ですが、
前提の知識として下記のものを読んでおくと良いでしょう。

qiita.com

Composer

ここまでのものを踏まえ、
開発初期時の composer.json は次のものを利用すると、
エディタとの組み合わせや、開発時に必要なテストライブラリなど一式が導入できます。

{
  "name": "vendor/your-project-name",
  "type": "library",
  "minimum-stability": "stable",
  "require": {
    "hhvm": "^4.0",
    "hhvm/hsl": "^4.0",
    "hhvm/hsl-experimental": "^4.0",
    "hhvm/hhvm-autoload": "^2.0.0",
    "facebook/hh-clilib": "^2.1.0"
  },
  "require-dev": {
    "hhvm/hacktest": "^1.5",
    "facebook/fbexpect": "^2.5.2",
    "hhvm/hhast": "^4.0.0"
  }
}

hhvm-autoload で利用する hh_autoload.json は次の通りです。

{
  "roots": [
    "src/"
  ],
  "devRoots": [
    "tests/"
  ]
}

次に hhvm/hhast で利用する hhast-lint.json です

{
  "roots": [
    "src/",
    "tests/"
  ],
  "builtinLinters": "all"
}

Hackを動かすために必要な .hhconfig ファイルは、
次の記述を記載しておくのが一般的かもしれません

assume_php = false
enable_experimental_tc_features = no_fallback_in_namespaces
ignored_paths = [ "vendor/.+/tests/.+" ]
safe_array = true
safe_vector_array = true
disallow_assign_by_ref = false
unsafe_rx = false

あとは $ composer install だけで
すぐに開発をはじめることができます。

エディタで補完されないな?という時に

エディタで補完が効かない、
タイプエラーで真っ赤なファイルがある、
という場合には、hh_clientを再起動してください。

再起動は次のコマンドで実行できます。

$ hh_client restart

Travisを使ってテストしたい

TravisCIを使って自動テストなどを実行したい場合は、
Travis上でDockerを利用すると様々なバージョンでテストできます。

ただし、TravisでもPHP実行環境のバージョン提供と同じ様にHHVMも多数のバージョンが用意されています。

コンテナ内でテスト実行などを行う様に下記のシェルスクリプトファイルを用意します。

#!/bin/bash
set -ex
apt update -y
DEBIAN_FRONTEND=noninteractive apt install -y php-cli zip unzip
hhvm --version
php --version

(
  cd $(mktemp -d)
  curl https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
)
composer install
hh_client

hhvm ./vendor/bin/hacktest.hack tests/

上記に合わせて.travis.ymlを次の通りにします。

sudo: required
language: generic
services:
- docker
env:
  matrix:
  - HHVM_VERSION=4.0.0
  - HHVM_VERSION=4.0.1
  - HHVM_VERSION=4.0.2
  - HHVM_VERSION=4.0.3
  - HHVM_VERSION=4.0.4
  - HHVM_VERSION=4.1.0
  - HHVM_VERSION=4.2.0
  - HHVM_VERSION=4.3.0
  - HHVM_VERSION=4.4.0
  - HHVM_VERSION=4.5.0
  - HHVM_VERSION=4.6.0
  - HHVM_VERSION=4.7.0
  - HHVM_VERSION=4.8.0
  - HHVM_VERSION=latest
install:
  - docker pull hhvm/hhvm:$HHVM_VERSION
script:
  - docker run --rm -w /var/source -v $(pwd):/var/source hhvm/hhvm:$HHVM_VERSION ./.travis.sh

例では4.0系以降のバージョンのみですが、
記載したHHVMバージョンのコンテナを起動してをテストなどを実行できますので、
柔軟に様々な要件に応えることができます。

これで最新のHHVM/Hackの開発環境を準備することができました。

これまでの、PHPがちょっと速く動く環境 という知識をアップデートして、
Hackにチャレンジしてみましょう!

事前準備が面倒な方は、下記のものを再利用すると良いでしょう。

github.com

Hack向けDIコンテナライブラリその2 公開

DI Container For HHVM/Hack

だいぶ前に作った軽量なものから、
HackのDIコンテナ向けインターフェース hack-interface-standards/container に準拠し、
HHVM4.0以降に対応しました。

github.com

下記のDIライブラリを意識していますが、作っていくと少しずつ変わっていきました。

github.com

利用方法を紹介します。

installation

インストール方法は、Composer経由で利用できます。
HHVM4.2+composer 1.8.5の組み合わせでもインストールできますので、
まだ安心してComposerを利用できます。

実際に利用する場合は、hhvm/hhvm-autoload 等も必要になりますので、
Composer経由でインストールします。

composer.jsonは下記のもので試しに動かすことができます。

{
  "name": "acme/testing",
  "minimum-stability": "stable",
  "require": {
    "hhvm": "^4.0",
    "hhvm/hhvm-autoload": "^2.0.0",
    "nazg/glue": "^1.1.2"
  }
}

HHVM/Hackのクラスマップ等はcomposer.jsonに記述しなくても、
hhvm-autoloadで吸収できますので、 hh_autoload.json を下記の通りに記述します。

{
  "roots": [
    "src/"
  ]
}

簡単な使い方

シンプルなクラスのインスタンス生成を登録します。
下記のクラスを、src/A.hack ファイルに記述します。
.hackはHHVM4.0から利用できるようになった、デフォルトで厳格モードになる拡張子です

final class A {
}

このクラスをコンテナに登録例として
src/main.hackファイルを作成してそのまま記述します。

require_once __DIR__ . '/../vendor/hh_autoload.php';

<<__EntryPoint>>
function main(): void {
  $t1 = microtime(true);
  $builder = new Nazg\Glue\ContainerBuilder();
  $container = $builder->make();
  $container->bind(A::class)
    ->to(A::class)
    ->in(Nazg\Glue\Scope::PROTOTYPE);
  $container->get(A::class);
}

上記の記述は、コンストラクタにAクラスがあれば(bind)、
Aクラスのインスタンスをそのまま渡す(to)指定で、
インスタンスは、都度インスタンス生成を行います(Nazg\Glue\Scope::PROTOTYPE enum)。
生成されたインスタンスはPSR-7と同様にgetメソッドで取得します。

enum Nazg\Glue\Scope

インスタンス生成は、enumで下記の二種が利用できます。

enum スコープ
Nazg\Glue\PROTOTYPE 都度インスタンス生成を行う
Nazg\Glue\SINGLETON 一度だけインスタンスを生成し、以降はそれを利用します

インターフェースを利用する場合

PHPの一般的なDIコンテナと同じように利用できます。

interface AInterface {
}

class A implements AInterface{
}

上記のインターフェースとクラスは、次の通りに記述してインスタンスを取得できます。

require_once __DIR__ . '/../vendor/hh_autoload.php';

<<__EntryPoint>>
function main(): void {
  $builder = new Nazg\Glue\ContainerBuilder();
  $container = $builder->make();
  $container->bind(AInterface::class)
    ->to(A::class)
    ->in(Nazg\Glue\Scope::PROTOTYPE);

  var_dump($container->get(AInterface::class));
}

bindメソッドでAInterface::class を指定し、 getメソッドでbindメソッド名を指定するだけです。

実装の裏側

getメソッドやbindメソッドなどは存在するクラス名のみを指定できます。

下記はbindメソッドのコードですが、
typename<T>を利用しこれ以外の型は利用できません。
したがってPHPライブラリなどである任意のサービス名などを使うことはできません。

  public function bind<T>(
    typename<T> $id
  ): Bind<T> {
    return new Bind($this, $id, $this->factory);
  }

依存解決

下記の場合はどうすればいいのでしょうか?

interface AInterface {
}

class A implements AInterface{
}

class B {
  public function __construct(
    public AInterface $a
  ) {}
}

複数のクラスを組み合わせる場合、
特殊なものがなければ次の記述で解決できます。

require_once __DIR__ . '/../vendor/hh_autoload.php';

<<__EntryPoint>>
function main(): void {

  $builder = new Nazg\Glue\ContainerBuilder();
  $container = $builder->make();

  $container->bind(B::class)
    ->to(B::class)
    ->in(Nazg\Glue\Scope::PROTOTYPE);
  $container->bind(AInterface::class)
    ->to(A::class)
    ->in(Nazg\Glue\Scope::PROTOTYPE);
  var_dump($container->get(B::class));
}

簡単ですね。

Provider

上記の依存解決方法では解決できないものは、
Providerインターフェースを使って依存解決を記述できます。
先ほどの例をそのまま使います。

interface AInterface {
}

class A implements AInterface{
}

class B {
  public function __construct(
    public AInterface $a
  ) {}
}

Providerインターフェースを使う場合は次の通りです。

class BProvider implements Nazg\Glue\ProviderInterface<B> {

  public function get(
    \Nazg\Glue\Container $container
  ): B {
    return new B(new A());
  }
}

Nazg\Glue\ProviderInterfaceにジェネリクスでB、
getメソッドで返却される型はジェネリクスに記述したクラスと同じ型を指定します。

Providerインターフェースを実装したクラスをコンテナに登録しなければ利用できないため、
下記の記述で登録します。

require_once __DIR__ . '/../vendor/hh_autoload.php';

<<__EntryPoint>>
function main(): void {

  $builder = new Nazg\Glue\ContainerBuilder();
  $container = $builder->make();
  $container->bind(B::class)
    ->provider(new BProvider())
    ->in(Nazg\Glue\Scope::PROTOTYPE);
  var_dump($container->get(B::class));
}

上記の登録方法を利用することで様々なインスタンス生成を行うことができます。

他にもいくつかありますが、
開発時に利用することがあれば是非色々試してみてください。