えぐろぐ

https://twitter.com/eggpogg

ROUTE06 に転職して 2年 たった

やったこと

  • Webアプリケーションの開発・運用
  • 面談・面接
  • Professional Service の開発組織作り
  • メンバーとの 1on1
  • ルートシックスラジオ出演

2022/01 から Professional Service の エンジニアリングマネージャー のポジジョンで働いている。といっても開発メンバーが少ないので、プレイングマネージャーとしての動きが多かった気もする。

今のチームの課題と状態

会社も 3年目 で最近は資金調達で大きなプレスリリースもあり社内は慌ただしい感じもある。それにありがたいことにメンバーも増えてきている。

今は複数の PJ が並行して動いているので、3年目の会社なのに複数のWebアプリケーションの開発の新規開発やグロースをしている状態である。

その状態の会社での僕の役目は Professional Service で PJ を効率よく進めていくための開発組織作りにフォーカスして働いている。

今まではプロジェクト毎にアサインされるエンジニアが得意な言語やFWを利用する流れだったが、複数案件を効率よく進めていくために、BE は Kotlin (SpringBoot) 、FE は React(Next.js) を採用するように進めたり、進め方を型かしたりドキュメントを残して属人性の排除や再現性を持たせるように進めている。

という感じで、ドキュメントや文化を作り進めている状態である。

ADR を導入している PJ もあり、ドキュメントドリブンの良さを自分自身が身を持って実感していたりする。

今後

僕自身としては、 EM として致命的なのだけど言語化や情報発信が得意ではない。。。ので、今後は鍛えていきたいと思っている。意味のある洗練された情報発信がすぐにはできないかもだけど、考えながら進めて力になって、会社の役になればと思っている。

チームとしては、メンバーや PJ が増えても、新規開発やグロースをスムーズに進めていける開発体制の基礎づくりを進めていく。

会社としては、順調に進んでいるように外部からは見えているかもだけど、社内はいい感じにカオス感はある。メンバーの増加 や PJの増加 など、要因は色々とあるのだけど、今年・来年あたりは特に山場の年になると思っているので、体を壊さない程度にやっていけたらなと思っている。

読んだ本

初めての マネージャー 経験なので、まずは色んな人がおすすめしている本をざっと読んでいる。

今まで読んできた技術の参考書とかと違って、自分の経験と状況の読むタイミングで受け取り方が全然違うので、繰り返し読んでいこうと思っている。





おわり

という感じで 1年ぶりの投稿だったけど、元気にやっております!

そもそもなんで EM になったの?な部分は別途投稿する。

まだまだ外部発信に慣れていないので、ゆっくり確実にやっていきたい。
ただ、 EM になって後悔はしていないし楽しくやってはいる。

ROUTE06 に転職して 1年 たった

※ なんとなく撮った最近の写真

転職して1年経ったので、その振替しとログ

なにをやってきたか

受託開発がメインで 1 年間で大小さまざま案件に関わった。(4 プロジェクト?)

プロジェクト毎にドメイン領域が違うので業界用語やエンドユーザーの特性など違っていて、関わる会社も違うので、進め方やステークホルダーもバラバラ。。。だけど社内のPMの方々が上手いこと舵取りしてくれていて、それが原因で開発が進まないってことが無いなと感じる。(本当にすごい!!)

大きなプロジェクトだと 9 ヶ月くらい関わっている。何をやっているかは言えないけど OMO ( Online Merges with Offline ) の Web システムの新規開発などなどやっている。

バリバリのスタートアップなので、分野分けなどは無いので全部やっている AWS のインフラの構築からサーバーサイド、フロントエンドと。

毎日が手探りで Try & Error は繰り返しながら進んでいる。なので、成長はすごく感じる!(その分小手先だけがうまくなっているエンジニアになっている気もする.... orz )

これから

毎日コツコツとやるしかない。 けど、30代になってしまったので、これからどういうキャリアパスを進めていくのか、色々考えながら進めて行く予定...

まとめ

もっとちゃんとしたブログとして書きたいなと思ったけど、自分の文章力だとこれくらいが限界なので転職して 2 年経ったのときはもっと書けるよう精進します

おわり 🔚

Vuex で変更通知が正常に動かなかったときのメモ

State の初期値を undefined で初期化するときに
以下は正常に変更通知を受け取れるが

export type StateType = { hoge?: Hoge}
export const state = (): StateType => ({
  hoge: undefined
})
export type ConfigState = ReturnType<typeof state>

