BASE開発チームブログ

Eコマースプラットフォーム「BASE」( https://thebase.in )の開発チームによるブログです。開発メンバー積極募集中! https://www.wantedly.com/companies/base/projects

ECS(Fargate)でコンテナアプリケーションを動かすための設定情報の扱い方

あけましておめでとうございます。 BASE BANK株式会社でソフトウェアエンジニアをやっている東口(@hgsgtk)です。

2018年末から年明けにかけて、EKSが東京リージョンに来たりAWSからのリリースが賑わいを見せていますが、その中から、AWS Fargateの次の新機能を実際のプロダクトに適用しました。

AWS Fargate プラットフォームバージョン 1.3 でシークレットのサポートを追加

これを期に、コンテナアプリケーションにおける設定情報を扱う考え方・それを実現するためのAWSのサービス構成と得られた利点についてまとめてみようと思います。

目次

  • 設定情報の扱いに対する要件
  • コンテナベースの設計思想・原則
  • ECS(Fargate)を用いる場合の設定情報の扱い方

設定情報の扱いに対する要件

開発背景

BASE BANK社では、即時に資金調達ができる金融サービス「YELL BANK(エールバンク)」というプロダクトを開発しています。 以前本ブログに投稿した「GoのAPI開発現場におけるユニットテストTips」 や「Goを運用アプリケーションに導入する際のレイヤ構造模索の旅路 | Go Conference 2018 Autumn 発表レポート」の通り、Go言語でアプリケーションを開発しており、docker buildしたイメージから作成したコンテナをECS(Fargate)上で動かすことで機能を提供しています。

設定情報とは

本記事内での「設定情報」は、データベース、Memcached、他バックエンドサービスなどのリソースハンドルのための認証情報を指します。これらは、本番・ステージング・開発・QAなど環境ごとにそれぞれ異なる値を持つ属性があります。

コンテナアプリケーションの設計として、設定情報をどう取り扱っていくか次に考えていきます。

コンテナベースの設計思想・原則

コンテナベースで動かすアプリケーションでの設計思想について次の2点の資料がよく参照されます。

この2つの資料からコンテナベースアプリケーションにおける設定情報の扱い方について見ていきます。

Beyond the Twelve-Factor App

2012年に、モダンなクラウドアプリケーションのベストプラクティス「The Twelve-Factor App」をHerokuの中の人が書きました。Beyond the Twelve-Factor Appは、2016年にPivotal社が、オリジナルのガイドラインのアップデート・ガイドラインの追加したものです。

クラウド環境を活用したクラウドネイティブアプリケーションの新たなベストプラクティスをガイドラインとしてまとめてくださっています。次のURLから実際にPDFをダウンロードすることができます。

content.pivotal.io

また、次のスライドが大変わかりやすくガイドラインについてまとめてくださっているので、そちらもご参照いただくと良いかと思います。

Chapter 5 Configuration, Credentials and Code

この資料内で、特に設定情報については、Chapter 5 Configuration, Credentials and Codeという章で言及されています。ピックアップすると大きく次の内容です。

  • 設定や認証情報はコードから分離すべき
  • 環境は無限に増えていくため、環境(dev, prd...etc)ごとに設定をグルーピングすべきではない。
  • 設定をコードから分離する一番の方法は環境変数への格納である。

設定情報とコードを分離することを求めており、分離できているかどうかの指標として、今すぐにでもコードをオープンソース化できるかを上げています。

次にもう一つredhatが公開している設計原則について見てみましょう。

Principles of container-based application design (Redhat)

redhatが公開しているホワイトペーパーで、コンテナベース・アプリケーションの設計原則についてまとめています。 次のURLにて日本語版の資料をダウンロードすることができます。

www.redhat.com

IMAGE IMMUTABILITY PRINCIPLE (IIP) イメージ不変性の原則

いくつかの原則を説明している中で設定情報についての扱いに関連のあるものとしてこちらの原則があります。

コンテナ化アプリケーションは不変であるため、ビルドされた後、異なる環境間で変化することは想定されていません。つまり、環境ごとにコンテナの作成や修正を行うのではなく、ランタイムデータの保存に外部手段を利用し、外部化した設定を環境によって使い分けます。

上記の記述により、yamlファイルなどでアプリケーション内で設定情報を分けてそれぞれビルドする方法ではなく、ビルドするアプリケーション内に環境によって異なる情報は入れず、外部に保存した設定情報を使用することが推奨されています。

2つの思想・原則から方針を見出す

これまで見てきた2つの資料から、コードから設定情報を分離し、環境変数から外部設定した設定情報を注入する構成としていきます。

ECS(Fargate)を用いる場合の設定情報の扱い方

設計方針が決まったところで実際にAWS、特にECS(Amazon Elastic Container Service)を利用した場合の設定情報の扱い方についてです。

概要構成

概要構成は次のようなものになります。

f:id:khigashigashi:20190115190403p:plain
概要構成

以下、AWS Fargate プラットフォームバージョン 1.3 でシークレットのサポートを追加で発表された機能を利用するため、プラットフォームバージョンは1.3以上を前提とします。

アプリケーション

環境変数から設定情報を取得する実装とします。例えば、Go言語の場合はosパッケージを利用して次のようなコードを書くことになるでしょう。

dbHost := os.Getenv("DB_HOST")

ビルドしたアプリケーションのコンテナイメージは、ECR(Amazon Elastic Container Registry)Docker Hubいったコンテナレジストリサービスにpushします。

設定情報の保存

設定情報は、SSM(Systems Manager) Parameter Storeに保管していきます。

SSMでは、パラメータを階層的に管理する事が可能です。

docs.aws.amazon.com

具体的には、/stage1/stage2/stage3 といった形で階層を掘っていく形になります。

この際、DBのパスワードなど暗号化して保存したい場合は、KMS(Key Management Store)を用いて暗号化キーを作成し、そのキーを持って暗号化します。

SSMに設定する情報を暗号化する際は登録時に暗号化オプションを付け、KMSキーを指定します。

aws ssm put-parameter --name /goecssample/database/sample/master/password --type "SecureString" --value "password" --key-id "< KeyId >" --description "データベースのmasterユーザーパスワード" --region ap-northeast-1

具体的には、typeをSecureStringとし、key-idに作成したKMSキーを設定するだけです。

コンテナから設定情報を利用

SSMに保存した設定情報を、コンテナに挿入するためにはタスク実行ロールに対してSSMのパラメータ取得・KMSキーでの復号を許可する必要があります。 具体的には、タスク実行ロールに対して以下のようなポリシーを追加します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ssm:GetParameters",
        "kms:Decrypt"
      ],
      "Resource": [
        "arn:aws:ssm:region:aws_account_id:parameter/parameter_name",
        "arn:aws:kms:region:aws_account_id:key:key_id"
      ]
    }
  ]
}

