Splatoon2 感想

前作ギリギリS+、今作150時間ぐらい。今Sでうろうろしてるプレーヤーなのでガチ勢ではない。一緒にやってる人達がS+ばかりなので、足を引っ張らない程度になろうと、ヒーヒー言いながらやってる。

前作は、ダイナモハコフグヒラメエリアだけで厳選でS+に上げたので、実質S適正ぐらいだったと思う。自分には入力精度と視野と決め打ちな戦術プランが不足している、という自覚があり、それらは経験で補わないといけないが、それらを得るための体力と時間を捻出しないといけないのが難しい。

この記事で、あれこれ文句言ってるが、面白いからこそ出る不満であって、アプデに期待している。展望として、2年ぐらいは飽きずに遊ばせてくれという感じ。あと自分の意見じゃなくて、自分よりうまいS+環境の人達の意見を鵜呑みにしている部分もある。

インフレ抑止 & 前作トップメタへの懲罰的なナーフ

前提として、前作でインフレしきった状態をリセットしようとして各メインは慎重に調整されているが、スペシャルは全リセットした結果大暴れみたいな状況になってる。環境としては前作で一通りゲームとしての研究は終わっているので、新要素もそれらの差分として、研究される速度が早い。

新環境で様子をみたいのか、マニューバ以外の新武器がどれもこれも酷い。ソイチューバーもクラブラもヴァリアブルローラーも調整諦めてトップの環境に影響が出ない程度に放り出した感が強い。ワクワク感を返せという気持ちになった。シェルターも結構遊んだけど、面白いけど強くはないよね、チーム戦でワンチャンあるかもね、で落ち着きそう。

引き続き前作から言えることだが、キッズ向けの調整と、ガチ勢向けの調整を同時にしようとした結果、どっちも噛み合ってなくて、全体的にギクシャクしている。少なくとも初出のPVでやってたような、プロゲーマー向けな環境は、それに耐えうる深みを持てるか怪しい。ブキの強弱がハッキリしてて、自分だけの強みを作るといったプレー体験の幅広さは現時点で実現できない。

前作の強武器は、まずダイナモがとてつもなく弱くなった。前線張ってたシールドシューターがいなくなった。前作はダイナモと52ガロン使いだったので、今作は新しいブキを探さないといけなくなった。

ガバエイム勢のオトモは、ダイナモに代わってヒッセンになった。ヒッセンがここまで強くなるとは思わなかった。手元の判定の大雑把さで打ち勝つのは格ゲー初心者のレバガチャ感ある。明日にでもナーフされそう。

ラピブラはそんなに変わってないはずだがステージ構成のチャーポジを狩るメタで噛み合って強武器になってる。

スシはスシ

スペシャ

全体的に、無敵系がなくなって、防衛側が弱く、攻撃側の打開が成功しやすくなった。これはスリリングなので良い調整だと思う。が…

なにはともあれ、ジェットパックが強すぎる。もはやジェットパックが上手いやつがいるチームが勝つ、という感覚がある。上手い人は1回で平気で2~3キルもっていく。塗りまくってジェットパックを撃つだけのギア構成のマニュコラが強すぎる。

次いでインクアーマーが強い。30ダメのバリアと解除時に数フレームの無敵時間。バリア剥げるときの超過分のダメージは捨てられてるので、とくにチャージャーを無視できるし、大雑把に打ち合いに持ち込んでも互角なら2-1交換まで持っていけてしまう。あとただでさえ強いジェットパックを守ることが出来るのも強い。

今の環境なら、スペシャルだけで選ぶならジェットパック3にバリア1が一番強いと思う。

ハイパープレッサーは研究が進んでないから弱いという余地もあるかもしれないが、それにしても、使うとメインが打てなくなる棺桶で、もはや「使うべきではない」というところまである。これがダイナモについてるのは前作で暴れた懲罰、という意図すら感じる。現状バレルが少ないのも、弾速が下がったのもあるが、プレッサーのせいもある。