以下は変更通知を受け取れない

export type StateType = { hoge?: Hoge}
export const state = (): StateType => ({})
export type ConfigState = ReturnType<typeof state>

色々とネットを見ていると以前は undefined の初期化でもだめだったぽい?

Intellij x husky x nodenv 時に pre-commit が失敗したときの対応

Intellij IDEA で日頃開発をしており、Project で npm の husky を使って、 pre-commit 時に lint チェックをしていたが、 Intellij 内の Git から commit をしたときだけ以下のエラーになりcommit が正常にできないことがあった。

※ terminal から git commit する場合は正常に動作する

12:42 Commit failed with error
  0 file committed, 8 files failed to commit: test
  error project-name@1.0.0: The engine "node" is incompatible with this module. Expected version ">=14.16.x". Got "14.8.x"
  error Commands cannot run with an incompatible environment.

node 14.8.x は mac の system node のバージョンだったので、 husky 実行時に nodenv による切り替えが正常に動作していないっぽい💦

調べると、 ~/.huskyrc に以下を記述すると nodenv で指定する node version で husky が実行されて解決した 👀

if command -v nodenv >/dev/null 2>&1; then
  eval "$(nodenv init -)"
fi

github.com

NestJS のMiddleware 内でModuleのServiceを使用する

たいした話ではないけど、実装中にハマったのでメモ 📝

MiddlewareはInjectableのデコレータをつけて、 NestMiddlewareをimplementsして、useメソッドを実装すれば使える Injectしたい値は他のControllerなどと同じで、constructorで設定をしてあげれば良い

// sample.middleware.ts

@Injectable
export class SampleMiddleware implements NestMiddleware {
  constructor(private readonly hogesService: HogseService) {}
  
  use(req: any, res: any, next: () => void) {
    this.hogesService.moge()
    next()
  }
}

Middleware | NestJS - A progressive Node.js framework

外部で使用されるクラスはModuleデコレータの
exportsに渡してあげれば外部で使用させることができる

@Module({
  exports: [HogseService],
})
export class HogesModule {}

Modules | NestJS - A progressive Node.js framework

TypeScript x Express x Session の実装

ちょくちょく express-session を使うのだけど実装方法を、
その都度調べながらやっているので、やり方をメモ... 📝

SessionOptionsを書き換えて使う

// session.ts

import * as express from 'express';
import * as ExpressSession from 'express-session';
import { createClient, RedisClient } from 'redis';
import * as connectRedis from 'connect-redis';

const redisClient: RedisClient = createClient({
  host: process.env.REDIS_HOST,
  port: parseInt(process.env.REDIS_PORT),
  prefix: process.env.REDIS_PREFIX,
});
const SessionRedisStore: connectRedis.RedisStore = connectRedis(ExpressSession);
const redisStore: connectRedis.RedisStore = new SessionRedisStore({
  client: redisClient,
});

const sessionOption: ExpressSession.SessionOptions = {
  secret: process.env.REDIS_SECRET,
  resave: true,
  saveUninitialized: false,
  store: redisStore,
};

const session: express.RequestHandler = ExpressSession(sessionOption);
export default session;

使い方

// index.ts

import session from './session'
const app = express()
app.use(session)

Nuxt x TypeScript で拡張関数の設定

TypeScriptで拡張関数を記述できることを知ったのでNuxtに組み込んでみた kakkoyakakko2.hatenablog.com

1度でも読み込まれれば良いので、  今回はPluginとして読み込ませるようにした

拡張ファイルを記述する 今回は1つだけだけど、複数増えるときはファイルを分けたほうがいいかも。

// ./plugins/extenstions.ts

export {}

declare global {
  interface Number {
    separatePrice: () => string
  }
}

Number.prototype.price = function(): string {
  return `¥${this}`
}

プラグインを読み込ませる

// ./nuxt.config.js

plugins: [ "~plugins/extenstions" ]

使うときは値を変数に代入後に使用できる

// ./page/index.vue

mounted() {
  const num = 100
  console.log(num.price()) // ¥100
},

自分で作ったカスタムクラスの場合は、それぞれのファイルで記述すればいいけど  プリミティブラッパーオブジェクト やDate , Array , Map とかのクラスはこっちで一元管理したほうが良さそう。

複数プロジェクトで使い回せるようにするにはnpm として管理だけど...それはのちのち...