mediaチームでのasanaの使い方について

こんにちは!技術開発部 media開発チームリーダーの河村です。

今回はvivitで使用しているタスク管理ツールの「asana」について、こんな使い方をしているという事例を交えつつ紹介します。

asanaについて

asanaとはvivitで使っているタスク管理ツールです。

vivitでは入社当時の2020年初頭から無料プランで使っていましたが、当時は技術開発部だけが使用しており、主なプロジェクト管理はスプレッドシートで行われていました。

その後、スプレッドシートより圧倒的にタスク管理がしやすいということで全社的に使うようになりました。

私はいろんな現場でRedmine, Wrike, backlogなど他のツールも使ってきましたが、asanaはUIも直感的だったりタスク間の関係性(親子関係、先行/後続など)がわかりやすい部分がとても気に入っています。

asana.com

asanaのmediaチームでの使い方

mediaチームでasanaを使い始めた時、同じプロジェクトのタスクでも各チーム毎にタスクを持っていてそれぞれのタスクの関係性が見えなかったり、リリース前後でタスクの抜け漏れが発覚するということがありました。

そこでプロジェクトを進める時に以下のようなテンプレート機能を使っています。

このテンプレートでタスクを作ることによって、1つのプロジェクトで必要なタスクを1度に全て揃えることができます。

f:id:Kawam:20220411090152p:plain こちらが親タスクになります。機能追加用テンプレートと書かれた部分にプロジェクト名や実現したい内容が入ります。 説明欄にはこのタスクをなぜやるのか・何がゴールなのかなどの目的を記載し、デザインの関連URLがあれば記入できるようにしています。 vivitではデザインツールはfigmaを使っているので、ワイヤーやfixしたデザインの共有用URLを記入しています。

f:id:Kawam:20220411090218p:plain こちらは親タスクに紐づくサブタスクです。 プロジェクト内で主に対応する必要があるタスクが並べられています。 今回はデザインがいらないなどのケースもあるので、このテンプレートでタスクを作った後に不要なタスクは削除するようにしています。 そうすることでタスクの抜け漏れを防止しています。

f:id:Kawam:20220411090401p:plain こちらは親タスクの実装に紐づくサブタスクです。 実装でもある程度やることが決まっているので必要タスクを並べています。 こちらも不要なタスクがある場合は削除して使っています。

以上のようなテンプレートの使い方をすることでタスクの抜け漏れが防止できたり、タスクの前後関係もわかりやすくなってスケジュール管理がとてもしやすくなりました。

最後に

asanaの機能についてはまだまだ使い切れていない部分も多々あるので、今後も他の機能も見ながらより円滑にプロジェクトが進むような使い方を考えていこうと考えています。

vivit では中途エンジニアも積極募集中です。 少しでも興味を持って頂いた方は、是非カジュアル面談の応募をお待ちしております! www.wantedly.com

GKE に Nginx でレート制限を入れる時の注意点

こんにちは。 vivit で SRE をやっている 宮本 です!

今回はサービスを Dos 攻撃から守るためにレート制限を導入した際に得られた知見をまとめてみたいと思います。

vivit の各サービスは GKE 上で動いており、 GKE Ingress から最初に転送する Pod は基本的に Nginx のリバースプロキシです。 Nginx からユーザーが利用するフロントや API などにアクセスします。

図にすると、以下のようになります。

f:id:tatsurom:20220310155842p:plain

どうやったのか

やり方自体はシンプルで、 Nginx が提供しているレート制限の仕組みをそのまま利用しただけです。 こちらの Nginx 公式ブログ が分かりやすいです。

一部省略や加工を行っていますが、以下のように設定を入れます。