タスク定義

ECSのプラットフォームバージョン1.3.0より前、Fargateを利用している場合、System MangerのParameter Storeなどから設定情報をコンテナに注入するには、自前でdocker-entrypoint.shなどからSSMに対してAPIアクセスして取得する必要がありました。

しかし、今回のサポートによって、タスク定義内のコンテナ定義に設定することによって、コンテナ起動時に自動でコンテナに対して設定を注入することができるようになりました。

具体的には、コンテナ定義の環境変数に、環境変数名・SSMのパラメータ名を指定するだけです。

f:id:khigashigashi:20190115190517p:plain
コンテナ定義/環境変数設定

1.3より前は、次のようなentrypoint.shなどを書いて対応していました。

#!/usr/bin/env bash

set -e

export DB_HOST=$(aws ssm get-parameters --name /prd/database/host --query "Parameters[0].Value" --region ap-northeast-1 --output text)

exec "$@"

1.3へのアップデートによって、自前での実装が不要になり、かなりシンプルになりました。

その他

その他、より詳細の説明は、AWS公式の次のドキュメントを参照してみてください。

docs.aws.amazon.com

この構成にして得られた利点

コードから設定情報を分離できた

コードから設定情報を分離したことによって、全アプリケーションエンジニアがすべての設定情報を参照できる状況は避けることができました。 加えて、設定情報は、AWS Systems Manager Parameter Storeに設定されています。 本番・ステージングなどでアカウント自体が分かれている場合は、そもそもアカウントを発行されている人のみに閲覧を絞ることができ、加えてIAMの設定等で誰のアクセスを許可するかを制御することが可能になりました。

設定の量が増えても階層的に扱える

AWS Systems Manager Parameter Storeでは、階層的にパラメータを登録することが可能なため、情報を階層的に扱いたいモチベーションもある程度満たしてくれました。

シークレットのサポートによって得られた嬉しいこと

AWS Fargate プラットフォームバージョン 1.3 でシークレットのサポートを追加によって嬉しかった点も記載します。

コンテナ起動時の複雑性が軽減された

当初、デプロイ時の複雑性を増していたdocker-entrypointでの自前実装が不要になり、アプリケーションの複雑性が減りました。

イメージサイズが小さくなった

副次的な効果として、AWSのAPIに対するアクセスが不要になったため、実行イメージに含めていたpythonaws-cliが不要になりました。 その効果によって、約40MB程度だったイメージサイズが約10MBまで小さくなりました。

まとめ

そもそも、コンテナアプリケーションをどう扱うべきなのかという観点から、実際にAWS Fargateを利用した場合についての説明をさせていただきました。 当初扱いづらさがあった部分もアップデートによって日々使い勝手がよくなってきている印象を覚えています。 現在、ECSなどでアプリケーションを構成しようとしている・または検討している方にとって、一つの参考になれば幸いです。

Vue Boot Campをやってみました!

f:id:chiiichell:20181225125728j:plain

この記事は「BASE Advent Calendar 2018」25日目の記事です。

devblog.thebase.in

こんにちは。BASEでFrontend Groupに所属している三佐和です。主にネットショップ作成サービス「BASE」のフロントエンドを担当しています。