仲間内では、ハイパープレッサーより、使うとインクが回復するだけの「無」の方が強いのではないか、みたいな話すらある。

チャクチは取り回しはいいけど打開能力はないので、劣勢時の打開が鍵のゲームでアドになりにくい。前作と違ってマップが見づらいので、本来想定されてるであろう、味方との連携で決めるのはこのスピード感での難度が高すぎる。野良だとボイチャもないし…。

スフィア、仲間が追われてるのを見かけてもほとんど戦局に影響しないので無視している。使ってる間に弾が撃てないディスアドすらある。

アメフラシはよくわかんないけど乱戦時に強いが適切に展開しないと腐る。

要約するとジェットパックが強すぎる。絶対にナーフされると思う。どうナーフしても強そう。

ローラーについて

前からローラー好きだったんだけど、スプラローラー属は相変わらずナーフされたままで、当たり判定が狭すぎてそれが勝敗に響くシーンが多すぎる。縦振りは中距離戦に乱入できるが、上位勢のスピード感に付いてきそうにない。

ローラーとカーリングとの相性がよく、とくにホッケはカーリングまみれになる。ただ、ボールドマーカーが上位互換な感じになってしまっている。段差はローラーのが強いが…。ロラコラはビーコンの研究が進んでないのとイカスフィアが弱いので選ぶ理由がない。

ダイナモは塗れなくなってなんとも言えない弱ブキになった。上に向かって振ると蒸発するってのなんなんだ。前作はメイン効率ガン積みで塗りまくってたようなプレーヤーなので、似たようなものがない。

マップ

相手側への進入不可エリアが増えて、打開で使ってね、という意図が強い。

タチウオはクソ。

ギア

攻撃、防御が消えてメタりあいが消えたのは、他で差別化する要素が増えて良い調整だと思う。

スペシャルのスパセン消えたのにマキガのブランドが増えているのは完全に意味不明。ポイセンは弱くはないがスロット使ってまで対策するものではない。

ゲソタウンはイカリング2を使うインセンティブにしたいんだろうけど、イカ速クラーゲスとか爆風防御シグレニとか純ブランドで19揃うものがあって、情報アドでガチ勢とそうじゃない人にギアで差がついてしまうの、あんまりよくない気がしている。自分は使うけど。

最後に

身内でDiscordのボイチャしながらワイワイするのが楽しすぎて、それだけで楽しすぎて全部吹き飛んで楽しいみたいなのが唯一無二みたいなのがあり、やっぱスプラトゥーンはこれだよなという感じがあり、でもその体験が長く続くような調整を任天堂ができるかなぁ、と思うと結構不安という感じ。

オープンワールドRPGに馴れた自分にとってゼルダが物足りなかった点

前提

面白いのは間違いないし、Switchのスタートダッシュに大きく寄与していて、自分も90/100あげたいゲームで、この路線で次の作品もやってほしい、が、現時点で不満に思う点も多く、またネットでも絶賛ばかりで気持ち悪いので、思うところを書いておく。

自分は比較的、他のオープンワールドゲームに慣れてる方だと思う。ゼルダの比較対象は Skyrim, Fallout4, Witcher3、ゼノブレイドゼノブレイドクロス。ただこれ以外にもRPGやりすぎていて、趣味がこじれている自覚はしている。

文句言ってるから面白くないというわけではなく、単に Not for me という意味合いが強い。

難易度曲線が緩やかで上限も低い

RTAや一部の縛りプレーを除いて考えると、順繰りにいってデスマウンテンあたりで難易度が頭打ちで、以降ダレがち。

メインシナリオから外れれば上位のライネルもいるが、それはエンドコンテンツの一部であって想定された難易度の外の話だし、ゲーム本編であまり使わないスキルに慣れれば勝てる敵で、やや浮いたコンテンツになっている。

とはいえ、過去作のゼルダもこのような難易度曲線だったような感覚はあるが、30時間のサイクルでやることを、80時間でやると、30時間ぐらいでダレて刺激がほしくなってくる。