http {
  limit_req_zone $http_x_forwarded_for zone=limit_x_forwarded:50m rate=3r/s;
server {
  listen 80;
  server_name example.com;
  location / {
    limit_req zone=limit_x_forwarded burst=1 nodelay;
    limit_req_status 429;

これだけです。

レート制限の動作確認は必須です。 検証環境への意図的な攻撃には ab を利用しました。

結果の確認は全て Datadog で行っているので簡単でした。 ホストや UA、IP アドレスなどで絞ることで簡単に、どの程度ステータスコード429 で返せたかが分かります。

f:id:tatsurom:20220310162941p:plain

Datadog は決して安くないツールですが、 vivit の開発部では必要で価値あるものにはしっかり投資する文化なのでケチらず使っています。
SRE だけでなく各チームの開発者も日常的に使っており、トラブルシューティングや開発に大いに役立てています!!

この構成の何が問題か

Nginx は Deployment で管理しており Pod のレプリカ数は2以上ですが、レート制限に引っかかるかの閾値はそれぞれの Pod の中だけで判断しています 😇

つまり L4 Service から Pod へのトラフィックは、Pod 間でほぼ等しく分散されるので、意図した数以上のアクセスを許可してしまいかねません。

当然ではありますが、最初は盲点でした。。。

だからといって、例えばレプリカ数が 4 であることを前提として閾値をチューニングすると、それはレプリカ数に依存した設定になってしまい、Pod を気軽に増減できなくなってしまい Kubernetes の良さを一部捨てることになります 🥲

レート制限においては、Nginx は Kubernetes の考え方と相性が悪いとも言えそうです。

結局どうしたのか

かかる工数や、現状受けている攻撃の規模や傾向、Nginx Pod の負荷などを総合的に判断して、今回はこのまま Nginx を使ってレート制限をすることにしました。

適切にチューニングを行った結果、完璧ではないものの、ある程度攻撃に強い構成にできたので目的は達成です!!

改善するなら

Kubernetes 環境でレート制限を入れたいケースは珍しくなく、そのような場合の最も多い構成はサービスメッシュで入れることかなと思います。

Istio を使っている企業さんは多く見受けられます。 公式チュートリアル もありました。

Istio ベースのマネージドな Anthos Service Mesh を検討する方も多そうです。

入れるとなると Kubernetes クラスター全体に影響があることなので今回は見送りましたが、もっと大規模になってきたら検討しても良いのかもしれません。

最後に

vivit では一緒に働くエンジニアを大募集しています 🎉

www.wantedly.com

少しでも興味を持って頂いた方は、是非カジュアル面談の応募をお待ちしております!

「エンジニア組織論への招待」という本から学んだ言葉の意味について

こんにちは、技術開発部の河村です。 アウトドアメディア、hinataの開発リーダーをしています。

2021年9月-12月にかけてvivit社内で「エンジニア組織論への招待」の輪読会を行いましたが、今回はその中で普段使っている言葉の意味を改めて知ることで目から鱗だったものをまとめてみました。

gihyo.jp

輪読会を始めたきっかけ

vivit社内では2週間に1度のペースで1on1を行っており、より1on1が有意義なものになる方法がないかと「メンタリング」というキーワードからこちらの書物に辿り着きました。 それ以外にもチームをより強くするために有益な情報がありそうだったので、社内でも私のようにこの本を読んでみたいというメンバーや一度読んだけど改めてみんなと見解を議論したいという声もあって輪読会を始めました。

どういう書籍か

「どうしたら効率よく不確実性を減らしていけるか」という考え方をもとに、エンジニアリングの課題を解決していく方法が書かれている本です。 最初は思考の整理から入り、メンタリングの技術、アジャイルについて、さらにマネジメントについてなどの組織を設計・運営するための解説がされています。

特に学んだ言葉の意味

この書籍を読んでいて特に感じたのは、普段使っている言葉の意味があまり理解できていなかったり勘違いしていたことでした。 その中でも特に学んだことを以下にまとめてみました。

エンジニアリング

エンジニアリングとは不確実性の高い状態から、低い状態に効率よく移すその過程で行う全てのことです。 (開発をすることはその手段の一つであって、開発=エンジニアリングではありません。)

ここでいう不確実性というのは、「未来のこと」「他人のこと」の2つが挙げられます。 これらをマネジメントすることで事業を最速かつ生産性高く成長させられるようになります。

その不確実性を減らすために、

  • 自分の考えにどんなバイアスや思い込みがかかっているのかを知る
  • 未来の不確実性を下げるために仮説と検証を行う
  • 同じ目的で働いているはずの人々とのコミュニケーションの不確実性を減らす(通信不確実性を排除する)

などといったことを日夜行っているのです。

アジャイル

アジャイルという言葉は、「チームが環境に適応して、不確実性を最も効率よく削減できている状態(自己組織化)」のことを指します。 (私はウォーターフォールと比較対象になると思っていたので、方法論の違いだと勘違いしていました。)

動詞ではないので、「アジャイルをやる、アジャイルをする」という言葉も「アジャイルになる」という言葉の使い方が正しいです。 また1on1で行うメンタリングをチームを対象にして行うことで振り返りや学習という仕組みを取り入れた考え方がアジャイルな方法論、アジャイル型開発とも言えます。 

プロジェクトマネジメントとプロダクトマネジメント

こちらもよく聞く言葉です。(いきなり違いを説明しろと言われてもなかなか難しいかと思います。) まず大きな目的の違いとして、プロジェクトマネジメントは終わらせること、プロダクトマネジメントは終わらせないことという違いがあります。

プロジェクトマネジメントは資源や資産、リスクを管理して効果を最大化する方法のことです。 プロジェクトマネージャはスケジュールに対する不安を減らし、納期の大幅な超過やプロジェクトを頓挫させないようにしながら効果を上げて終了させることが役割となります。 また、プロジェクトを進める方法がはっきりしていないのでこの方法不確実性に対処していくことが必要となります。

対して、プロダクトマネジメントは「プロダクトが継続的に収益をあげることで終了しないこと」が目的となります。 プロダクトマネージャはプロダクトがマーケットに受け入れられ続けるように物事に取り組むことが役割となります。 また、やってみないと何を作れば受け入れられるかわからないため、目的不確実性に対処していくことが必要です。

さいごに

この書籍では開発面だけに留まらず、ビジネス側とのコミュニケーションなども含めて会社の組織論が書かれていました。 今後は開発部だけでなく、この話を社内に広めてよりvivitを強い組織の会社にしていければと考えています。

今回は「エンジニア組織論への招待」という本から学んだ言葉の意味についてお話ししてみました。

vivit では一緒に働くエンジニアを大募集しています。 これからもメンバー一人一人が自走していけるような環境作りをしていきますので、その中でみなさんと一緒に働けることを楽しみにしています。

いつでもカジュアル面談を受け付けていますので、是非よろしくお願いします。

【デスクツアー】アウトドア企業のプログラマーの作業環境

はじめに

フロントエンドエンジニアの関です。

vivit株式会社では一部の社員がリモートワークでの業務を行っています。
リモートワークの詳細な取り組みについては下記の記事をご覧ください。

vivit.hatenablog.com

私個人としては感染症リスクについてはともかくとして、リモートワークはしたいもののオフィスでの顔を合わせる業務もバランス良く行いたいと思っています。

今回は最近流行りのデスクツアーと題してオフィスと自宅の両方で快適に作業をするための工夫や商品の紹介ができればなと思います。

オフィス

こちらがオフィスでの私のデスクです。(写真は一部加工しています)
恐らく社内でも随一好き勝手やってるデスクですがとても快適に作業できています。

f:id:KeytacK:20220117041429j:plain

PCは基本的に支給されますがその他周辺機器の利用は個人の自由です。純正コネクタ等一部申請すれば会社側で買ってもらえるものもあります。

f:id:KeytacK:20220117041546j:plain

キーボードは HHKB Professional HYBRID Type-SDomikey Semiconductor for HHKB を付けたもので、ORCASリストレストを使っています。

ポインティングデバイスエレコムトラックボール HUGE M-HT1DRBK を愛用しています。

トラックボールといえばロジクールの親指タイプがポピュラーかと思いますが大玉の安定感が自分は好きです。

ノートPCスタンドは YOHANN のウォルナットを一目惚れで取り寄せました。

基本的に木でできた製品が好きで買ってしまうのですが、これは高さが丁度良くて座りがいいので買ってよかったです。

下には MiTo GMK Pixel のデスクマットを敷いています。

生地が思ったより厚くて打鍵感が凄く心地よいです。

デスク下にはリモート中の方と通話する際に使うヘッドセットが引っ掛けてあります。
(ブームマイク付きが使いたくて家に余ってたのを引っ張り出してきたのでいいのがあれば買い変えたいところです。。。)

基本的にPC周辺機器は毎日触るものなので気に入った道具を揃えたいという思いがあり、デスク周りの用品は妥協なく選んでいます。

自宅

こちらは自宅で作業する際のデスクです。
コミュニケーション周辺のツールを AVerMedia 製品で固めているので親和性が高く快適にテレワークができています。
(仕事だけでなく友人とオンラインゲームをする際もここなのでゲーム用コントローラーも見えていますが平日昼間はちゃんと仕事してます。。。)

f:id:KeytacK:20220117041734j:plain

画角の都合上写せなかったのですが、チェアは Herman Miller の アーロン リマスタード ライト を使っています。購入にはかなり勇気がいりましたが、やはり買ってよかったと言えるものの一つです。

卓上両端には 以前 紹介したキーボードの Lily58 + Domikey SA Dolch Orange がありますが、今スイッチが Candy’s Jade Green に変わっています。
手前には PFU公式 のセパレート型ウッドパームレストを置いています。

vivit.hatenablog.com

トラックボールはオフィスと同様 HUGE M-HT1DRBK を使っています。

モニター上にWebカメラの AVerMedia Live Streamer CAM 313 があり、セットで購入したデスクマットを敷いています。

写真左側には Live Streamer MIC 330 がアームでせり出てきていて、ここでの音周りは全てその下の Live Streamer AX310 で一括管理しています。

家で作業しているときは正面モニター下の iPad Air でタスク管理アプリやカレンダーを表示しています。

終わりに

デスクまわりに限らず海外製品があったりして、注文したら翌日には届くというものでもないので中々おすすめしにくい面もありますがどれも買ってよかったと言えるものばかりです。

執筆時現在のデスク周りはこんな感じですが、ウルトラワイドモニターやモニターアームなど欲しいものが結構あるため割とすぐアップデートされるかもしれません。
情勢的にまだまだ油断の許されない昨今です、テレワーク環境構築の旅はまだまだ終わりません。

vivit株式会社ではアウトドア業界の新たな可能性を共に探す旅人を募集しています。

www.wantedly.com

Datadog で「リリース後にだけ」利用するモニターを作成する

こんにちは。
vivit で SRE をやっている宮本(https://github.com/tatsuro-m)です!

今回は Datadog で「リリース後にだけ」利用するモニタリングリソースをどうやって作成、運用していったかを書いてみようと思います。

基本的には常時 OFF(ミュート)で、リリース後に ON(アンミュート)になり、1時間後に自動で再度ミュートします。

背景

一般的に、何らかのリリースが起点となって障害が発生することは多いと思います。

vivit では常時 Datadog モニターを利用してエラー率、 SLO の監視をしていますが、タイムウィンドウが1週間と長くなっています。

リリース後の1時間など、もっと小さいタイムウィンドウで突発的なエラー率の上昇を監視したいという要件があり、今回の仕組みを構築しました。

前提知識

  • モニターにはミュート、アンミュートの機能があり、ある期間のアラートを無視することができる(モニターの管理)

  • ミュート時にはミュートを解除する時間を指定できる

  • アンミュートする際には再度ミュートする時間を指定する機能は存在しない
  • Datadog は多くのリソースに対して REST API を提供していて、モニターもある(https://docs.datadoghq.com/ja/api/latest/monitors

よって、時間経過によって自動で再ミュートする仕組みは自分で構築しなくてはなりません。

アーキテクチャ

f:id:tatsurom:20220111151024p:plain

順番に解説します。 対象となるモニターは予め作成した上でミュート状態にしておき、 monitor_id を控えます。 monitor_id は Datadog 画面から確認できます。

  1. リリースをトリガーにして1つ目の Cloud Functions を gcloud で呼び出す
  2. unmute エンドポイントを叩いてミュート解除する
  3. Cloud Tasks のキューにタスクを積む。この時、起動時刻のオプションで特定時間を設定する
  4. 指定した時間に HTTP 呼び出しで mute エンドポイントを叩く Cloud Functions を呼び出して再度ミュート

ポイント

トリガーは何でも良いのですが、今回は特定マイクロサービスの本番環境へのリリースです。

vivit では GitOps を採用しているので、Kubernetes マニフェストの更新を検知して GitHub Actions のワークフローが起動するところからスタートできます。

vivit での GitOps については 、

vivit.hatenablog.com

こちらの記事をご参照下さい !!


以下、Cloud Functions で実行される Cloud Tasks キューにタスクを作成する部分のコードです。

ts := &timestamppb.Timestamp{Seconds: time.Now().Add(1 * time.Hour).Unix()}
req := &taskspb.CreateTaskRequest{
    Parent: queuePath,
    Task: &taskspb.Task{
        ScheduleTime: ts,
        MessageType: &taskspb.Task_HttpRequest{
            HttpRequest: &taskspb.HttpRequest{
                HttpMethod: taskspb.HttpMethod_POST,
                Url:        os.Getenv("MUTE_FUNCTION_URL"),
                AuthorizationHeader: &taskspb.HttpRequest_OidcToken{
                    OidcToken: &taskspb.OidcToken{
                        ServiceAccountEmail: os.Getenv("UNMUTE_FUNCTION_SA_EMAIL"),
                    },
                },
            },
        },
    },
}

Go で提供されているクライアントライブラリを利用します。
ScheduleTime に起動時刻を設定することができます。 Cloud Functions の HTTP 呼び出しには認証必須にしているので、 OIDC トークンも忘れずにセットします(ここでハマりました 🤧)。


Datadog は様々な言語の API Client を提供しており、Go のライブラリも存在します(GitHub - DataDog/datadog-api-client-go: Golang client for the Datadog API)。

ただし今回は API Client を使うまでもないと判断したので、Go の標準パッケージで REST API を呼び出しています。

   req, err := http.NewRequest(http.MethodPost,
        fmt.Sprintf("https://api.datadoghq.com/api/v1/monitor/%s/unmute", os.Getenv("MONITOR_ID")),
        nil)
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("DD-API-KEY", os.Getenv("DD_API_KEY"))
    req.Header.Set("DD-APPLICATION-KEY", os.Getenv("DD_APP_KEY"))

    if err != nil {
        return err
    }

    resp, err := http.DefaultClient.Do(req)

Datadog の API を呼び出すには、2つの秘匿情報が必要です。

  • api key
  • app key

これらの情報を Cloud Functions に伝えるために、Secret Manager を利用して環境変数に登録しました。

Using secrets  |  Cloud Functions Documentation  |  Google Cloud


「特定時間経過後に Cloud Functions を呼び出したい」という要件だけ聞くと、Cloud Scheduler の利用を検討される方もいると思います。

しかし Cloud Scheduler は Cron を使用する以上、単発の実行には不向きです。

cloud.google.com

単発で実行したいという理由で、今回は Cloud Tasks の scheduleTime を利用する構成で作ってみました。

最後に

割と特殊なケースですが、 Datadog APIGCP のサービスを上手く組み合わせることで、このような構成も可能であることが伝われば幸いです。

vivit では一緒に働くエンジニアを大募集しています。
www.wantedly.com

少しでも興味を持って頂いた方は、是非カジュアル面談の応募をお待ちしております!

Goでコンストラクタ関数(完全コンストラクタ)を定義する

はじめに

vivitで hinata spot というキャンプ場の検索・予約サービスのbackendを担当しています名嘉眞です。 hinata spot のbackendはGoで書かれています。 今回は、Goでコンストラクタ関数(完全コンストラクタ)を定義した際の問題や対応策について書きます。

※この記事の内容はチームの方針や実装者の考え方、サービスの仕様やユースケースにより変わる部分もあると思いますので、ひとつの参考になればと考えています。

Goでコンストラクタ関数(完全コンストラクタ)を実装

hinata spot では全ての箇所ではないのですが、値オブジェクトの生成などで、 コンストラクタ関数(完全コンストラクタ) を定義しています。 完全コンストラクタ はオブジェクトを生成した時点でそのオブジェクトは正しく利用することができる状態になる実装方法です。

そのためオブジェクトを生成するタイミングで、対象のオブジェクトを生成する上で不正な値ではないか、バリデーションを行う必要があります。

また、setterを定義しないことで、コンストラクタ関数で安全な状態で生成したオブジェクトを変化させることがないです。

※オブジェクトの変更を加えたい場合は、setterではなくその変更内容をふるまいとしてメソッドを定義したりします。

下記は注文金額(OrderAmout)を生成するコンストラクタ関数で0円では生成できないルールを実装しています。 フィールドもprivateなフィールドとして宣言することで外部のpackageから変更できないようにします(フィールドの先頭の文字を小文字にする)

type OrderAmount struct {
  amount uint
}

func NewOrderAmount(args uint) (OrderAmount, error) {
    if args == 0 {
        errors.New("OrderAmoutは0円では生成できない")
    }

    return OrderAmount{amount: args}, nil
}

フィールドがprivateなので、外部のパッケージからのOrderAmountオブジェクトの生成をNewOrderAmountに限定することができました。 また、 NewOrderAmount内でバリデーションが実行されることで不正な値のOrderAmountオブジェクトが生成されることも無くなりました。

しかし上記の実装だと以下のようなちょっとした問題があります。

Goでコンストラクタ関数(完全コンストラクタ)を実装した際の問題

不正な値で生成される可能性がほぼ無い場合でもコンストラクタ関数を使いエラーチェックする必要がある

Goの場合、例外(panic)を気軽に使うことが推奨されていないため、エラーを返す関数の場合はエラーチェックを行い呼び出し元の関数が正しく処理すべきです。

今回の例の場合だとDBの情報からオブジェクトを生成する場合や、テストコードでオブジェクトを使用する場合もエラーチェックを行う必要があります。

※DBの情報からオブジェクトを生成する際もバリデーションチェックするべきという考えもあると思います。

これは人によっては問題ではないと考えるかもしれません。

私も基本的には問題とは考えずに、不正な値でオブジェクトが生成される可能性がほぼ無い場合であっても定義した完全コンストラクタ関数を使ってオブジェクトを生成しエラー処理も書いています。

またテストコードでもコンストラクタ関数を利用してオブジェクトを生成することで不正なオブジェクトを使ってテストされることを防ぐメリットもあります。

しかしテーブル駆動テストコード書いた場合だと特にそうなのですが、テストコードが長くなり見通しが悪くなる可能性が高いです。

テストコードでは完全コンストラクタをラップした関数を用意するなど、テスト用のオブジェクト生成の仕組みを定義するだけでも基本的には解決します。 ただ、完全コンストラクタを定義したオブジェクトの数だけテストコードに関数が作られる可能性があります。

対応策

対応策は単純なのですが、バリデーションを行いエラーを返すコンストラクタ関数と、オブジェクトの生成だけを行うコンストラクタ関数を2つ定義します。

type OrderAmount struct {
  amount uint
}

func (o OrderAmount) Valid() error {
  if o.amount == 0 {
        return errors.New("OrderAmoutは0円では生成できない")
  }

  return nil
}

// NewOrderAmountはバリデーションなし、エラーをかえさない。
func NewOrderAmount(args uint) OrderAmount {
    return OrderAmount{amount: args}
}

func CreateOrderAmount(args uint) (OrderAmount, error) {
    o := NewOrderAmount(args)

  if err := o.Valid(); err != nil {
    return OrderAmount{}, err
  }

  return o, nil
}

前の例と比べると以下のように変更しています。

  • バリデーションを別のメソッドに抽出しています
  • NewOrderAmountはバリデーションせず、エラーも返さない関数として定義しています
  • CreateOrderAmountを完全コンストラクタとして定義します

バリデーションを別のメソッドに抽出しています

バリデーションを別のメソッドにせず、CreateOrderAmount内で処理しても良いですが、分けた方がCreateOrderAmount関数がシンプルになります。

今回の例では0円かどうかのチェックのみですが、ルールが増えた場合は分けた方がわかりやすくなると思います。

NewOrderAmountはバリデーションせず、エラーも返さない関数として定義しています

NewOrderAmountは、シンプルなコンストラクタ関数としてDBの情報からオブジェクトを生成する場合やテストコードで使用します。

エラーを返さないコンストラクタ関数を使用する箇所を限定的にするために、関数名をNewOrderAmountFromRepositoryなど明確にすることも良いと思います。

ただ、NewOrderAmountFromRepository だとrepository層からオブジェクトを生成しない場合などに違和感がありますので別の名前の方が使いやすいかもしれません。

CreateOrderAmountを完全コンストラクタとして定義します

CreateOrderAmountはバリデーションを行い、不正なオブジェクトを生成しない完全コンストラクタとして定義します。そのためエラーを返します。

実際のユースケースで外部からの情報をもとにオブジェクトを生成する場合に使用します。

今回は引数の値をそのまま設定するだけですが、例えば金額計算を行う必要が出てきた場合、CreateOrderAmount関数内で計算処理を行うように変更することもできます。 その場合CreateOrderAmountからCalculateOrderAmountという関数名に変更し、よりドメインロジックの内容にあった関数名にして良さそうです。

まとめ

コンストラクタ関数を2つに分けることで、上記にあげた課題の解消はできました。

ただ、コンストラクタ関数が2つになることで問題も生まれます。

それは、実際はバリデーションを行うべきユースケースで、バリデーションを行わないシンプルなコンストラクタ関数が使用されることです。

この問題はレビューで確認したり、コンストラクタ関数の命名をより明確にしていくことである程度は防ぐことができると思いますが、完全に防ぐことはできないと思います。

そのためコンストラクタ関数を2つに分けるのは、オブジェクトが利用される頻度などを考えて分けた方が良さそうと判断した場合のみと考えています。

最後に

Goでコンストラクタ関数(完全コンストラクタ)を定義した際にでた問題とその解決策に関して書きました。 記事の冒頭にも記載しましたが、チームの方針や実装者の考え方、サービスの仕様やユースケースにより変わる部分もあると思います。また人によっては問題ではないと考えるかもしれません。 今回紹介した内容はコンストラクタ関数の実装方針という細い部分かもでしたが、誰かの参考になれたら幸いです。

vivitではGoを書きたい人を募集しています!

vivit 開発部はナレッジ・ドキュメントが豊富

はじめに

こんにちは!開発部マネージャーをしている井島です。
開発部では以下で紹介されているように、強みとして「ナレッジ・ドキュメントが豊富」も挙げられています。

vivit.hatenablog.com

今回は、実際にどんなドキュメントがあるか少し紹介していきたいと思います。

vivitはドキュメントのツールとしてDocBaseを主に使っており、必要に応じてGoogleのドキュメント、スプレッドシート、スライドも使っています。

開発部 全般的な資料

各画像はDocBaseの画面になります。

f:id:ijimakenta:20220116003431p:plain

開発部全体、各プロダクト開発チーム毎の振り返り資料で、主にKPT(Keep, Problem, Try) の内容になります。
「エンジニアランチ委員会」は、開発部内でコミュニケーションを活発化させる動きがあり、その資料になります。

f:id:ijimakenta:20220116003504p:plain

ここから各チームやプロダクトの資料ページに飛べるようになっています。
設計書などもこの先から飛べるようになっています。

f:id:ijimakenta:20220116003725p:plain

開発部ではクウォーター毎にキックオフMTGを行っています。
会社、各事業の情報共有や今後の方針、開発部レベルでのKPT実施など行っています。

f:id:ijimakenta:20220116003740p:plain

コードレビューについてのナレッジ、ルールを記載しています。
各チームでコードレビューのやり方があるのですが、チーム内だけのナレッジで留めず、全体に共有していけたらと思っています。

f:id:ijimakenta:20220116003756p:plain

遅刻、休み、リモートするときなどの方法のまとめになります。

f:id:ijimakenta:20220116003837p:plain

開発部では障害に対して、ポストモーテムを作成しています。
2020年からポストモーテムを書く活動を初めて、現時点では29件まで増えました。毎回きちんと根本対応まで行っており、それが功を奏しているのか、同じ問題は発生していません!

また、ナレッジを収集する活動もあります。
Slack にスタンプすると、特定チャンネルに投稿されるようになっています。まだ日々の開発で発見したナレッジを体系的にまとめる仕組みは整えられて居ませんが、収集だけは行っています。 2022年1月からは、溜まってきたナレッジを共有していく会を開催していく予定です!

f:id:ijimakenta:20220116003855p:plain

開発部内で行った勉強会、輪読会の資料になります。皆さんの満足度が高かったものは以下でした!

おわりに

vivit 開発部は決して分からないことは自分で調べろ という文化ではありません!!
常に情報共有し、メンバーが相互に助け合っている組織です。vivit のValue 「Give and Give」です!

最後に、vivit では一緒に働いてくれる仲間を募集中です。
気になったことがあれば、是非、お気軽に話を聞きに来てください!

【新卒】
www.wantedly.com

【中途】
www.wantedly.com www.wantedly.com