先日デザイングループのマネージャー早川が 「BASE」の管理画面リニューアルプロジェクトのこれまでとこれからで話しているように、現在BASEでは本格的にフロントエンドをVue.jsで置き換えるプロジェクトが進行しています。

これまでのBASEのフロントエンドは、主にマークアッパーを含むデザイナーが中心になってjQueryでゴリゴリと実装していました。 Frontend Groupが発足したものの、まだまだこれからで、しばらくはデザイナーと協力してサービスを作っていくスタンスで開発を進めています。

そのため、モダンなフロントエンドの考え方や新しく導入されたシステムについて、デザイナーの方へ伝えたり、慣れてもらうことの重要性が高まっていました。

しかし、当初はこんな声もありました。

f:id:chiiichell:20181225130939p:plain:w300

そこで、Frontend Groupとして、主にデザイナー向けにVue.js勉強会を開催することにしました。 また、少し前に流行した短期集中型エクササイズ・Billy's Boot Campから、この勉強会のタイトルを「Vue Boot Camp」と名付けました!

このブログでは、それを開催する過程で伝えたかったことや考えていたこと、準備したことを紹介していけたらと思います。

対象を考える

BASEの場合は主に以下の3種類のロールが「デザイナー」と呼ばれています。

  • いわゆるマークアッパーで、jQueryを使ったフロントエンドコーディングができる
  • UIデザインができて、HTMLとCSSでそれを表現できる
  • UIデザイン、ビジュアルデザインの専門で実装はほとんどしない

このうち今回対象にしたのは、上の2つで、前提としてある程度HTMLとCSSのことは分かっている、ということをラインとしています。 これらの条件に当てはまる人は一旦Vue.jsにはまったく触ったことがない人、と仮定しています。

覚えてもらいたい・知ってもらいたいこと

対象を絞ったので、次に覚えてもらいたいことを考えていきます。 「デザイナー」と呼ばれる方にフロントエンドで責任をもってもらいたい部分は、主に以下の2つだと考えました。

  • 大まかなシステムが構成されている上での、デザイン当て、マークアップ、インタラクションデザイン
  • 自社開発のコンポーネントのメンテナンス

これらを実現する為にVue.jsやモダンフロントエンドに関する知識の中でも、この要素は伝えたい!というのが

  • Web Componentsという考え方
  • BASEで利用している基本的なフロントエンド構成
  • 自社開発のコンポーネントを実際に利用した開発を体感してもらう
  • css-moduleを使ったスタイリング
  • フロントエンドにおける簡単なCRUD操作

これらであるとして題材を考えることにしました。

題材を考える

前半はVue.jsのチュートリアルをなぞりつつ、BASEの新しいフロントエンドやWeb Componentsな考え方に触れてもらう、というところまではすぐに決まりました。

後半は、なにか一つアプリを作る体験をしてもらいたいと考えていました。

これらを満たせるアプリを考えたときに、JavaScript界隈ではおなじみ(?)のTodoMVCというものを紹介してもらいました。 これをベースに考えていくと上記のような要素が満たせそうだったので、これをアレンジしたTodoアプリを今回の題材にすることにしました。

f:id:chiiichell:20181225131149g:plain:w300

これに対し、実際にどのようなアレンジをしていったかというと...

自社コンポーネントを使った開発

BASEではBBQという名のUI実装時に使用されるコンポーネントのライブラリがあり、例えばVue.jsのサンプルでは以下のようなコードになっていますが、

<ul class="todo-list">
    <li v-for="todo in filteredTodos"
    class="todo"
    :key="todo.id"
    :class="{ completed: todo.completed, editing: todo == editedTodo }">
        <div class="view">
          <input class="toggle" type="checkbox" v-model="todo.completed">
          <label @dblclick="editTodo(todo)">{{ todo.title }}</label>
          <button class="destroy" @click="removeTodo(todo)"></button>
        </div>
        //...
    </li>
</ul>

このようなリストに含まれるチェックボックスや削除ボタンのコンポーネントをBBQを使って書くと以下のように書くことができます。

<ul :class="$style.todo">
    <li :class="$style.todo_list">
        <bbq-checkbox :class="$style.todo_checkbox">
            <template slot="text">
                {{ item.text }}
            </template>
        </bbq-checkbox>
        <bbq-icon-button :class="$style.destroy" icon="crossCircle" noBorder @click="removeItem"></bbq-icon-button>
    </li>
</ul>

このような変更を全体的に行うことで、それぞれをBBQを使って実装することを体験してもらうことができます。

css-moduleを使ったスタイリング

またcss-moduleを使った実装に置き換えて.vue ファイル内にスタイルを書くことで、そのコンポーネントの中でしか影響を与えないCSSを作ることができます。

<div :class="$style.hoge">{{ message }}</div>

<style lang="scss" module>
    // スタイルを書く
    .hoge {
        //...
    }
</style>

事前に準備したこと

テンプレートプロジェクトの作成