収集要素によるインセンティブが(他のオープンワールドRPGに比べて)とても弱い

防具を鍛える要素と、その素材を集める部分。そこが主な収集要素。

武器も結局、攻撃力に速度かけたDPSとして見る程度。現地徴収でローグライク感を出したかったんだろうが、正直武器を失うストレスのが上回っていて、また、武器を集めたり育てたりするシステムを導入した際にどういう楽しみのバリエーションを導入できるか考えると、あまり上手くいったシステムに見えない。プレーヤー側のインフレを抑えたい意図はわかる。

それらの成長システムを意図的に省いた結果か、クエストの報酬がとてもしょぼく、クエストにモチベートされない。ゼルダ的ミニマルさが、クエスト報酬でプレイヤーを引っ張るオープンワールドRPGの文脈とあまり合致しなかったように思える。

もちろん、そういうRPGを要素を強くすると離れるプレーヤーがいるのもわかるが、それはRPGとしての部分が、リニアに設計されたわかりやすさの結果だとも想像できる。

風景が変わり映えしない

そりゃもちろん、初見でワクワクしたし、動線がうまく設計されてるのはすごいと思う。とくにハテノ村から北側に山越えて、ゾーラの湿地を見下ろしたところは最高だった。

でも、なんというか途中からドンドン見慣れて予想したものしかなくなってくる。

たとえばゼノブレイド(クロス)だとランドマークっていう地形ごとに特殊なオブジェクトがワープポイントになるわけだけど、祠がワープポイントになってしまったせいで、祠の見た目が期待を裏切らないせいで、風景が単調になってしまった。祠と塔を探すゲームになってしまったのは、わかりやすくもあり、探検の物足りなさでもあると思う。

開発がゼノブレイドクロスと同世代で、モノリスの技術協力を受けていて(CEDECのセッション、会場でみてました)、ゼノブレイドクロスの絵作りの異様なバリエーションの幅(とそれに意味が付随しないことへの虚無が問題なのだが…)と比較すると、丁寧に作った結果、おとなしくまとまってしまった、という感想を受ける。

ダンジョン、というか洞窟に潜って倒してお宝を持ち帰る、といったシチュエーションが少ないのも、自分はそういうのが好きなので、つまらなく感じた点ではあった。ハイラル城地下坑道やマップ上で発生する一部の試練ぐらいしかそういう場所がない。というか武器を拾っても何も嬉しくないのが問題だと思う。

敵の種類も、敵がいる地形のバリエーションも少なく、あまり攻め甲斐がない。というか敵が弱くてあんまり考えなくてもどうとでもなってしまうのが本当に残念。

祠もつまらないのが多かった。というかそもそも初期に開放されるシーカーストーンのギミックにあまり発展性がなかったと思う。祠=ワープポイントで108個置く、というプランがそもそもいい設計ではないように思える。

ギミックを序盤で全部開放することの良かった点として、〜するには〜を手に入れてから〜というのがなかったのは本当に良かったし、他のゲームもそうしてほしい。

今後

文句行ったけど最初の30時間は本当に楽しかったので、次のDLCと次回作に期待しています。

再プレー時は5時間でデスマウンテンの神獣までクリアして飽きてしまった。6/30の難易度パッチあててから続きをやるか考える。

日記

先月末、右下の親知らずの抜歯に挑戦したが、麻酔が効かず、歯を1/4ほど砕いた状態で中止するという出来事があった。麻酔きかないのに何度もドリル当てられて「ヤバイっす、マジでヤバイっす」と言って止める、を繰り返して、最悪の体験だった。今もまだ痛い。

もう一方、個人的に精神的に参るイベントも発生しており、その心労、抜歯失敗とその後の縫合による肉体的消耗、元々やってたダイエットと抜歯縫合後の食が進まないのが重なった結果、ここ2ヶ月で体重が 3.5kg 落ちて、63.5kg。減ったのはいいのだが、この落ち方は、あまり本意ではない。