デザイナーの人にwebpackの設定をしてもらいたいわけではないので、BASEで実際に使用している構成と近い形になるよう、事前に以下のような設定を行ったプロジェクトを準備しました。参加者は git cloneyarn install を行うだけで、すぐに Vue.jsでの開発が始められます。

一般的なwebpackの設定などは割愛しつつ、特に重要なポイントのみ列挙します。

必要なパッケージをインストール

yarn add -D webpack webpack-cli webpack-dev-server
yarn add vue
yarn add -D typescript ts-loader vue-class-component
yarn add -D vue-loader vue-style-loader vue-template-compiler
yarn add -D css-loader sass-loader postcss-loader

webpackを設定

TypeScript、シングルファイルコンポーネント、css-moduleが使えるよう設定します。

    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use : {
                    loader: 'ts-loader',
                    options: {
                        appendTsSuffixTo: [/\.vue$/],
                    }
                }
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        'scss': 'vue-style-loader',
                        'sass': 'vue-style-loader'
                    }
                },
                exclude: /node_modules/
            },
            {
                test: /\.[s]?css$/,
                use: [
                    'vue-style-loader',
                    {
                        loader: 'css-loader',
                        options: {
                            modules: true
                        }
                    },
                    {
                        loader: 'postcss-loader'
                    },
                    {
                        loader: 'sass-loader'
                    }
                ],
                exclude: /node_modules/
            }
        ]
    }

シングルファイルコンポーネント用の型定義を追加

拡張子が .vue となっているSFCのファイルをimportするときに、記述されているコードをTypeScriptとして認識できるようにする必要があります。このために以下のような型定義ファイルを作成します。

declare module '*.vue' {
    import Vue from 'vue'
    export default Vue
}

ドキュメントの用意

Vue.jsの公式ドキュメントとは別にBASEの構成で表現するための対応の説明と、順を追って TodoListを作成していくドキュメントを用意をしました。 全体の進行をこれにあわせることで当日参加していない方でも、このドキュメントを上から追っていくとだいたい理解できるようになっています!

当日の様子

そんなこんなで迎えた勉強会当日

f:id:chiiichell:20181225124920j:plain f:id:chiiichell:20181225124909j:plain

Vue.jsを独学で勉強し始めたメンバーやバックエンドエンジニアなど、デザイナー以外もたくさん参加してくれました!

反省と感想

開発環境作りやドキュメントを作りながら、どのような順序でチュートリアルを進め、どのような説明をどのタイミングで伝えたらVue.js初学者にとって分かりやすい勉強会になるかを考えて準備を進めてきました。

実際にVue Boot Camp当日を迎えてみると、進行していくことに精一杯で、参加メンバーの進捗具合など見れない部分が多かったのですが、Frontend Groupのメンバーがフォローに回ってくれたり、Vue Boot Camp専用のSlackチャンネルの中で、参加メンバー同士で参考となるリンクや追加の課題を共有し合ったり、とサポートしてくれたおかげで会を円滑に進めることができました。

f:id:chiiichell:20181225130942p:plain:w300

参加者の感想のコーナー

  • 楽しかったです!追加の課題なんかも丁度良い難易度に感じました。
  • 第二回目があれば是非参加したいと思います。
  • 題材がちょうど良かったです。
  • ある程度人集まってしたので色々フォローしてもらったり解説してもらったりすごく有意義でした。
  • 業務でそれなりに使ってる方だったのでまあまあ自信もって臨みましたが、改めてこうやってステップバイステップでやっていく中で、結構基本的なところで理解できてなかった点が色々と発見できたので非常に良い機会でした!

このような声をもらうことができたので、第二回目も開催できたら、と思います。

また、今回の記事がBASEアドベントカレンダーの最終日ということで、今までに公開された記事の一覧をご紹介します!

日付 タイトル
12/1(土) エンジニアとしてワクワクし続けるためのエンジニアリングマネージャという役割分担
12/2(日) 君は GitHub の Suggested change を知っているか?
12/3(月) 新任エンジニアリングマネージャ(私自身)を支えてくれた本と言葉
12/4(火) GoのAPI開発現場におけるユニットテストTips
12/5(水) BASE で使っているPHPフレームワークにプルリクエストを送ろうとしたら、先を越された話
12/6(木) 分位点回帰を使って、「その回帰予測どれぐらい外れるの?」を説明する
12/7(金) Abstractを用いたデザイン管理システムを導入して1年経ったお話
12/8(土) 「BASE」の管理画面リニューアルプロジェクトのこれまでとこれから
12/9(日) SQLアンチパターンとBtreeインデックスの関連性
12/10(月) 初めてでも実践できる、挫折しないテックブログ運営~半年間更新0→30本公開しました~
12/11(火) BASE株式会社を6年間経営して感じた学び
12/12(水) BASEがもっと好きになる。鶴岡さん観察日記
12/13(木) テストを書くモチベーションを上げるための、カバレッジレポート活用方法
12/14(金) デザイナーの私が初めてプロダクトのコードをコミットしてみた!
12/15(土) 日本のパパに、育休のススメ~私の育休体験記~
12/16(日) デザイン表現が広がる、Lottieアニメーション
12/17(月) グロースハックとディレクションとAndroid開発を経験した1年の振り返り
12/18(火) Data Strategy GroupのAPI開発の挫折とその後
12/19(水) 国内2019年のFinTechトレンド予想(融資・資金調達・ファイナンス領域編)
12/20(木) クラスタリングで時系列予測はできる? 〜Twitterの株価を予測してみた〜
12/21(金) 「Sketchを用いたデザインシステム」を作ってチームでのデザイン作業を効率化した話
12/22(土) ボドゲ最強説 ~BASEボードゲーム部のご紹介~
12/23(日) BASEのプロダクトマネージャーが大切にしている3つのこと
12/24(月) Goによる静的解析入門

それではみなさん、良いお年を!

Goによる静的解析入門

f:id:Imorley:20181223123414j:plain

この記事は「BASE Advent Calendar 2018」24日目の記事です。

devblog.thebase.in

はじめに

BASEでエンジニアとしてインターンをしている池田です。今日はクリスマスイブということで、以前から気になっていたグリューワイン(ドイツのクリスマスに欠かせないホットワイン)をクリスマスマーケットに飲みに来ています。

普段はBASE BANKというBASEの100%子会社にて金融事業の立ち上げを行っています。BASE BANKのプロダクトのAPIはGoを使って書かれているのですが、BASEでのGoの使用はこのプロジェクトが初だったので、開発基盤整備の一貫で様々なlinterの導入を行いました。その際にlinterの内部がどうなっているかに興味を持ち、すごく簡単なlinterの仕組みを実際に作ってみたので、今回はその知見をお話しします。

Goと静的解析

Goには、標準パッケージとして静的解析を行うためのgoパッケージが存在します。 また何よりGoは文法がシンプルな静的型付け言語なので、静的解析をとても簡単に行うことができました。

今回はその中でも、字句解析を行うgo/token、構文解析を行いAST(abstract syntax tree: 抽象構文木)を取り扱うgo/astgo/parserパッケージを用います。

今回は、megacheckというlinterを用いた際に実際に注意された、

bool値で条件分岐するときは、
if x == false {...}
じゃなくて
if !x {...}
の方がいい

といったことを検出してみたいと思います。 今回の静的解析の簡単な流れを下図に示します。 f:id:Imorley:20181223121212p:plain

抽象構文木のノードを探索していき、条件に当てはまるものがあったら警告するといった感じです。

やってみる

では実際にコードを見ていきましょう。 下がコード全体です。少しずつ解説していきます。

func main() {
    // 指定したファイルの構文解析を行う
    fset := token.NewFileSet()
    f, err := parser.ParseFile(fset, "sample.go", nil, 0)
    if err != nil {
        log.Fatal("Error:", err)
    }

    // 抽象構文木を探索する
    ast.Inspect(f, func(n ast.Node) bool {

        // 二項演算子ではない場合は無視
        expr, ok := n.(*ast.BinaryExpr)
        if !ok {
            return true
        }

        // == の場合
        if expr.Op == token.EQL {

            xIdent, ok := expr.X.(*ast.Ident) // Expr型をast.Ident型に型アサーション
            if !ok {
                return true
            }
            yIdent, ok := expr.Y.(*ast.Ident) // Expr型をast.Ident型に型アサーション
            if !ok {
                return true
            }

            // 識別子を文字列として取り出す
            xString := xIdent.String()
            yString := yIdent.String()

            switch yString {
            case "true":
                fmt.Printf("- got: %s == %s\n+ want: %s\n", xString, yString, xString)
            case "false":
                fmt.Printf("- got: %s == %s\n+ want: !%s\n", xString, yString, xString)
            }

            return true
        }

        return true
    })
}

ファイルの読み込みと構文解析

// 指定したファイルの構文解析を行う
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "sample.go", nil, 0)
if err != nil {
    log.Fatal("Error:", err)
}

まずはsample.goというファイルを指定してparser.ParseFileにより構文解析を行います。

package main

func sample() {
    isAvailable := false
    if isAvailable == false {
        return
    }
}

ここで、「あれ、まず字句解析しないの?」と思った方もいらっしゃるかもしれません。 実はgo/parserパッケージが内部で字句解析を行うため、直接字句解析を行うことはあまりないのです。

抽象構文木の探索

続いて、構文解析した結果により作られた抽象構文木を扱います。

// 抽象構文木を探索する
ast.Inspect(f, func(n ast.Node) bool {
        ...
    }
)

ast.Inspectは抽象構文木のノードをトラバースする関数です。この中のfunc(n ast.Node) bool { ... }で、抽象構文木の各ノードに対して一律の処理をかけます。 実際にどのような処理をするか見ていきましょう。

// 二項演算子ではない場合は無視
expr, ok := n.(*ast.BinaryExpr)
if !ok {
    return true
}