仕事は順調だけど、フリーランス的な辛さというものもわかってきて、自分は、どうなると胃が痛くなるかがわかった。まあこれに関しては乗り越えられそうではあるのだが、フリーランス心理的安全性を考慮しながら動く必要があると感じた。

頑張っていきましょう

GWの進捗としてRPG作った / redux-saga でメインループ処理、JSONSchemaからのコード生成

作った。GWの間、コンビニと近所のカフェ以外に外出してないし、ゲームもしてない。

https://mizchi-sandbox.github.io/rpg-prototype/ で触れる。デザインはしょぼい。Chrome以外で動いてる気がしない。

コードはここ https://github.com/mizchi-sandbox/rpg-prototype

仮素材はウディタに付いてくるサンプル素材をお借りした。

WOLF RPGエディター公式サイト 【RPG作成フリーソフト】

仕様

  • Spaceでポーズ&リスタート
  • クリックでスキルの使用
  • 一度スキルを使ったらクールダウンがある
  • Player1 だけ操作できる

あとはなんか察してほしい。

何故作ったか

前々から、ゲーム、とくにRPGを作りたいと思ってたのだけど、メインループがすんなり綺麗にかけたためしがない。趣味プロジェクトは技術的に辛いとやる気が無くなる。

ゲーム作りたい人は、そこを気合で乗り越えるんだろうけど、そこに関しては自分はエンジニア気質なのが勝つので、自分が納得できるまで綺麗なアーキテクチャが実現できるまで、なんども試作していて、今回やっと納得できそうなコードが書けた。

あと http://anond.hatelabo.jp/20170507200847 みたいなこと言われて、いや、揶揄じゃなくて、別にそう見えるのは仕方ないよなと思いつつ、いずれ金にしたいという思いはありつつも成果はある程度まで公開しとこうと思った。

技術

主な構成要素は flow/react/react-redux/redux-saga。 まず一番難しいであろう、戦闘画面だけ作った。

Immutable

コード、汚くはないつもりだが、かなり手癖が強い。頭のなかにある将来的な仕様も同時に作ってるので、デッドコードもたくさんある。テストもコメントも足りない。プロトタイピングなので、こんなもんで許して。コミットログは最悪。

特徴があるとすると、一部を除いて、オブジェクトへの副作用絶対ほぼ禁止、というルールで書いた。

たとえば入力されたコマンドを実行しながら、Resultの配列を作る処理はこうなってる。

export function processCommandPhase(
  state: BattleState,
  commandQueue: Command[]
): CommandApplicationProgress {
  return commandQueue.reduce(
    (next: CommandApplicationProgress, nextCmd: Command) => {
      const { state: nextState, results } = nextCmd(next.state)
      return {
        state: nextState,
        results: next.results.concat(results)
      }
    },
    { state, results: [] }
  )
}

また、 https://github.com/peterkhayes/eslint-plugin-mutation というルールを導入した。

やってみると、ほぼすべてImmutableにしたことで、コードの予測のしづらさがなくなり、心理的な安心が得られた。ただ、コードを書く量はどうしても増える。四則演算ごとに計算関数生やさないといけないから当然っちゃ当然だが。

このスタイル、おそらく盛大にメモリを使うと予想していたが、メモリプロファイラを見てもそこまで漏れてる様子がない。

GC負荷はそれなりにかかってそうなので、あとで調べる。

redux-saga でメインループ制御

1フレームの処理はこんな感じになる。

  • 入力処理
  • コマンド生成
  • コマンド処理
  • コマンド結果をビューに送信

で、二種類実装してみた。一つは某F○っぽく、常に時間が経過するアクティブなやつで、もう一つは入力可能なコマンドがあると一旦処理を止めて、入力があると再開する。

これを表現するために、 battleSaga.js というエモい名前で次のような処理を書いている。

let waitMode = false
function* start(_action: any) {
  // Use wait mode
  waitMode = location.search.indexOf('wait') > -1

  let state: BattleState = createBattleMock()

  // Sync first
  yield put(sync(state))

  // Start loop
  while (true) {
    // InputQueue buffer
    let takenInputQueue: Input[] = []

    // WaitMode: check executableSkill
    if (waitMode) {
      // Wait input on wait mode
      const executableSkill = findActiveSkill(state.battlers)
      if (executableSkill) {
        yield put(sync(state))
        yield put(battleActions.paused())
        const takenInputAction: { payload: Input } = yield take(
          battleActions.ADD_INPUT_TO_QUEUE
        )
        takenInputQueue = [takenInputAction.payload]
        yield put(battleActions.restarted())
        yield call(delay, 100)
      }
    }

    // ActiveMode: wait interval or intercept by pause request
    if (!waitMode) {
      const { paused } = yield race({
        waited: call(delay, 300),
        paused: take(battleActions.REQUEST_PAUSE)
      })
      // if user request pausing, wait for restart
      if (paused) {
        yield put(battleActions.paused())
        yield take(battleActions.REQUEST_RESTART)
        yield put(battleActions.restarted())
      }
      // Get input
      takenInputQueue = hydrateInputQueue()
      yield put(battleActions.updateInputQueue([]))
    }

    // Update state
    const processed = processTurn(state, takenInputQueue)
    state = processed.state
    for (const result of processed.results) {
      switch (result.type) {
        case ResultActions.LOG:
          yield put(battleActions.log(result.message))
          if (waitMode) {
            yield put(sync(state))
            yield call(delay, 100)
          }
          break
      }
    }

    // Check finished flag
    const finshed = isFinished(state)
    if (finshed) {
      yield put(sync(state))
      // yield put(battleActions.log(`${finshed.winner} win.`))
      yield put(battleActions.openResult(`${finshed.winner} win.`))
      break
    }

    // Sync state by each frame on active
    if (!waitMode) {
      yield put(sync(state))
    }

    // Clear inputQueue
    takenInputQueue = []
  }
}

generator関数の無限ループでyieldして一個ずつイベントを処理する。

put がビューへの dispatch, take が イベント待ちだと思えばよい。call は非同期関数呼び出し。

たぶん制御フロー的に面白いのはここ。

      const { paused } = yield race({
        waited: call(delay, 300),
        paused: take(battleActions.REQUEST_PAUSE)
      })
      // if user request pausing, wait for restart
      if (paused) {
        yield put(battleActions.paused())
        yield take(battleActions.REQUEST_RESTART)
        yield put(battleActions.restarted())
      }

saga の race コマンドで、「300ms 待つ」もしくは「ポーズ命令を受け取る」の速い方で処理を進めて、もしポーズ命令だったなら、リスタート命令が来るまで待機する。

saga、やってる処理が非常にRx的だが、このストップ&リスタートをRxで自然に書ける気がしない。いや、単に自分がRx詳しくないだけかもだが。

また、これをReducerからsaga側にゲームロジックの更新を全部追い出したことで、実際に副作用を起こす場所を、サーバー側に持っていけそう。オーバーエンジニアリングの成果だ。

ゲームの内部状態をビューに伝える箇所がここ。

    // Update state
    const processed = processTurn(state, takenInputQueue)
    state = processed.state
    for (const result of processed.results) {
      switch (result.type) {
        case ResultActions.LOG:
          yield put(battleActions.log(result.message))
          if (waitMode) {
            yield put(sync(state))
            yield call(delay, 100)
          }
          break
      }
    }

今はちょっと時間がなくて、LOG イベントしか実装してないんだけど、ここでアニメーションの再生命令などを書くと、ステップ処理をシュッと綺麗に書けそう。

JSONSchemaでコード生成

昔ポシャったやつから借りてきた。ので、ほとんど使われてないが…

masterdata/
├── data
│   ├── consume-item-data.yml
│   ├── dungeon-data.yml
│   ├── equip-data.yml
│   ├── job-data.yml
│   ├── material-data.yml
│   ├── monster-data.yml
│   ├── race-data.yml
│   ├── skill-data.yml
│   └── troop-data.yml
└── schema
    ├── consume-item-schema.yml
    ├── dungeon-schema.yml
    ├── job-schema.yml
    ├── material-schema.yml
    ├── monster-schema.yml
    ├── race-schema.yml
    ├── skill-schema.yml
    └── troop-schema.yml