まずはast.Node型のノードをast.BinaryExpr型に変換しています。 ast.BinaryExprは+==などのような二項演算子を表す型です。今回はx == falseのような箇所を検出したいので、この型に変換できない場合は無視して次に進みます。(なぜ最初にast.BinaryExp型に変換できるノードを探しているのかは下で説明します)

ast.BinaryExprは以下のような構造体です。

type BinaryExpr struct {
    X     Expr        // 左のオペランド
    OpPos token.Pos   // オペレーターの位置(ファイルの何行目の何バイト目か)
    Op    token.Token // オペレーター
    Y     Expr        // 右のオペランド
}

また下図は二項演算を抽象構文木にした場合の図で、BinaryExpr構造体のフィールド(X, Y, Op)との対応が見て取れると思います。 f:id:Imorley:20181223121042p:plain

図を見てわかる通り、二項演算では演算子が親ノード、オペランドが子ノードになるため、このステップではまずast.BinaryExp型に変換できるノードを探していました。

続いて、上記の結果返ってきたast.BinaryExp型の値に対して処理をかけます。

// == の場合
if expr.Op == token.EQL {

    xIdent, ok := expr.X.(*ast.Ident) // ast.Expr型をast.Ident型に型アサーション
    if !ok {
        return true
    }
    yIdent, ok := expr.Y.(*ast.Ident) // ast.Expr型をast.Ident型に型アサーション
    if !ok {
        return true
    }

    // 識別子を文字列として取り出す
    xString := xIdent.String()
    yString := yIdent.String()

    switch yString {
    case "true":
        fmt.Printf("- got:  %s == %s\n+ want: %s\n", xString, yString, xString)
    case "false":
        fmt.Printf("- got:  %s == %s\n+ want: !%s\n", xString, yString, xString)
    }

    return true
}

今回は簡単にx == yのような部分だけ検出したいので、まずオペレーターOptoken.Token型の==と等しいか調べています。 そしてオペレーターが==だった場合に、次は各オペランドをast.Identという型に変換しているのがわかるかと思います。

ここでIdentが何かというと、識別子を表します。

f:id:Imorley:20181223121153p:plain

上図のように、字句解析のあとの変数名や関数名、bool値は識別子を表すast.Ident型、1"dog"など数値リテラルや文字リテラルはast.BasicLit型になります。 今回はある変数をboolと比較している箇所を評価したいため、その条件に合致するようなオペランド対を探しています。 あとは、該当するような箇所があったらその旨を出力して終わりです。

実際にsample.goにこのlinterをかけた結果を見てみましょう。

# go run main.go
- got:  isAvailable == false
+ want: !isAvailable

ご覧のように、sample.go内でbool値と直接比較している箇所を検出できています。

終わりに

今回は、標準の静的解析パッケージであるgoパッケージを使って簡単な静的解析ツールを試作してみました。 goパッケージを使えば、lintの他にもコードの自動生成や自動フォーマットをすることもできます。 またこのパッケージのソースコードを読むことでコンパイラや言語処理系の勉強にもなるので、静的解析はGoの中でも面白いトピックの一つなのではないでしょうか。

では、よいクリスマスをお過ごしください!

BASEのプロダクトマネージャーが大切にしている3つのこと

f:id:h7jin16:20181223113610j:plain

BASEの執行役員/Product Managerをしている神宮司(7jin16)です。

BASEのプロダクトマネージャーは、プロダクトの戦略、製品、事業数値まで責任を持ちます。

ユーザーの方々にどうしたら素晴らしい体験を届けることができるのかを悩みながら毎日淡々と会社全体でプロダクトを作っているため、プロダクト作りでとても重要だと思うことを書いていきます!

ポエムを書く

新プロダクトや新機能を作り始める前に実現したい理想の世界観についてのポエムを書くことが多いです。ポエムはあくまで Be Hopeful に書きます。深夜に書くとより叙情的に書けるのでオススメです。

ポエムを書くことによって自分たちが目指したい方向性が言語化されて、新プロダクトや新機能のコアバリューが設定されます。コアバリューが設定されていれば、タスクの優先順位が付けやすくなります。

ポエムによってチームもエモい気持ちで頑張ることが出来てテンションが上がります。 

優先順位の設定

施策の優先順位決めは、めちゃくちゃ大切です。すべての力を優先順位決めに使った方がいいんじゃないかと思うほど、超大切です。

プロダクトを作っていると、様々な目線でのフィードバックがありプロダクトの改善施策案はめちゃくちゃ出てきます。しかもサイズ感も改善される箇所も様々です。しかし時間は有限です。プロダクトマネージャーは常に効率的にユーザー体験を改善して事業数値、そして世の中にインパクトを与えていかなければなりません。

その中で適切に優先順位を設定していくのは難易度が高いです。

施策の優先順位を設定するときは、以下の3つを並べて考えます。

  1. リリースまでの時間軸(工数)
  2. 改善が期待できる効果(数値)
  3. 改善することによって積み上がる施策か