2 directories, 17 files

script/gen-code.js が、こんな感じのコードを生成する。

/* @flow */
/* eslint-disable */
import data from './data'

// === ConsumeItem ===
export type ConsumeItemId = '$life-herb'
export type ConsumeItemData = {
  id: string;
  displayName: string;
  stackable?: boolean;
};
export function loadConsumeItemData(id: ConsumeItemId): ConsumeItemData  { return data['consume-item'].find(i => i.id === id) }

// === Job ===
export type JobId = '$warrior' | '$mage' | '$rogue' | '$novice'
export type JobData = {
  id: string;
  displayName: string;
  life: string;
  mana: string;
};
export function loadJobData(id: JobId): JobData  { return data['job'].find(i => i.id === id) }
// ... 略

データ自体は仮なので、とくに意味はない。生成できてるというのが大事。

Storybook

試してみたら結構良かった。 なんとなくアトミックデザインっぽい分割をしてみている。

反省

仕事で使うReact/Reduxの知見を深める目的もあった。redux-sagaは元々半信半疑で、今回はユースケースに合うので使ってみたんだけど、大抵のケースではオーバーキルな気はする。ただ、今回はこれが生命線っていえるぐらいMVP。

前回の試作(1年半ぐらい前だったと思う。公開してない)と比較して、RPGツクールMVのエンジン部分のコードと、Game Programming Patterns を読んだ経験が生きた。

このGame Programming Patterns って本すごくよくて、ゲームの本というよりは、ゲームの視点でGoFデザパタを再考する、という感じで読むと、すごくいい。この手の本は筆者の視点がC++に偏ってることが多いが、関数型も動的型付の言語で実装する際のことも言及されていて、とてもバランスがよく、読みながら納得しかない。SPAのアーキテクチャGUIにとても近いので、実際に参考にできる技術も多い。

今後

  • マスターデータ増やす
  • 戦闘以外の画面を増やす
  • セーブデータの永続化層を作る
  • react-native に突っ込む

現状、まだ動くことがわかっただけで、ゲーム性と呼べるものが発生してない。

自分的には設計に納得したので、もう少し作り続けられそう。頑張る。

いかにしてJavaScriptを教えるか

経緯

ドワンゴ様から恵贈頂いた。

高校生からはじめる プログラミング

高校生からはじめる プログラミング

…読んでみたけど、HTML/CSS/JS の初歩的な部分を、初学者にやらせるとこうなる、という素朴な世界観で、CSSフレームワークもJSライブラリも出てこない。いや、出せと言ってるわけじゃない。理解せずにフレームワークを使う習慣がつくと、スクリプトキディ的な振る舞いによっていくし、教える側としても、変数が大きくなってコントロールできないのが問題だろう。

じゃあ基礎を抑えたとして、この先どう教えるといいんだろうな、というのは、たしかに自分も前から考えてはいて、それを書いてみる。

この文章のターゲット

JavaScriptを教える人、またはポインタがあれば自学できる中級者以上

追記: すべての初学者にJSを教えろという内容じゃなくて、ある程度コンテキストあってJSを学ぶ人がどういう経路で学ぶべきかというものを書いたつもりだけど、自分がマウントして気持ちよくなりたいがために意図してそこ無視してる人が多くて怒っています

提案: 初心者にNode.jsから教える

理由はいくつかある。

  • ES2015のES Module 以外はだいたい実装された環境
  • パッケージマネージャが最初から付いている
  • REPLが付いている
  • パッケージマネージャによってモジュールを分割する慣習が得られる
  • Node.jsツールチェインに抵抗がなくなる
  • サーバーエンジニアにもクライアントエンジニアにもモバイルにも派生できる
  • レガシーな jQuery 方面の慣習に引きずられていない

ただ、黒い画面に抵抗があったり、画面をゴリゴリ動かすのに最初から行きたい人は、Nodeから入るとモチベーションが削がれるかもしれない。そういう人には create-react-app から入って、しばらくそれ縛りでReactアプリを触らせるのがいいと思う。結局、そうやってると、これもあとからNodeツールチェインの理解が必要になる。段階的に、Babel、Webpackと触ることになるだろう。

TypeScriptとAngularは、最初からそれを使ってる会社での研修ではない限り、学習用途にはあまり勧めない。AngularはAngularの世界観が強くて、おそらくJSのルールなのかAngularなのかの区別がつかないし、TSも同じ。TSの慣習は、JSの雰囲気とやや距離がある。TSをやるのはJSやってからで遅くはない。

学習段階のブロッキング要素

  • 後方互換を切ることができずに残っている構文上のBadParts郡
  • 過去に書かれたES2015以前のドキュメント
  • 全体的にテストを書く強制力が弱く身につかない
  • プロジェクトごとにフレームワークが違う

テスト、まともなエンジニアなら、これだからJSは!と憤りがちなのは知ってるんだけど、GUI環境はそもそもテスト書く難易度が異常に高く、Unityなんかのゲームエンジン方面も同じ問題を抱えている。書けるけど難しい。TS/Flowを使って、型で強く固めるのも、結局テストを書かずにある程度カバーしたいという需要から来ている。

とはいえ、テストのターゲットがピュアなJSオブジェクトのうちはテストを書けるし、環境依存のDOMやその他のオブジェクトを、ピュアな部分から切り離す慣習を持つようにするのが、Nodeを使うと自然に身につく習慣なので、そこを頑張るように仕向けたい。これもNodeを勧めてる理由の一つ。

補足: サーバーエンジニアとしてのJavaScript

USだとそうでもないのだが、Node.jsを国内で運用してる会社が少ない。その為運用経験が足りなくて、採用されづらい。Nodeを使うような会社だったらRubyを使うだろう。とはいえ、npm の慣習は基本的に、rubygems の模倣だったので、LLでOSSのモジュールを組み合わせて、という体験が得られるので、学習段階の言語としては無駄にはならない。もちろんクライアントにも経験は生きる。

プログラミング言語としての JavaScript をどう捉えるか

雑に書くのは簡単だが、真っ当に運用しようとすると突然難しくなる。知識があれば、何を使っていいか、何を使っていけないかわかるが、それが身につくのは泥臭い経験の先である。ベストプラクティスは常に更新されていて、参考にして良い資料はここ3年に書かれたものに限る。

メインストリームは主に Babel/TypeScript だが、Babel も Flow が使われるようになってきているし、全体としては型ありきの固い環境を志向している。ただ、OOP周りでは、クラス記法は入ったが、あまり使われようとする気配はなく、Record + Pure Function による関数型的な方向性に寄っている雰囲気が強い。ライブラリが提供するAPIなどにその傾向が見られる。これは、JSが主に通信で使われていて、シリアライズ/デシリアライズを頻繁に行うためだと自分は考えている。

言語として物足りなくなった場合、Flowで型を拡張したり、Babelの構文を足したり、Lintツールで全く違う言語のような縛りにして遊ぶことが出来るので、長期的に物足りないということはないだろう。もうちょっとしたらWASMも来るし、そこからぜんぜん違う方面へ脱出できる環境を、これから自分は頑張りたい。

JavaScriptに投資して幸せになれるか

昔は片手間専用だったけど、今はこれ一本で一通りのことができるようになってはいる。ただ、フロントエンド以外で品質が高くなるかは、それ専用のプラットフォームに劣る。劣った分を技術で取り返したい場合、できなくはないが、そこそこのコストがかかる。

プログラミング初学者は、最初に見た言語を親だと思ってついていく習性がある。今のJavaScriptは、そこから脱出するきっかけを提供してくれない。これは勿論悪い意味で。