リリースまでにどれくらいの時間が必要か、これが短ければ短いほどより多くの改善を行うことができ、改善が期待できる効果が大きいほど、ユーザー体験を向上することができ、施策が積み上がれば積み上がるほど、他のプロダクトとの差が生まれます。

これを徹底的に考えていくことが大切です。どこかの目線に偏らず、3つの観点を考え続けて Move Fast に優先順位を設定し続けます。

優先順位設定は施策案が出てきた瞬間に決められることが重要であり、そのためにはプロダクト設計、事業数値、ポエムで作ったコアバリューへの解像度の高さが重要です。解像度を上げるためには数値が必要で、実際に起きている事象を常日頃から把握することが大切です。

優先順位を設定したら突き進みましょう。そして再現性を作るために結果を振り返り、軌道修正できるところは再度優先順位を設定して修正しましょう。

楽しむ

プロダクトを作っていると期待通りに改善されなかったり、ハプニングがあって計画が崩れてしまったり、意見がぶつかり合ったり、ウッ🤢となることも多々ありますが、楽しんでプロダクトを作ることが大切です。楽しめていないと作り続けることが難しいです。プロダクト作りは長距離走なので自分の感情と向き合って淡々とユーザー体験を良くしていきましょう。

自分が書いたポエムの世界観を信じていれば楽しく作り続けられます! 

おわりに

プロダクトマネージャーとしてプロダクトを作るときに重要だなと思っていることを書いてみました。3つしかなかったですが、ぼく自身全部完璧にできているわけではなく、日々トライ&エラーを繰り返しています。

Eコマースプラットフォーム「BASE」では、主なプロダクトとして、ネットショップ作成サービス「BASE」、ショッピングアプリ「BASE」の2つがありますが、まだプロダクトマネージャーがぼくしかおらず募集中ですので、ぜひ気軽にオフィスに遊びにきてください!

【BASE】プロダクトマネージャー / BASE株式会社

 

 

ボドゲ最強説 ~BASEボードゲーム部のご紹介~

これは「BASE Advent Calendar」22日目の記事です。

devblog.thebase.in

はじめに

こんにちは。BASEでサーバサイドエンジニアをしている柳川(@gimupop)です。直近では、即時に資金調達ができる金融サービス「YELL BANK(エールバンク)」というプロダクトの開発を行っていました。

さて本日ですが、技術ブログなんですが技術の話はしません。私が部長を務める社内の部活がすごく良いという話をします。

BASEには、CLUB BASEという部活動制度があります。共通の趣味を持つ社員が部署を超えて集まり、なにかしらの活動をすることを会社から補助を出す形で支援しています。一例としましてはランニング部とかボルダリング部といった活動内容が想像できるものから、日本酒部といった一見何をするかわからないものまで、様々な部活があります。

本日はその中でも僕が部長を務めるボードゲーム部について紹介させていただきます。

ボードゲーム部とは

さて、ボードゲーム部は何をする部活かといいますと、文字通りみんなでボードゲームをする部活です。活動内容がわかりやすい方の部活ですね。

基本的な活動としては、週に一回水曜日の業務後、会社の会議室でボードゲームをしています。 月に一回行われるBASEの締め会の日も活動していて、ここで普段ボードゲーム部に参加していない人と交流したりもしています。

また、他社のボードゲーム好きを会社に招いて開催したり、夏は湯河原で合宿も行いました。合宿では夕方から明け方までひたすらボードゲームをやってました。

f:id:gimutokenri:20181221143852j:plain
合宿の様子

BASEのボードゲーム部には、生粋のボードゲーム好きから、普段あまりボードゲームをしない人たちまで様々な人がいます。要するに懐が深いです。

ボードゲーム部のここが良い

1.手軽

会社にボードゲームがあるので、思い立ったときにさっとできます。運動系の部活のように着替えなどを用意する必要がありません。

2.業務で関わりのない人と仲良くなれる

これは部活全般に言えることなのですが、BASEの部活では基本的に複数部署から人を集めて活動することが推奨されています。そのため、普段業務で関わることのないあの人やその人と仲良くなることができます。

3.普通に話をしただけではわからないみんなの考え方がわかる

「業務で関わりのない人と仲良くなれるっていっても。何を話したら良いかわからないよ。」
そういう声もあると思います。でも安心してください。ボードゲームがそれを解決してくれます。

とりあえずそこにあるボードゲームをやりましょう。気の利いた会話はできなくてもボードゲームを通してお互いのことが理解できるはずです。

この人は割と素直にカードを出していくなとか、あの人は相手の動きをよく見てうまい手を打っているな、などなどその人の様々な側面を垣間見ることができます。

4.楽しい

何より大切なことですが、ボードゲームは楽しいです。

サイコロの目に一喜一憂したり、どちらのカードを出すか延々と考えてうまくいったり間違えたり。最初に描いてた戦略が潰されても諦めずに次の手を探して買ったり負けたり。全力で頭使ってみんなでなにかやる。そういったことが手軽にできるのがボードゲームの良いところかなと思います。

5.あらゆる場面でゲームをしっかり理解する能力を磨ける

弊社代表の鶴岡が先日のブログ記事で「王将を取ることが勝利」と言っていたように、今自分がどのようなゲームを戦っているのか理解することは重要です。 ボードゲームをプレイすることを通して、何をすれば勝利できるのかという本質をまず把握することと、そのためにいま何をすべきかを考えるくせが付きます。普段の業務に置き換えれば、どうすればプロジェクトが成功するのか、成功とはなにか、の定義がスムーズにできるようになるといったように仕事にも役立つのです。

ボードゲーム部を作りたくなったあなたへ おすすめボードゲームたち

さて、ここまでボードゲーム部について語りましたが、皆さんボードゲームをやりたくなってきたのではないでしょうか?

「でも、ボードゲームっていってもたくさんあるから何を選んだら良いかわからないよ。」
そういった声もあると思います。でも安心してください。弊社ボードゲーム部が誇る膨大なライブラリーの中から、厳選したボードゲームを紹介させていだきます。

f:id:gimutokenri:20181221141112j:plain
膨大なライブラリー。BASEでは部活動補助として毎月1万円補助が出るのでそれを購入費用に充てています。

ニムト

f:id:gimutokenri:20181221141441j:plain

プレイ人数:2~10人

概要

このゲームは弊社ボードゲーム部の大定番ゲームです。

10人まで参加でき、しかもルールが簡単なので、ボードゲームにあまり馴染みのない人でも楽しんでもらえると思います。大勢が集まる締め会や、合宿などでとても盛り上がるゲームです。

1から104まで数字が書かれたカードの中から10枚ずつをそれぞれが持ち、一定のルールで並べていき、6番目に並ぶカードを出してしまった人が失点してしまうというゲームになります。

特に人数が多いと、何を出せば失点をせずに済むかという部分に運が絡んでくるので、初めて参加する人でも楽しめると思います。

カードを一斉に出したあと、並べていく際には、 「まさかこのカードで失点するとは・・・。」 「ギリギリセーフ!」 といった阿鼻叫喚が聞こえてきてとても盛り上がります。

コードネーム

f:id:gimutokenri:20181221141540j:plain

プレイ人数:2~8人

概要

ボードゲームと言うと、計算が早かったり、論理的思考が得意な人が強いという先入観があるかもしれません。しかしこのゲームでは、チームでのコミュニケーションがとても大切です。そしてひらめきとそれを言葉で表現する力と、仲間が発した言葉を解釈する力が求められます。

簡単に説明すると、青チームと赤チームに別れて、並べられた25個の単語の中から複数ある自チームの単語を当てていくゲームです。リーダーが発する1つの単語から自チームの単語はどれかを当てていきます。1回のターンで複数の単語を当てていかなければ負けてしまうので、リーダーは複数の単語に共通するキーワードを連想するひらめき力とそれをチームメンバーが当てられるように表現する語彙力、単語チョイスセンスが求められ、メンバーはそれを解釈する力が重要になります。

言葉を発するリーダー側と当てるチーム側、お互いに相手のことを考えに考え抜いてゲームを進めていく必要があるので、自然と互いに親近感を持つと思います。

髑髏と薔薇

f:id:gimutokenri:20181221141511j:plain

プレイ人数:3~6人

概要

「髑髏と薔薇」は、いわゆるブラフゲームになります。

ものすごく簡単に説明すると、手持ちのカードを順番に裏側にして重ね、重ねられたカードをめくっていき、薔薇ならセーフ、髑髏ならアウトです。相手の手持ちのカードや進捗を考慮し、他の人が髑髏をめくるようにうまく仕向けるのがコツです。

このゲームはいかに相手を欺くか、という駆け引きを楽しむゲームです。ルールがシンプルで短時間でできるのに、勝てるまで何度も遊んでしまうゲームの一つです。

あまりはまり込むと、誰も信じられなくなります。

パンデミック

f:id:gimutokenri:20181221141431j:plain

プレイ人数:2~4人

概要

一般的にはボードゲームは参加者同士で戦うものです。しかしパンデミックは違います。みんなで協力して世界を救うゲームです。

プレーヤーは協力して、世界中で蔓延するウィルスを撲滅するために行動していきます。 そ れぞれ特徴を持つ役職を持っていて、 「この能力をこういうふうに使えば、最小限のリスクで進められる。」 「ここはリスク取らないと間に合わないよ。」 などコミュニケーションとりながら進めていきます。

共通の目的に対して挑むので、達成できれば、みんなが嬉しいし、達成できなくても、次はこうしようといったような話ができて、参加者の考え方がわかるようになるゲームです。

まとめ

以上、BASEのボードゲーム部の紹介でした。

ボードゲームはやりたいけど部活作るのは大変そう、周りにやる人がいない、やり方とかよくわからないという方は、気軽にBASEに遊びに来てください! メッセ待ってます! またボードゲーム購入の際はショッピングアプリ「BASE」をご利用いただけると嬉しいです!

明日はPMの神宮司です!お楽しみに!