僕は雑に使える言語が、JSの他には RubyPythonScala という感じだが、やはりJSでなんでもなぎ倒してしまえるので、あまり触ることがない。よくないと思う。

とはいえ、目先の問題を解決するには良い言語だと思っているし、勉強した分の見返りはある。今一番プログラマの大統一言語に近いのは、「残念ながら」、JavaScriptだと思う。ここの「残念」のニュアンスは汲み取ってほしい。僕はそもそもJSという言語はそこまで好きではない。

あわせてよみたい / tagomoris.hatenablog.com

29歳の世界観

29歳になった。連休誕生日組はこうやってアピールしないと全く祝ってもらえないので…

例のリストです。

http://amzn.asia/3HzTsJb

去年からの変化

体は資本

20代のうちは大丈夫だろと高をくくっていたが、僕は作業時の姿勢が悪くて、首、肩、腰が悪くしがちだった。結局27歳ぐらいから肩こり、首の痛さ、腰の痛さで集中力を乱されることが多くなり、改善を決意した。

ダイエットはその一環で、糖質制限で14kg痩せたことで、腰への負担はかなり改善し、腰痛が減った。

肩は、周辺の筋肉を付けて改善しようと思い、今トレーニングの数をかなり増やしている。

首は未だに悪く、手足のしびれ、呼吸の辛さなど、頚椎ヘルニアのような症状が出ることがある。懸垂バーを買った。

Twitter

Twitter始めたのが20歳になる直前だったので、人生の1/3程度Twitterしてることになる。もはや生活の一部になってるので、Twitterをしてるという感覚すらない。

世代的な話

結婚しそうな人はだいたい結婚してしまった。早い人は第二子とか家建てたとかそういう話をしている。

自分がそれらに全く興味がない、わけじゃないけど、趣味に生きるタイプだし、それを他人と共有しなくても平気で、そもそも他人にあまり興味がなく、誰かと生きることをあまり学ばずに大人になってしまったので、そういうこと人並みにやろうとしてもうまくいきそうにない、という感覚だけがある。経験がないわけじゃないけど、無理にやろうとすると、自分が飽きるだろう。相手に失礼だと思う。

とはいえあと数年がまともにそういうチャレンジできる数年だし、ちょっとした葛藤はある。とはいえ、たとえば結婚したいというモチベーションのほとんどが、祖母を安心させたい、というところに尽きるので、いやーそんな気持ちで婚活しても相手に失礼では?という…

genba.fm

https://genba.fm/

まだ 第0回しかやってないのだが、第0回、好評で嬉しかった。音質が悪かったので、その辺反省して、今後も続きをやっていきたい。

今後もやる気はあるのだが、ゲストの予定が中々合わなくて、収録タイミングがない。

1回やるとCloudfrontの転送量が40GB で $5 ぐらいかかるのがわかって、ちょっとオエってなってる。

技術的な方向性

技術選択的には、最近はもっぱらFacebook党になってしまった。React, Flow, Babel その辺。

ReactNative がすごく盛り上がってるのを感じる。フリーランス的発想だと、これは間違いなく金になる。結局Titanium、RubyMotion、Cordovaと一緒やんけ、みたいなのもわかるが、これらが越えられなかった、周辺エコシステム構築の壁を超えるだけの勢いを感じる。

ただ、自分はフロントエンドエンジニア的なことより、nodeで書かれたツールチェインや、BFFのサーバーをいじってることが多く、nodeエンジニアとして環境やミドルウェアを作ることを期待されてることが多いと感じている。ReactもReactNativeも下回りのツールであって、下回りが整ったからこそ、Redux的なアーキテクチャの世界観が生まれていて、ここが自分の主戦場だという認識をしている。

30までに頑張ること

  • 税務関係の手続きを覚える
  • AWS/Terraform周りを覚える
  • 今年こそ趣味プロジェクトをリリースする

趣味開発、リリースできたことなくて、無茶な構成して、アレは駄目、コレはいける、みたいな経験値貯めて、仕事にフィードバックして終わり、ってなりがち。

じゃあ今年もこんな感じで。