TECH PLAY

BASE株式会社

BASE株式会社 の技術ブログ

587

この記事は「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/ast や go/parser パッケージを用います。 今回は、 megacheck というlinterを用いた際に実際に注意された、 bool値で条件分岐するときは、 if x == false {...} じゃなくて if !x {...} の方がいい といったことを検出してみたいと思います。 今回の静的解析の簡単な流れを下図に示します。 抽象構文木のノードを探索していき、条件に当てはまるものがあったら警告するといった感じです。 やってみる では実際にコードを見ていきましょう。 下がコード全体です。少しずつ解説していきます。 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)との対応が見て取れると思います。 図を見てわかる通り、二項演算では演算子が親ノード、オペランドが子ノードになるため、このステップではまず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 のような部分だけ検出したいので、まずオペレーター Op が token.Token 型の == と等しいか調べています。 そしてオペレーターが == だった場合に、次は各オペランドを ast.Ident という型に変換しているのがわかるかと思います。 ここでIdentが何かというと、 識別子 を表します。 上図のように、字句解析のあとの変数名や関数名、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の執行役員/Product Managerをしている神宮司( 7jin16 )です。 BASEのプロダクトマネージャーは、プロダクトの戦略、製品、事業数値まで責任を持ちます。 ユーザーの方々にどうしたら素晴らしい体験を届けることができるのかを悩みながら毎日淡々と会社全体でプロダクトを作っているため、プロダクト作りでとても重要だと思うことを書いていきます! ポエムを書く 新プロダクトや新機能を作り始める前に実現したい理想の世界観についてのポエムを書くことが多いです。ポエムはあくまで Be Hopeful に書きます。深夜に書くとより叙情的に書けるのでオススメです。 ポエムを書くことによって自分たちが目指したい方向性が言語化されて、新プロダクトや新機能のコアバリューが設定されます。コアバリューが設定されていれば、タスクの優先順位が付けやすくなります。 ポエムによってチームもエモい気持ちで頑張ることが出来てテンションが上がります。  優先順位の設定 施策の優先順位決めは、めちゃくちゃ大切です。すべての力を優先順位決めに使った方がいいんじゃないかと思うほど、超大切です。 プロダクトを作っていると、様々な目線でのフィードバックがありプロダクトの改善施策案はめちゃくちゃ出てきます。しかもサイズ感も改善される箇所も様々です。しかし時間は有限です。プロダクトマネージャーは常に効率的にユーザー体験を改善して事業数値、そして世の中にインパクトを与えていかなければなりません。 その中で適切に優先順位を設定していくのは難易度が高いです。 施策の優先順位を設定するときは、以下の3つを並べて考えます。 リリースまでの時間軸(工数) 改善が期待できる効果(数値) 改善することによって積み上がる施策か リリースまでにどれくらいの時間が必要か、これが短ければ短いほどより多くの改善を行うことができ、改善が期待できる効果が大きいほど、ユーザー体験を向上することができ、施策が積み上がれば積み上がるほど、他のプロダクトとの差が生まれます。 これを徹底的に考えていくことが大切です。どこかの目線に偏らず、3つの観点を考え続けて Move Fast に優先順位を設定し続けます。 優先順位設定は施策案が出てきた瞬間に決められることが重要であり、そのためにはプロダクト設計、事業数値、ポエムで作ったコアバリューへの解像度の高さが重要です。解像度を上げるためには数値が必要で、実際に起きている事象を常日頃から把握することが大切です。 優先順位を設定したら突き進みましょう。そして再現性を作るために結果を振り返り、軌道修正できるところは再度優先順位を設定して修正しましょう。 楽しむ プロダクトを作っていると期待通りに改善されなかったり、ハプニングがあって計画が崩れてしまったり、意見がぶつかり合ったり、ウッ🤢となることも多々ありますが、楽しんでプロダクトを作ることが大切です。楽しめていないと作り続けることが難しいです。プロダクト作りは長距離走なので自分の感情と向き合って淡々とユーザー体験を良くしていきましょう。 自分が書いたポエムの世界観を信じていれば楽しく作り続けられます!  おわりに プロダクトマネージャーとしてプロダクトを作るときに重要だなと思っていることを書いてみました。3つしかなかったですが、ぼく自身全部完璧にできているわけではなく、日々トライ&エラーを繰り返しています。 Eコマースプラットフォーム「BASE」では、主なプロダクトとして、ネットショップ作成サービス「BASE」、ショッピングアプリ「BASE」の2つがありますが、まだプロダクトマネージャーがぼくしかおらず募集中ですので、ぜひ気軽にオフィスに遊びにきてください! binc.jp    
これは「BASE Advent Calendar」22日目の記事です。 devblog.thebase.in はじめに こんにちは。BASEでサーバサイドエンジニアをしている柳川( @gimupop )です。直近では、即時に資金調達ができる金融サービス「 YELL BANK(エールバンク) 」というプロダクトの開発を行っていました。 さて本日ですが、技術ブログなんですが技術の話はしません。私が部長を務める社内の部活がすごく良いという話をします。 BASEには、CLUB BASEという部活動制度があります。共通の趣味を持つ社員が部署を超えて集まり、なにかしらの活動をすることを会社から補助を出す形で支援しています。一例としましてはランニング部とかボルダリング部といった活動内容が想像できるものから、日本酒部といった一見何をするかわからないものまで、様々な部活があります。 本日はその中でも僕が部長を務めるボードゲーム部について紹介させていただきます。 ボードゲーム部とは さて、ボードゲーム部は何をする部活かといいますと、文字通りみんなでボードゲームをする部活です。活動内容がわかりやすい方の部活ですね。 基本的な活動としては、週に一回水曜日の業務後、会社の会議室でボードゲームをしています。 月に一回行われるBASEの締め会の日も活動していて、ここで普段ボードゲーム部に参加していない人と交流したりもしています。 また、他社のボードゲーム好きを会社に招いて開催したり、夏は湯河原で合宿も行いました。合宿では夕方から明け方までひたすらボードゲームをやってました。 合宿の様子 BASEのボードゲーム部には、生粋のボードゲーム好きから、普段あまりボードゲームをしない人たちまで様々な人がいます。要するに懐が深いです。 ボードゲーム部のここが良い 1.手軽 会社にボードゲームがあるので、思い立ったときにさっとできます。運動系の部活のように着替えなどを用意する必要がありません。 2.業務で関わりのない人と仲良くなれる これは部活全般に言えることなのですが、BASEの部活では基本的に複数部署から人を集めて活動することが推奨されています。そのため、普段業務で関わることのないあの人やその人と仲良くなることができます。 3.普通に話をしただけではわからないみんなの考え方がわかる 「業務で関わりのない人と仲良くなれるっていっても。何を話したら良いかわからないよ。」 そういう声もあると思います。でも安心してください。ボードゲームがそれを解決してくれます。 とりあえずそこにあるボードゲームをやりましょう。気の利いた会話はできなくてもボードゲームを通してお互いのことが理解できるはずです。 この人は割と素直にカードを出していくなとか、あの人は相手の動きをよく見てうまい手を打っているな、などなどその人の様々な側面を垣間見ることができます。 4.楽しい 何より大切なことですが、ボードゲームは楽しいです。 サイコロの目に一喜一憂したり、どちらのカードを出すか延々と考えてうまくいったり間違えたり。最初に描いてた戦略が潰されても諦めずに次の手を探して買ったり負けたり。全力で頭使ってみんなでなにかやる。そういったことが手軽にできるのがボードゲームの良いところかなと思います。 5.あらゆる場面でゲームをしっかり理解する能力を磨ける 弊社代表の鶴岡が先日の ブログ記事 で「王将を取ることが勝利」と言っていたように、今自分がどのようなゲームを戦っているのか理解することは重要です。 ボードゲームをプレイすることを通して、何をすれば勝利できるのかという本質をまず把握することと、そのためにいま何をすべきかを考えるくせが付きます。普段の業務に置き換えれば、どうすればプロジェクトが成功するのか、成功とはなにか、の定義がスムーズにできるようになるといったように仕事にも役立つのです。 ボードゲーム部を作りたくなったあなたへ おすすめボードゲームたち さて、ここまでボードゲーム部について語りましたが、皆さんボードゲームをやりたくなってきたのではないでしょうか? 「でも、ボードゲームっていってもたくさんあるから何を選んだら良いかわからないよ。」 そういった声もあると思います。でも安心してください。弊社ボードゲーム部が誇る膨大なライブラリーの中から、厳選したボードゲームを紹介させていだきます。 膨大なライブラリー。BASEでは部活動補助として毎月1万円補助が出るのでそれを購入費用に充てています。 ニムト プレイ人数:2~10人 概要 このゲームは弊社ボードゲーム部の大定番ゲームです。 10人まで参加でき、しかもルールが簡単なので、ボードゲームにあまり馴染みのない人でも楽しんでもらえると思います。大勢が集まる締め会や、合宿などでとても盛り上がるゲームです。 1から104まで数字が書かれたカードの中から10枚ずつをそれぞれが持ち、一定のルールで並べていき、6番目に並ぶカードを出してしまった人が失点してしまうというゲームになります。 特に人数が多いと、何を出せば失点をせずに済むかという部分に運が絡んでくるので、初めて参加する人でも楽しめると思います。 カードを一斉に出したあと、並べていく際には、 「まさかこのカードで失点するとは・・・。」 「ギリギリセーフ!」 といった阿鼻叫喚が聞こえてきてとても盛り上がります。 コードネーム プレイ人数:2~8人 概要 ボードゲームと言うと、計算が早かったり、論理的思考が得意な人が強いという先入観があるかもしれません。しかしこのゲームでは、チームでのコミュニケーションがとても大切です。そしてひらめきとそれを言葉で表現する力と、仲間が発した言葉を解釈する力が求められます。 簡単に説明すると、青チームと赤チームに別れて、並べられた25個の単語の中から複数ある自チームの単語を当てていくゲームです。リーダーが発する1つの単語から自チームの単語はどれかを当てていきます。1回のターンで複数の単語を当てていかなければ負けてしまうので、リーダーは複数の単語に共通するキーワードを連想するひらめき力とそれをチームメンバーが当てられるように表現する語彙力、単語チョイスセンスが求められ、メンバーはそれを解釈する力が重要になります。 言葉を発するリーダー側と当てるチーム側、お互いに相手のことを考えに考え抜いてゲームを進めていく必要があるので、自然と互いに親近感を持つと思います。 髑髏と薔薇 プレイ人数:3~6人 概要 「髑髏と薔薇」は、いわゆるブラフゲームになります。 ものすごく簡単に説明すると、手持ちのカードを順番に裏側にして重ね、重ねられたカードをめくっていき、薔薇ならセーフ、髑髏ならアウトです。相手の手持ちのカードや進捗を考慮し、他の人が髑髏をめくるようにうまく仕向けるのがコツです。 このゲームはいかに相手を欺くか、という駆け引きを楽しむゲームです。ルールがシンプルで短時間でできるのに、勝てるまで何度も遊んでしまうゲームの一つです。 あまりはまり込むと、誰も信じられなくなります。 パンデミック プレイ人数:2~4人 概要 一般的にはボードゲームは参加者同士で戦うものです。しかしパンデミックは違います。みんなで協力して世界を救うゲームです。 プレーヤーは協力して、世界中で蔓延するウィルスを撲滅するために行動していきます。 そ れぞれ特徴を持つ役職を持っていて、 「この能力をこういうふうに使えば、最小限のリスクで進められる。」 「ここはリスク取らないと間に合わないよ。」 などコミュニケーションとりながら進めていきます。 共通の目的に対して挑むので、達成できれば、みんなが嬉しいし、達成できなくても、次はこうしようといったような話ができて、参加者の考え方がわかるようになるゲームです。 まとめ 以上、BASEのボードゲーム部の紹介でした。 ボードゲームはやりたいけど部活作るのは大変そう、周りにやる人がいない、やり方とかよくわからないという方は、気軽にBASEに遊びに来てください! メッセ 待ってます! またボードゲーム購入の際は ショッピングアプリ「BASE」 をご利用いただけると嬉しいです! 明日はPMの神宮司です!お楽しみに!
こんにちは。BASEでサーバーサイドエンジニアをやっている、東口( @higasgt )です。 先日、「 PHPカンファレンス2018 」が開催されました。事前申し込みが2,000人超えというたいへん盛り上がったカンファレンスでした! 私は、当日セッション登壇したり、スポンサーとしてブース出展したり、運営スタッフをしたりして、大変楽しめたカンファレンスでした。 今日は、当日発表した内容やブースの様子について話したいと思います。 PHPカンファレンス2018 改めて、 PHP Conference 2018 とは、国内のPHPエンジニアが一斉に集まるテックカンファレンスです。 今年のテーマは「GROWTH」 今回、個人として公募で、25分セッション・LTの2枠で発表させていただき、BASEとしてもゴールドスポンサーとして協賛させていただきました。 発表内容 今回、25分セッション・LTの2つを採択いただいたので、2回壇上に上がることができました。 PHPバージョンアップと決済リプレイスを支えたユニットテスト 25分セッションにて発表した資料です。 ユニットテストについて次の2点をテーマにまとめた内容です。 テストがないコードにどうテストを書くか テストがないコードを生まないための考え方 私が入社してからの約1年間で起きたコードベースの変化と、それに対応して発生する課題と対策について、ユニットテストという観点でまとめさせていただきました。 セッション発表中 25分に無理やり凝縮して押し込んだ内容だったので、Q&Aの時間がとれなかったのですが、その後BASEのブースに来て質問していただいたりして大変ありがたい反響をいただけました。 発表駆動開発を一年間実践してきて今 LT大会にて発表した資料です。 私は、2017年10月にBASEに入社してから勉強会・イベントに参加できる時間が増えたこともあり、20本ほどLTやセッション発表をしてきました。 がっつり量をこなしてみた結果、「発表する」という行為自体が技術力向上にとても有益だと改めて感じています。 それを一言「発表駆動開発はええぞ!」の一テーマでまとめたものになります。 LT中 懇親会で、この発表フックで話しかけていただく機会が多く、「人見知りでも懇親会が楽しめる」という発表駆動開発のメリットを改めて時間しました。(話しかけていただいた方々本当にありがとうございます。。。) ブースの様子 BASEは、ゴールドスポンサーとして協賛しておりましたので、ブース出展もさせていただいていました。 ノベルティとして、ネットショップ作成サービス「BASE」をご利用いただいている 京都ぎょくろのごえん茶 さんのお茶を準備いたしました。 準備していたノベルティなどの配布物を配りきってしまうほど、たくさんのPHPerの方にお会いすることができ、大変楽しい時間となりました。 最後に 今回、少しだけカンファレンススタッフのお仕事も手伝わせていただきましたが、1年前から業務で忙しい中時間を割いて準備してくださっている方々がいるからこそ、PHPカンファレンスが開催できていることを改めて感じました。 運営委員会の皆様、本当にお疲れ様でした! また、2018年もそろそろ終わりですが、PHPerの年明けは早いことに、2019年1月26日に、「 PHPカンファレンス仙台2019 」が開催されますね。 こちらでは、「テストを書くのが辛くならないテスト駆動開発のアプローチ」というセッション発表・BASEとしてシルバースポンサーとしての協賛をします。 ぜひ、2019年1月26日、仙台でお会いしましょう!
この記事は、「 BASE Advent Calendar 2018 」の21日目の記事です。 devblog.thebase.in はじめまして。2018年2月にBASE株式会社へデザイナーとして入社した小山です。 技術ブログを書くのは初めてなのですが、今回は私が2月に入社してから今日までネットショップ作成サービス「BASE」で「Sketchを用いたデザインシステム」を作ってチームでのデザイン作業を効率化した話について書こうと思います。 入社当時の状況 私が入社した当時、デザインチームは人数が増え始めた時期で、大きな課題が2つありました。 デザインデータの管理 私が入社する前まではプロダクトに対してデザインデータを作るデザイナーが少なく、各デザイナーが個人のローカルでファイル管理をしていました。その為、誰がどの画面のデザインデータを持っていて、最新のデータがどれなのかを毎回メンバーに確認をして、最新のデータを送ってもらわないとデータを見ることができないという状況でした。 ファイル管理については、Abstractの導入でファイル管理とバージョン管理の問題を解決しました。この内容については12月7日の「 Abstractを用いたデザイン管理システムを導入して1年経ったお話 」で北村が詳しく書いているので興味のある方はぜひ読んでみてください。 デザインパーツの共通化 もう一つはデザインパーツがデザイン的にもデータ的にも共通化されていなかったことです。 当時のBASEは新旧のデザインが入り混じっており、どのパーツが最新のものでどのレイアウトに合わせて作っていいかが入社したての私には難しいものでした。また、コーディング用のスタイルガイドはあったものの、Sketch用のデータはなかった為、毎回パーツを作るかそのパーツを含むファイルを探してコピーしてくる必要がありました。 そこでSketchとAbstractのLibrary機能を使ってSketchを用いたデザインシステム(通称:BASE UI kit)を作る「UI コンポーネントプロジェクト」が立ち上がりました。 UI コンポーネントプロジェクト始動 BASE UI kit 作成にあたり、デザインチーム内の管理画面に関わるデザイナーとフロントエンドエンジニアでプロジェクトを2月末に立ち上げ、毎週定例ミーティングをしながら必要なデザインパーツの洗い出しを行いUI コンポーネントとしての仕様決めを行っています。 はじめに作ったBASE UI kit は1ファイルでPC、SPの全てのコンポーネントを管理しており、pageもグループごとに分けていました。 しかし、BASEの管理画面ではコンポーネントの数も多く、レイアウト側のデザインもファイル数が膨大になり、次第に管理が難しくなっていきました。 BASE UI kit 大改修 今まで1つのプロジェクトですべてのファイルを管理していましたが、BASE UI kit は専用プロジェクトに分離してAbstractのLink Library 機能を使って別のプロジェクトへリンクさせ、さらに1ファイルで管理していたコンポーネントはcommon、PC、SPの3ファイルで管理するように大改修しました。 また、BASE UI kit を大改修する一環として、コンポーネントの命名規則もAtomic Designのレベル分けでグルーピングして参照しやすいものに変更しました。(例:1 = Atoms、 2 = Molecules ) BASE UI kit を別プロジェクトにしたメリット BASE UI kit の編集をしたブランチをマージする度に他の各ブランチで変更をPullする必要がなくなった 右上に出てくる「Library Updates Available」をクリックするだけで最新のコンポーネントに更新できるようになった 個人の作業ブランチでBASE UI kitの編集ができなくなったことで、そのブランチがマージされるまで他のブランチで最新のコンポーネントが使えないという問題が起きなくなった(運用でカバー仕切れなかった問題が解決) ファイル分割したメリット コンポーネントを呼び出す時に階層を減らすことができた 1ファイル内のコンポーネント数が減ってコンポーネントを探すのが楽になった その他にもBASE UI kit以外のデザインデータもグループ分けをしてプロジェクトを分けて管理することで、担当外プロジェクトのAbstractのシンクを切ることができます。(これによりAbstractとSketchが軽くなったような気がします。※個人の感想です。) 大改修をする時の注意点 一度作成したBASE UI kitを別プロジェクトへ移行してファイルを分割する際に注意するべきことがいくつかありました。 BASE UI kitとして登録しているシンボルは一度ファイルから消してしまうと呼び出し先でリンクが切れる(つまりカット&ペーストした時点でそのシンボルはリンク切れになる) 既にライブラリ化済みのBASE UI kit(旧 BASE UI kit)を別ファイルの BASE UI kit(新 BASE UI kit)にリンクする場合、呼び出し先のデザインファイルでリンクが切れる前に新 BASE UI kit のコンポーネントへシンボルを置き換える作業が必要 大改修をする時に便利だったSketch プラグイン Symbol Organizer レイアウトされたシンボルを別ファイルのシンボルに一括で置き換えてくれるプラグインです。 同じ名前のシンボル同士を置き換えるのでシンボルの名前を変更するタイミングには注意してください。 Rename It コンポーネントの階層を整理したい時にシンボルの名前を一括変更できるのでとても便利なプラグインです。 今回はUI kitの階層も合わせて整理したのでとてもお世話になりました。 大改修の手順 Abstract上の全てのブランチをmasterへマージする Abstractで BASE UI kit 専用プロジェクトを作る 既にライブラリ化済みのBASE UI kit(旧 BASE UI kit) をBASE UI kit専用プロジェクトへコピーする BASE UI kit専用プロジェクトへコピーした新 BASE UI kitの中身を整理する(シンボル名は絶対変えない!) BASE UI kit専用プロジェクト以外のデザインプロジェクトに新 BASE UI kitを Link Libraryで紐づける デザインデータを開き、プラグインのSymbol Organizerを使って旧 BASE UI kit を新 BASE UI kitに置き換える(すべてのデザインデータで同じことをする) 新 BASE UI kitのシンボル名をプラグインのRename Itを使って整理する 現在、BASE UI kitの運用はこれで落ち着いています。 シンボル名の変更はシンボルを置き換える前とかでなければいつでもできるので、足りないコンポーネントが増えて階層を整理したくなったタイミングや、Atomic Design的にここじゃないよねって思ったタイミングで適宜修正しています。 まとめ UI コンポーネントをきちんと定義したことでデザイナー間やフロントエンドエンジニア間での仕様の認識を揃えることができ、また、BASE UI kitを作ったことで、シンボルを呼び出すだけで統一された UI コンポーネントを使うことができるのでデザイン作業が格段に早くなったと思います。 途中でUI kitの大改修もありましたが、毎日使うものだからこそストレスが少ないかたちで運用できる方が楽しく仕事ができるんじゃないかなと思います。(大変だったけどやってよかった!) 明日は ボドゲ部の部長 柳川です!
これは「 BASE Advent Calendar 2018 」の20日目の記事です。 devblog.thebase.in こんにちは。Data Strategy Group の岡です。趣味は珍しいお酒を飲むこと、将来の夢はウイスキーの蒸留所を持つことです。 私は機械学習エンジニアとしてまだ2年目なのですが、「この予測手法、本やweb上でほとんど見かけないな。」とずっと気になっている手法があります。ざっくり説明すると、時系列データをクラスタリングして同クラスタ内の平均を予測に使う、というもので、私より20くらい歳上の分析屋に教えてもらいました。下記の論文が一番これに近いと思います。 「 Time Series Forecasting through Clustering - A Case Study 」 今回は実験も兼ねてその予測手法を再現しようと思います。 使用データ そういえば、昨日は @Toshi_Day1 のFintechについての記事があり、先日の河越の 鶴岡さん観察日記 ではジャック・ドーシー氏の話題があったので、この流れで Twitterの株価 を予測してみましょう。 ナスダック のサイトから5年分の日次株価データをダウンロードしました。 ここから直近30日分を検証データとして切り出し、それ以前のデータを学習データとして使います。 #!/usr/bin/env python3 # モジュール import numpy as np import pandas as pd from sklearn.cluster import KMeans from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler from sklearn.metrics import mean_squared_error from matplotlib import pylab as plt # 読み込み & 日付でソート twtr_stock = pd.read_csv( 'twtr_stock.csv' ).sort_values( 'date' ).reset_index(drop= True ) # 末尾30件を検証データとして分割 train_df = twtr_stock[ 0 :- 30 ].reset_index(drop= True ) test_df = twtr_stock[- 30 :].reset_index(drop= True ) 先頭数件は下記のようになっています。 この中で close(終値) の値を予測していきます。 下のグラフはcloseの値を時系列でプロットした結果です。 plt.plot(twtr_stock[ 'close' ]) 前半大きく下り傾向があり、後半から徐々に上がり調子になっていますね。このデータから後に続く30日分のデータを予測することが今回の目標です。 予測の手順 この予測手法を直感的に説明してしまうと、 1. 時系列データを等間隔でスライドさせながらカーブを切り出して 2. それらを形状の似ているもの同士でグルーピングし 3. 同じグループ内で末尾の株価だけ取り出し、その平均を予測値として扱う という流れになります。もう少し詳しく説明すると 時系列データから幅(N + K)のスライド窓の作成 スライド窓ごとに平均0、分散1に標準化 スライド窓の手前N個を PCA + k-means でクラスタリング 同クラスタ内で、N+K時点のデータの平均値を計算 cos類似度で近傍クラスタを求め、そのクラスタの平均値を予測に使う という手順になります。 1. 時系列データからスライド窓の作成 スライド窓とは、時系列データから一定の幅で1時点ずつスライドさせながら取り出して作るカーブのことです。下図がそのイメージになります。 スライド窓、だとわかりにくいので今後はカーブと呼んでしまいます。 ここで作られる複数のカーブを似ているもの同士でまとめ、末尾の値の平均で予測を行います。 今回は直近20日のデータから5日先のデータを予測するとします。(20 + 5)日分のデータで切り出したいので、幅25で1日ごとにスライドさせたデータセットを作成します。 TRAIN_SIZE = 20 TARGET_FUTURE = 5 WINDOW_SIZE = TRAIN_SIZE + TARGET_FUTURE def split_window_data (array, window_size): length = array.shape[ 0 ] roop_num = length - window_size + 1 window_data = np.stack([ np.hstack( np.array(array[i: i+window_size].astype( 'float64' )).reshape(window_size, 1 ) ) for i in range (roop_num) ]) return window_data train_close = np.array(train_df[ 'close' ]) window_data = split_window_data(train_close, WINDOW_SIZE) 2. カーブごとに標準化 カーブごとに切り出したデータは、あるものは(20 30 35 25 30)、別のものは(60 80 70 80 100)だったりとスケールが異なります。この生の値でクラスタリングを行うと、スケールの大きいもの同士でまとまってしまいますが、今回は時系列の形状や特徴が似ているもの同士でまとめる必要があります。 そのためカーブごとに「標準化」という操作を行い、平均0、分散1のスケールを統一してしまいます。 # 標準化 sc = StandardScaler() window_sc = np.stack([ np.hstack(sc.fit_transform(vec.reshape(WINDOW_SIZE, 1 ))) for vec in window_data ]) 標準化については下記が参考になります。 「 統計における標準化の意味と目的 」 3. PCA + k-means でクラスタリング ここからの手順を下図を使って説明します。同じ幅のカーブを冒頭で作成しましたが、今度はこれらを形の似ているもの同士でまとめていきます。 k-meansとはクラスタリングの一つで、数学的に似ている(数学的に距離が近い、と言ったりします)データを任意のグループに分類します。分類後のグループを「クラスタ」、各クラスタの重心に位置するデータを「代表ベクトル」と呼びます。代表ベクトルも後の計算で使うため、ここで算出しておきます。クラスタリングの後、分類時には外していた末尾のデータの平均値を計算します。末尾というのは、今回でいうと25日分のカーブのうち末尾5日分のデータのことです。 細かい話になるので上図には記載しなかったのですが、今回の予測ではPCAという処理を通してからk-meansを実行します。なぜPCAが必要か、については記事末尾の補足にて記載しております。 クラスタリングの実行 それでは、PCA + k-means クラスタリングを行い、クラスタごとの平均値を計算していきます。 def curve_clustering (array, curve_len): train = np.stack([vec[ 0 :curve_len] for vec in array]) test = np.stack([vec[curve_len:] for vec in array]) test_len = test.shape[ 1 ] # PCA pca = PCA(n_components=curve_len) pca.fit(train) # 共分散行列から写像 cov_mtrx = pca.get_covariance() train_pca = np.dot(train, cov_mtrx) # あとで元に戻すため、共分散行列の逆行列を求めておく cov_mtrx_inverse = np.linalg.inv(cov_mtrx) # k-meansクラスタリング curve_clst_size = int (np.sqrt(train_pca.shape[ 0 ]/ 2 )) cls = KMeans(n_clusters=curve_clst_size, random_state= 123 ) curve_clst = cls.fit_predict(train_pca) # クラスタ毎に、カーブのリスト、平均、分散、代表ベクトルを求めておく curve_df = pd.DataFrame({ 'curve_clst' : curve_clst , 'train' : [vec for vec in train] , 'train_pca' : [vec for vec in train_pca] }) for i in range (test_len): curve_df[ 'test{}' . format (i)] = [vec[i] for vec in test] print ([col for col in curve_df.columns if 'test' in col]) curve_clst_dict = { cluster : { 'test_means' : [df[col].mean() for col in df.columns if 'test' in col] , 'test_medians' : [df[col].median() for col in df.columns if 'test' in col] , 'test_stds' : [df[col].std() for col in df.columns if 'test' in col] , 'train_cluster_center' : np.dot(cls.cluster_centers_[cluster].flatten(), cov_mtrx_inverse) , 'train_pca_cluster_center' : cls.cluster_centers_[cluster].flatten() , 'train_vectors' : [vec for vec in df[ 'train' ]] , 'train_pca_vectors' : [vec for vec in df[ 'train_pca' ]] } for cluster, df in curve_df.groupby( 'curve_clst' ) } return (curve_clst_dict, cls, pca) curve_clst_dict, cls, pca = curve_clustering(window_sc, TRAIN_SIZE) ここではクラスタ数を curve_clst_size = int (np.sqrt(train_pca.shape[ 0 ]/ 2 )) と決めていますが、理由は記事末尾の補足に少しだけ記載しております。 クラスタリングの結果の可視化 それらしい分類になっているか、クラスタ毎のカーブをまとめてプロットしていきます。 # グラフを行列形式で表示する clst_size = len (curve_clst_dict) row_size = int (clst_size/ 3 ) if clst_size% 3 == 0 else int (clst_size/ 3 ) + 1 x_axis = [x for x in range (WINDOW_SIZE - 1 )] fig = plt.figure(figsize=( 19 , 30 )) for key in curve_clst_dict: # カーブのリストを取り出す clst_info = curve_clst_dict[key] raw_curves = clst_info[ 'train_vectors' ] # subplotと行列番号の設定 row_n = int (key/ 3 ) col_n = key% 3 ax = plt.subplot2grid((row_size, 3 ), (row_n, col_n)) # カーブのプロット for raw_curve in raw_curves: ax.plot(raw_curve, color= 'steelblue' , alpha= 0.3 ) # 区間のプロット upper_95 = np.hstack([np.repeat(np.nan, TRAIN_SIZE- 1 ), np.array(clst_info[ 'test_means' ]) + 2 *np.array(clst_info[ 'test_stds' ])]) lower_95 = np.hstack([np.repeat(np.nan, TRAIN_SIZE- 1 ), np.array(clst_info[ 'test_means' ]) - 2 *np.array(clst_info[ 'test_stds' ])]) ax.fill_between(x_axis, upper_95, lower_95, facecolor= 'gray' , alpha= 0.4 ) # 平均値のプロット ax.plot( list (np.repeat(np.nan, TRAIN_SIZE- 1 )) + list (clst_info[ 'test_means' ]), color= 'coral' ) ax.set_title( 'curve cluster{}' . format (key)) plt.show() 実行結果は下記となります。 (本当はクラスタ23まであるのですが、長い上に結論も変わらないのでクラスタ8まで載せています。) 青色の線がカーブの集まりです。一つのクラスタを注視すると、変動の大きいカーブと小さいカーブが混在しつつも、大まかなトレンドは同一であると分かります。 オレンジの線がクラスタリングに使わなかったデータの平均値です。グレーは (平均 ± 2 * 標準偏差)の範囲を表しています。やや分散の大きいクラスタが多い印象です。 4. cos類似度で近傍クラスタを求める ここからの手順を下図を使って説明します。今度は、未知データがどのクラスタに近いかをcos類似度を用いて探します。 cos類似度とは、2つのベクトル(ここではカーブのこと)の類似度を測る指標です。上の図中では未知データのカーブと、各クラスタの代表ベクトル(青色の点線)を比較し類似度を計算しています。クラスタ1との類似度が高いと判定され、未知データのカーブの先に、クラスタ1の平均値(オレンジの点線)を当てはめて予測値としています。 それでは実際のデータで実行していきます。 最近傍のクラスタを見つける 下記のコードでは、2018年11月以前のデータを再びスライド窓に分割し、標準化しています。各クラスタの代表ベクトルとの類似度を求めるため、切り出す幅が TRAIN_SIZE になっている点が冒頭と異なります。 # TRAIN_SIZEで分割 window_data_train = split_window_data(train_close, TRAIN_SIZE) # 標準化 sc = StandardScaler() window_sc_train = sc.fit_transform(window_data_train.T).T 次に切り出したカーブのベクトルと、各クラスタの代表ベクトルの類似度を計算し、もっとも類似度が高いクラスタの番号を返す関数を作ります。 # cos類似度を計算する関数 def cos_sim (v1, v2): return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)) # もっとも類似度の高いクラスタの番号を返す関数 def calculate_neighbor_clst (window_vec, curve_dict): cos_sim_vec = np.array([ cos_sim(window_vec, curve_clst_dict[clst][ 'train_cluster_center' ]) for clst in curve_clst_dict ]) return cos_sim_vec.argmax() 最近傍クラスタから平均値の取り出し 続いて、最近傍クラスタの平均値を取り出します。取り出したらスケールを戻して予測値とします。 # もっとも近いクラスタの平均値を取り出す scaled_means = [] for vec in window_sc_train: neighbor_clst = calculate_neighbor_clst(vec, curve_clst_dict) scaled_mean = np.array(curve_clst_dict[neighbor_clst][ 'test_means' ][TARGET_FUTURE - 1 ]) scaled_means.append(scaled_mean) # 取り出した平均値を元のスケールに戻す scaled_means = np.array(scaled_means) pred_means = sc.inverse_transform(scaled_means) 以上で予測値を算出するところまでは完了です。次の節で予測がどれくらい当たってたのかを検証していきます。 5. 予測結果の評価 予測結果と実際の値をプロットしてみましょう。 act = train_close[WINDOW_SIZE:] pred = pred_means[ 0 :-TARGET_FUTURE- 1 ].flatten().tolist() plt.plot(act, label= 'act' ) plt.plot(pred, label= 'pred' ) plt.legend() 青色が実測値、オレンジが予測値です。すごく当たっているように見えますが、実は数日前のラグを取ったような予測になっています。これでは予測できたと言えません。 株価の「上昇する」か「下落する」かの予測 今回は直近20日のデータから5日先のデータを予測する、というテーマだったので、20日目の株価から5日先の株価が上がっているか、下がっているかの判定をしてみましょう。 # 20日目の株価と5日後の実際の株価を比べ、上がってるor下がってるか act_updown = [ train_close[i + WINDOW_SIZE] > train_close[i + TRAIN_SIZE] for i in range ( len (train_close) - WINDOW_SIZE) ] # 20日目の株価と5日後の予測株価を比べ、上がってるor下がってるか pred_updown = [ pred[i] > train_close[i + TARGET_FUTURE] for i in range ( len (train_close) - WINDOW_SIZE) ] 最初の act_updown には20日目と比較して5日後の実際の株価が上がったか、下がったかの真偽値を格納しています。次の pred_updown には5日後の予測の株価と比較した結果が入っています。この予想結果の正答率を計算していきます。 TF = (np.array(act_updown) == np.array(pred_updown)) sum (TF)/ len (TF) 結果は 51.8% でした!シンプルに株価の上下を予想してもほとんど当たってないですね笑 検証データと予測値の比較 今度は冒頭のほうで検証用に残していた、2018年11月以降の30日分の株価を予測してみましょう。 30日分の予測なので、ひとつずつ予測値をカーブに追加していきながら、最終的には20個の予測値を使って30日先の株価を予測することになります。 # スライド窓から予測値を算出する関数 def predict_ (window_vec, target_future): test_sc = StandardScaler() vec_sc = test_sc.fit_transform(window_vec.reshape(TRAIN_SIZE, 1 )).T neighbor_clst = calculate_neighbor_clst(vec_sc, curve_clst_dict) scaled_mean = np.array(curve_clst_dict[neighbor_clst][ 'test_means' ][target_future]).reshape(- 1 , 1 ) return test_sc.inverse_transform(scaled_mean.reshape(- 1 , 1 )) # 予測値を追加しながら、次点の値を予測 def predict_forward (window_vec, n_forward, target_future): predictions = [] vec_len = window_vec.shape[ 0 ] train_vec = window_vec.copy() for _ in range (n_forward): pred = predict_(train_vec, target_future).flatten() predictions.append(pred[ 0 ]) train_vec = np.append(train_vec[-vec_len + 1 :], pred) return predictions # テストデータの長さ分の予測値を算出 test_len = len (test_df) last_window = window_data_train[- 1 ] predictions = predict_forward(last_window, test_len, TARGET_FUTURE- 1 ) この予測を重ねた結果と、30日分の実測値をプロットした結果が下記となります。 plt.plot(test_df[ 'close' ], label= 'act' ) plt.plot(predictions, label= 'pred' ) plt.legend() 青色が実測値、オレンジの線が予測値です。実測値より予測値はなだらかな線になっています。やはり予測値を平均で代用しているので、変動の大きい時系列を捉えるのは不得意そうですね。 まとめ 株価を使う時点で予想してはいましたが、さっぱりうまくいきませんでした。この手法を教えてくれた人は「これで為替レートの予測がうまくいった!」と言っていたので、万に一つの可能性があって株の予想ができたら、、、と思いましたが現実は厳しいですね。 これの使いどころとしては、クラスタ毎にまとめた平均値、つまりノイズを省いたトレンドを検出できるので、下記のケースなら有効かもしれません。 局面変化の検知 長期ではなく短期の予測 件数の少ない時系列データに対し、傾向の似ている別の時系列データから予測値を算出 以上が、私の記憶と数少ない資料を頼りに再現した予想手法でした。これを読まれたどなたかが、「その分析知ってるけど使い方違うよ!」などご指摘くだされば何よりです。 明日はデザイナーの小山さんです!お楽しみに! 補足 PCAとk-meansの組み合わせ PCAとk-meansを組み合わせることでより綺麗にクラスタリングできるという、イケてる分析屋の間ではよく使われるテクニックだそうです。 私は最近まで知りませんでした。 PCAとk-meansの関係については、下記の資料が参考になるかと思います。 「 K-means Clustering via Principal Component Analysis 」 クラスタ数について 下記はk-meansを実行する部分のコードです。 def curve_clustering (array, curve_len): ~~~ # k-meansクラスタリング curve_clst_size = int (np.sqrt(train_pca.shape[ 0 ]/ 2 )) ~~~ ここでしれっとクラスタ数を (サンプルサイズ/2)の平方根で設定していますが、適切なクラスタ数が不明なときはこれで良かろう、という先人の知恵なんだそうです。以下のやりとりから文献にたどり着いたので、これから理解を深めていこうと思います。 「 How can we choose a "good" K for K-means clustering? 」
この記事は「BASE Advent Calendar 2018」19日目の記事です。 devblog.thebase.in はじめに こんにちは。BASEの100%子会社であるBASE BANKの矢部( @Toshi_Day1 )です。BASEの金融事業という立ち位置で先日リリースした、リスクなく即時に資金調達ができる金融サービス「 YELL BANK(エールバンク) 」を中心に複数の金融事業を立ち上げ責任者をしています。 今回、社をあげてのアドベントカレンダーということで、テックな内容ではありませんがFinTechについて少し書き連ねていきたいと思います。 ここ1年弱、消費者と事業者の混ざり合ったようなユーザー層への金融サービスに思いをめぐらせつつ、決済をコアとした事業構造のBASEに身を置き、またFinTech企業や金融機関の方々とお話させていただく中で学んできたことをもとに、来年のファイナンス領域におけるFinTechトレンドを予想したいと思います。 より多くの人にとって金融サービスが普遍的なものになり、個々人が想像力や可能性を広げることができる世の中を作るため、日々事業に向き合っています。このブログ記事を読んで、興味が湧いた方がいらっしゃれば、ぜひ気軽にご連絡ください。ディスカッションやブレストなども誘っていただければ嬉しいです。 ※Crypto、Blockchain、STOなどと、面白いと感じることも多いのですが、まだ勉強中のため割愛します。 ※この記事の内容はあくまで個人的な意見・見解を示したものです。 1. 個人やスモールビジネスが持つ資産を流動化し、換金性をあげるサービスが登場 個人の資産流動化の流れ 資産の現金化という意味では2017年の「CASH」を筆頭に、それまで行われていた「メルカリ」で物を売って現金に変える、という行為を簡略化するような形で即現金化サービスがでてきました。また2018年には給与の前払いサービスなどへ多くの事業者が参入していきました。このような消費者向けの少額資金ニーズが顕在化したことについては、個人的には仮想通貨の価格高騰により我々が認知する割引現在価値が大きく変化したからであると、こちらの note で考えてみたこともあります。 これらのビジネスに共通しているのは、個人のBSを想定したときに流動資産科目をキャッシュに変えるような機能であることと言えます。基本的には、引き続き2019年もこのトレンドが続いていくと考えていて、ブランド品や(パート・アルバイトを含めた)給与以外にも身の回りにある高単価な物品、あるいは無形材をバーティカルにカテゴリー化して換金できるような仕組みに挑戦する企業が出てくるのではないのでしょうか。タイミングはもう少し先だと思いますが、権利や契約関係、データなどのBSに反映されにくいものもブロックチェーン上で資産管理され、換金性が高まるような変化が起こるでしょう。 オンラインファクタリングサービスの登場 一方で、類似の仕組みを事業者に当てはめたサービスが2018年の下半期からぽつぽつとリリースされ始めています。もっとも多かったケースとしては、事業者が保有する売掛債権を譲渡することで資金調達をする"ファクタリング"のビジネスをオンライン化していくケースです。 直近の事例としては、下記が挙げられます。 クラウドワークスが提供する「フィークル(feecle)」 GMOクリエイターズネットワークが提供する「FREENANCE(フリーナンス)」 マネーフォワード100%子会社であるMF KESSAIが提供する「MF Kessai」 三菱東京UFJグループ運営のMUFJ Digital Accelerator出身のOLTAが提供する「OLTA(オルタ)」 また「YELL BANK」もスキームとしてはファクタリングを応用させたものになっています。 フリーランスや中小企業に特化しつつ、各社自社サービスの強みを生かす形での参入パターンと、全くの新規での参入との両パターンが存在していますが、ファクタリングは産業としての歴史は比較的浅いこともあり、ほとんど認知されていません。おそらく経営者や財務関係の方でもファクタリングについての知見を持ち合わせている方はごく少数なのではないでしょうか。 アメリカでは既に「Fundbox」や「BlueVine」など売掛債権を活用したファクタリングやABL(動産担保融資)等のファイナンススキームでユニコーンとなる企業も登場し始めています。今後日本のマーケットにおいてもFinTechスタートアップによって、本格的にファクタリングが流行っていくのか、とても楽しみです。 流動資産を活用したファイナンス 売掛債権を活用するファクタリングのように、流動資産(不動産に対して動産という)を活用したファイナンススキームは、ファクタリングやABLなど、アメリカでの市場形成を参考に日本では2000年代から中小企業庁を中心に推進しようとする動きが活発でした。しかし、残念ながら未だに一般的に利用されているとは言い難い現状があります。 中小企業のバランスシートをみると、動産の資産価値ベースで売掛債権で87兆、棚卸資産46兆、その他流動資産47兆円が積み上がっています。借り入れを見てみると金融機関、その他から合わせて約240兆円あり、この規模が事業性ファイナンスにおけるTAMという考えることも可能かと思います。加えて小規模事業者のマーケット、フリーランスなど統計上捉えられない市場も加味すると、マーケットのポテンシャルの凄さに気付くかと思います。細かいセグメントでの分析は別の機会にしようと思いますが、チャレンジに値するマーケットが存在することは明らかです。 (中小企業白書 第2部 中小企業の稼ぐ力「 第5章:中小企業の成長を支える金融 」より) 事業者向けのFinTechサービスとしては、貸金業との対比における参入障壁の低さからファクタリングが先行していきますが、商流ファイナンスの流れに乗っかって在庫、POなど、売掛債権よりも更にサプライチェーンを遡った部分でのファイナンス手法を提供するインターネット企業が後々生まれてくるでしょう。一例としては、事業者の物流管理がクラウドサービスで行われるようになった際に、生産過程での商材を担保に運転資金融資をするなど、ある意味で商社金融によって担われていたようなサービスを、個人やスモールビジネスでも受けられるような時代がくるでしょう。 (日本銀行金融高度化センター ITを活用した金融の高度化に関するワークショップ「データを活用した金融の高度化」) 競争環境は厳しめ このように事業者の資金調達課題、特に運転資金の課題に対しての切り口は現時点でも複数考えることができます。また、既存の市場環境をみてみると無数の中堅、小規模な事業者が激しく戦っている状態で、まだ誰が勝ち切っているとは言い難いのが現状です。 更に言うと、トランザクションレンディングの切り口でAPI型、マーケットプレイス型、会計型、決済型、それぞれの参入が続いていく中で、ファクタリングや商流ファイナンス単体でどこまでスケーラビリティをとれるかは難しいところかもしれません。 新規参入の際に既存プレイヤーとの差別化として、外部サービスとのAPI連携や銀行口座情報の取得など、多くのデータポイントを作り出していくことを戦術的に取りれる事例が増えていきますが、マーケットのマジョリティーを占めるであろう中小製造業社や卸売業者がデータソースとなるようなクラウドサービスを導入しているかといえば、現状まだまだな状況です。 米国事例との単純比較で言えば、独立的にファイナンスサービスを提供するテクノロジー企業(代表的な例で言えば「Kabbage」)の立ち上がりが、決済やマーケットプレイス企業である「PayPal」、「eBay」と同時期であったことにより、複数のユニコーン企業を産む結果に繋がっている一方で、日本ではマーケットプレイスが先行したために融資・ファクタリングのテックプレイヤーが急拡大する余地が薄くなってしまっています。 このような市場環境での新規参入に取りうる事業戦略は、他産業の事例や金融業界の歴史を振り返ると6つほどに類型できると私自身整理していますが、これについてはまた別の機会に書いてみたいと思います。 何にしても事業性融資/中小企業の資金調達という巨大マーケットで戦うプレイヤーが増えることは、資金需要者からするとファイナンスオプションの増加につながり、メリットは計り知れません。 CACの問題や、ファクタリングなどの参入障壁の低さ、債権回収のパワー関係、資本政策の難しさなど、あげようと思えばいくらでもこの市場でビジネスを生み出していく上での壁を思いつくことができます。しかし、我々はスタートアップとして課題があれば解決していかなければいけない立場にあります。BASEもBASE BANKを通してこの市場に参入しているわけなので、新規サービス、産業の発展、そして顧客の課題解決に知恵を働かせていきたいものです。 2. 既存のSaaSサービスから派生した金融サービスへの展開 クラウド会計サービスの貸金業進出は言わずもがなとして、ピンポイントなところで言うと、SmartHRが金融サービスを展開していくでしょう。代表の宮田さんご本人の ブログ にも、 おそらく FinTechっぽい事業になる予定です とありますし、確度は高いのではないでしょうか。 事業展開としては、給与前払い系、あるいは会社が従業員へ貸付する場合は貸金業登録を必要としないので、従業員への貸付や債権管理をサポートする機能、給与から天引き回収などの事業展開かなと思っています。自社で「SmartHR Pay」のような機能を用意して、給与振込自体を自社サービス内に留める、といったことも妄想はできますが、現在のPayment市場では難しいのではないでしょうか。そうすると選択肢としては、やはり貸付周りや、積立や資産運用サービスを「Folio」など他社とのアライアンスで提供していくような新規事業を作っていくのではないかと考えます。 決済+ECで事業を作りあげてきたBASEは、個人的にはSquareと重なって見えることが多いのですが、彼らがPayroll領域へとプロダクトの幅を広げていることもありSmartHRとも若干被り始めているように映り、とても興味深いところです。 日本ではまだSaaS自体が立ち上がっているフェーズということもあり、金融サービスへと展開していくケースは少ないかもしれませんが、産業ごとのバーティカルSaaSの特性を生かして個々の金融課題を解決していく様子は想像するだけでワクワクするものです。 物流や医療機関など、各カテゴリーごとに立ち上がったSaaSがホワイトラベル化する銀行とアライアンスを組みながら金融事業を展開していく、というストーリーは多くの方が想像するところだと思いますし、これが実現される世の中であってほしいです。 3. 株式投資型クラウドファンディングの立ち上がりの兆し 事業としてエクイティクラウドファンディングが立ち上がりはじめたのは2012年頃に米国でJOBS Actが成立してからだと記憶していますが、欧米に引き続き日本でもようやく参入の兆しがみえはじめています。 (参考記事: JOBS ACTによる米国証券法等の改正 ) またスタートアップ界隈でもエンジェル投資が一般化され始めており、この流れに乗っかりたい投資家は潜在的に多いのではないかと考えています。かくいう私も個人的な趣向としてFinTechスタートアップを中心に、人間の可能性や想像力を拡大していくような企業へ50〜300万ほどの少額投資したいと思うことが多々あります。(ほとんど自己研鑽/事業立ち上げが好きだからという理由ですが。) もちろん調達側の企業とのマッチングが本質であるので、一般化されるのは難しいかもしれません。しかしながら特定のビジネスレイヤーに対しての拡大は非常に早いのではないかと、半分願望ですが考えています。 4. 比較レイヤーの新規参入 顧客へダイレクトにサービス提供する事業者が増えるにともなって、インターネットのことわり通り、顧客側には比較検討するニーズが発生します。しかし、融資領域では商品特性がコモディティ化されており、金融機関ごとに差別化することが難しい現状があります。ここに一歩踏み込んだ形で比較サービスを展開するプレイヤーが出てくるでしょう。 例えば融資領域ですと、現状検索結果はアフィリエイトサイトで溢れています。一方で融資の媒介(送客・広告ではなく、融資契約を仲介すること)は、貸金業法で登録済みの事業者しかできないことになっており、気軽には参入することができません。 新規の比較レイヤーは正式に貸金業登録を完了させた上で、自社サービス上で財務分析・信用調査・金融機関による審査と条件交渉などを複数同時平行で進めることができるようなプラットフォームを目指して生まれてくると思います。このように既存金融機関が融資プロセスの中でコストをかけて行なっていた一部の過程をアウトソースするという切り口での参入は、他産業ではよく見かける事例でもありますが、金融はブラックボックス化されやすい特性からか未だスタートアップが入り込めていません。 米国事例で言えば、「 Fundera 」がこれに近いかもしれません。 Crunchbase を見ると2015年のシリーズB以降の資金調達がないですが、金融機関の広告、オペレーションコストを考えるとマーケットは十分と言えそうです。 5. 金融リスク管理系SaaSサービスの発展 比較レイヤーの論理と同じで、プレイヤーが増えればその分事業者の課題の総量も増えていきます。 特に新規参入のスタートアップにとって、与信、債権管理、回収、ALMマネジメント、信用リスクモデルの構築、ポートフォリオ管理、統合的リスク管理、担保や保証などの各種経営管理要件を自前で準備して運用していくことは大きな負担であり、そもそも人材マーケットにこれらの経験がある人はほとんどいません。 金融におけるリスクは信用リスク、オペレーショナルリスク、市場リスクなどに分けて考えられますが、まずは信用リスクの部分を補完するサービスを展開していく事業者がでてくるかと思います。そもそも金融におけるリスク、というのは情報の非対称性と不確実性の両性質を持っています。前者についてはインターネット的な解決手段を提示しやすく、後者については機械学習を筆頭にAIがコアバリューとなったソリューション提供が増えていくでしょう。 先行する米国では、すでにいくつかのサービスが立ち上がっています。債権管理であれば「 Yaypay 」、債権回収領域の「 TrueAccord 」、Banking as a Serviceの「 Plaid 」などがこれにあたります。 また信用調査に関して言うと、日本では伝統的な企業信用情報サービスはTDB(帝国データバンク)やTSR(東京商工リサーチ)による独占状態です。この領域は市場規模も1000億以上あり、かつ課題が多く、上記のような切り口でのスタートアップによる参入もあるはずです。シードステージのスタートアップでは「 アラームボックス 」などが存在していますが、まだまだ参入企業数が少ない印象です。2019年は盛り上がりを見せることを期待しています。 おしまい 注目しているスタートアップや各市場への参入の戦略など、他にも考察したいことは多いのですが、今回のブログでは一旦ここまでとします。色々と考えを書き連ねてきましたが、まとめたり分析したり考えを書くだけならば、私個人としてはノーバリューだと思っています。 私はアナリストでもコンサルタントでもなく、あくまでも起業家/事業家としてしっかりと新しい時代の金融サービスを創り上げ、より良い未来に貢献いきたいと思います。 Be Hopeful!! お茶・ランチも常時募集してますので、こちらの リンク や Twitter からでも気軽にご連絡ください! 明日はBASE BANKチームを機械学習エンジニアとして支えてくれている岡さんです!
BASE Advent Calendar 2018 18日目 「 BASE Advent Calendar 2018 」の18日目の記事です。 devblog.thebase.in お久しぶりです。BASEビール部部長(& Data Strategy Group)の氏原です。 アドベントカレンダーの季節が来て今年も終わりかと実感しているところです。 年末年始、どこにビール飲みに行くか今から悩んでます。 参考: 大晦日もお正月もクラフトビール! 年末年始営業日カレンダー (2018 – 2019) – クラフトビールのお店の予定がわかる さて、今回はアドベントカレンダーということで機械学習そのもののお話は他のData Strategy Groupのメンバーが書いてくれるでしょうから、 私はちょっとインフラ寄りのお話をさせていただこうかと思います。 以前 類似商品APIのお話 を書きましたが、 それ以降もData Strategy Groupでは関連ワードAPIとか売上予測APIとかいろんなAPIを作ってきました。 APIはAWS API Gatewayを利用してBASE本体に提供していますが、ある日AWSさんからAPIの構成について貴重なアドバイスをいただきました。 どういう内容でご指摘いただいたか、そしてそれにどう対応したか、対応して良かったことを書こうと思います。 Data Strategy GroupのAWSのインフラ構成 Data Strategy Groupは自分たち専用のAWSアカウントを持っていまして、その内部構成は自由に決められます。 メンバーが各々で開発を好きに進められるように機能ごとにVPCを分けて、自分が担当しているVPC内については好きに作っていいよという構成にしました。 AWS環境のVPC構成 VPC間で通信が必要な場合はVPC Peeringで繋ぎます。 VPC Peering こうして各機能を疎結合にして、各メンバーが割と好きに開発を進められるようにしてありました。 そして問題のAPI Gatewayですが、これは各VPCから生やすようにしていました。 API Gateway API Gateway自体はVPCとは繋がっていませんので、API Gatewayに来たリクエストをVPC内のサーバにルーティングするにはVPC Linkを設定する必要がありました。 エラー ある日新しく作ったVPCにAPI Gatewayを生やすためにVPC Linkを作成しようとするとエラーが起こりました。 どうやらAWSの制限に引っかかったようです。 1アカウント、1リージョンあたりのVPC Linkの数は初期状態では5つに制限されています。 VPC Linkの制限 まだ慌てるような時間ではありません。AWSはそもそも初期状態では結構厳し目に制限かかってますからね。 ちゃんと使い出したらすぐに制限に引っかかって緩和申請出すというのはAWS使ってる方なら経験があるでしょう。 引き上げ可能かに「はい」と書かれているわけですからいつも通り制限緩和を申請しましょう。 どれだよぅ そのままドンピシャな選択肢が見つかりません。 制限タイプの「API Gateway」とか「API Gateway管理」とか「VPC」とかの中を探したんですが見つかりません。 だんだん嫌な予感がしてきました。 仕方ないので技術サポートに問い合わせました。 結果、 「VPC Linkの項目はない。適当な項目選んで申請理由の説明のところにVPC Link数増やして欲しい旨記述してほしい」 とのこと。 …今まで誰も申請してないんだろうか。 気を取り直してそれで申請しました。その結果がまさかのNG。 「VPC Linkの数は増やすことをあまり想定していない。利用方法について聞かせて欲しい。」 インフラ構成変更 その後AWSの担当の方とのミーティングなどを経て、VPC Linkの数を増やすことは諦めて構成を変更することにしました。 API VPC爆誕 まずAPI提供用のVPCを一つ用意してAPI GatewayとVPC Linkで繋ぎました。 VPC Linkの一方の端はNLBです。で、このNLBから直接各VPCのALBに繋ぎたかったんですが、NLBにそういった設定はできません。なので一旦HAProxyにリクエストを飛ばして、ここで各VPCのALBへ振り分けるようにしました。各VPCのALBはVPC内のマイクロサービスへリクエストをルーティングします。 このような構成にすることでVPC Linkの数は1つあればよいようになりました。 さて、こうしてみると実はこの構成のほうが良かったんじゃないかと思います。 その理由としては キャッシュをAPI VPC内でやるようにすれば各機能でキャッシュとか考えなくてもAPI VPCで統一的に扱える。 APIの入れ替え、A/Bテスト、障害時の対応などがHAProxyの設定変更で行える。 複数の機能を統合したAPIの提供をAPI VPC経由で行える。例えば画像系とテキスト系の類似度を両方使った類似商品APIなど。 APIを外部に提供するときに考えなくてはいけないことと、提供する機能を綺麗に分離することができたように思います。 まとめ 実運用されていてかつ試行錯誤させてくれる環境って貴重ですよね。いろんな知見が溜まっていく。実は上で説明した今の構成もさらに改善中で来年頭くらいにはまたちょっと変わっちゃってると思います。Data Strategy Groupの環境はまだまだ手探りで構築中ですが、それがまた楽しいでところでもあります。 ではこのへんで。 明日は id:Toshi_Day1 さんがファイナンス系でなにか書いてくれます。 お楽しみに。
BASE Advent Calendar 2018 17日目 この記事は「BASE Advent Calendar 2018」17日目の記事です。 devblog.thebase.in はじめに はじめまして。Native Application Group の木下です。主にAndroidアプリの開発を担当しています。 今年はアプリの開発に留まらず、プロジェクトのディレクションやグロースハックといった分野にも少し手を出してきましたので、1年を振り返りながら知見などを共有できればと思います。 最近のBASEの組織 最近のBASEでは「グループ」と「プロジェクト」の二つの組織体系で業務を行なっています。 「グループ」はデザイン・バックエンド・アプリ・SREなど、スキルや分野によって分類された組織で、私の所属する Native Application Group では、日常的にスマホアプリに関する次のような業務を行なっています。 他部署からの要望にもとづく機能開発 不具合やOSのアップデート対応 新しい技術の組み込みや技術的負債の解消 開発環境の基盤づくり 新バージョンのリリース これに対して「プロジェクト」はクォータごとに目的・目標(KGI)と期限が設定され、目標を達成すべく、各「グループ」から選抜されたメンバーで構成される組織になります。同時に複数のプロジェクトに所属するケースもあります。 プロジェクトのイメージ プロジェクト名 目的 KGI プロジェクト マネージャ ディレクター デザイン バックエンド アプリ プロジェクトA プロジェクトB プロジェクトC はじめてのグロースハック 2018年の各クォータで所属した「プロジェクト」では、ディレクターかAndroidアプリエンジニア、もしくは両方のポジションに就き、特に1Qと2Qでは数値改善を目的としたグロースハック系のプロジェクトを担当しました。 グロースハックはほぼ未経験でしたので、まずは基礎知識を身につけなければと思い関連する書籍を読みました。特に参考になった2つを紹介します。 「いちばんやさしいグロースハックの教本 人気講師が教える急成長マーケティング戦略」 タイトルのとおり、初心者向けでとてもわかり易い内容でした。 「データ・ドリブン・マーケティング―――最低限知っておくべき15の指標」 紹介文の “ジェフ・ベゾスが愛読! 世界最強のマーケティング企業 アマゾン社員の教科書” に惹かれて読んでみました。プロダクトの意思決定で重要となる15の指標についての説明が、実例を交えながら書かれています。 まずはデータ収集から グロースハックでは仮説・検証を繰り返し行いますが、その前段として現状を捕らえるためにデータ集めを行いました。 ショッピングアプリ「BASE」では、Firebase Analytics でイベントログを収集して、BigQuery にインポートし、Redash を使ってモニタリングしています。社内には50インチ以上の大型ディスプレイが何枚もあり、さまざまな指標やサービスの状況をモニタリングできるようになっています。 Redashの導入・布教については過去の記事をご覧ください。 devblog.thebase.in はじめの頃は個人的にRedashではなくData Studio(今のデータポータル)を利用していましたが、グラフのレイアウト調整などが地味に面倒だったり、社内的にRedashの布教が進んでいたこともあり、途中でRedashに切り替えました。 Data Studio はダッシュボードを Google Driveのファイルとして扱え、アカウントや権限の管理が簡単だったりと良い点もありますが、日々新たなダッシュボードを追加していくとなると、多機能すぎてちょっと扱いづらいかなと思いました。 KGIからKPI、施策から効果測定まで 前述のとおりプロジェクトごとにKGI(Key Goal Indicator : 重要目標達成指標)が設定されます。KGIには最終的なゴールとなる指標が設定されるため、直接KGIを上げようとしても具体的な施策を立てるのが困難でした。このため、まずKGIを構成するいくつかのKPI(Key Performance Indicator : 重要業績評価指標)に分解して、このKPIをあげるための施策(ユーザー体験や機能の改善)を検討して実施(開発・リリース)する流れとしました。 ダイエットに例えるとこんな感じです。 KGI : (3ヶ月で)体重マイナス10kg KPI(1) : 1日の摂取カロリーを300kcal削減する 施策(1-1) : 夕食のご飯の量を50%削減する 施策(1-2) : 3時のおやつを廃止する KPI(2) : 1日の消費カロリーを300kcal増加させる 施策(2-1) : 通勤電車では椅子に座らない 施策(2-2) : 毎日5kmジョギングする 施策を実施したら効果測定を行います。リリースと同時にRedashを使ってモニタリングを開始し、KPIとKGIの動向を追います。KPIが改善されてもKGIに影響しない(仮説が外れる)こともあるため必ず両方を見ます。 改善されない場合や不十分な場合は、施策の内容を改善したり、施策をキャンセルすることもあります。ダイエットの例であれば、1ヶ月経っても体重が減らない場合は「ジョギングの距離を10kmに変更する」といった感じになります。 プロジェクトのディレクション 続いてプロジェクトのディレクションについてです。 BASEにおけるディレクターの役割については次のように考えています。 メンバーの活動を最適化して、プロジェクトが成功する確率をできる限り高めること。 プロジェクトを成功させるのはあくまで各メンバーであって、環境づくりや交通整理をするのがディレクターの役割であると考えています。ディレクターが重要な意思決定を下したり、仕様を決めたりするのは適切でないと思います。特にBASEは数字やデータに基づきシンプルに意思決定する文化のため、この考えは適していると思います。 また、ディレクター要因でプロジェクトの進行やメンバーの活動を鈍らせることは絶対にあってはいけないと考えます。1Q=3ヶ月、という短い期間で目標を達成しなければいけないため、特にこの点は特に留意しました。 ディレクターとしてやったこと ディレクターに就いた直後は、何を期待されているのか?何をやれば良いのか?よく分からず右往左往した時期もありましたが、いろいろと試行錯誤した結果、主に次のようなことをすることとしました。 プロジェクト開始前 プロダクトマネージャーからプロジェクトの目的についての背景や詳細、マストでやりたい施策についてのヒアリング 施策ごとに作成するドキュメントのテンプレート作成 主要KPIの設定 プロジェクトの立ち上げ キックオフミーティング プロジェクトの目的やKGI、プロダクトマネージャーの意向などを共有 定例ミーティングの調整 メンバー全員で施策ブレスト 施策案出し 施策の規模感や実現性の確認 優先順位付け マスタスケジュール作成 BASEでは Asana を活用しています プロジェクト中 ミーティングのファシリテーション Dailyでスタンドアップミーティング Weeklyでミーティング(進捗確認、施策の結果共有、追加施策の検討) 進捗把握とフォロー リリースや効果測定のサポート プロジェクト終了後 KPTでの振り返り 納得感と温度感 プロジェクトはKGI/PKIを達成するために活動しますが、各施策についてメンバーが納得感を持つことが重要だと考えます。 なぜそれをやるのか?プロジェクトに貢献できる施策なのか?ユーザー体験は改善されるのか・悪化しないか?...などプロジェクトの目標は共通であったとしてもメンバーごとの視点は異なり、納得感が高ければ施策の質も高めることができ、より良い結果が期待できると思います。 この納得感を高めるため、ブレストで作成した施策案リストに次のような「いいね」欄を設けて、温度感を可視化することとしました。 ミーティング中に「この施策どう思いますか?」と聞いても、声の大きい人の意見で染まったり、分からないことがあっても今更聞きづらい空気ができてしまっている場合もあり、メンバーそれぞれの納得感を確認し高めることは難しいため、カジュアルに可視化できる仕組みとしてトライしてみました。 この「いいね」で多数決することはしませんが、優先順位に多少は影響しました。中にはプロダクトマネージャーの挙げた施策でも、「いいね」数が少なく優先順位を下げることもありました。温度感の高い施策について重点的に議論を進めることができました。逆に効果が期待できそうなのに温度感の低い施策については、施策内容を掘り下げて納得感を高めにいくことができました。 測定不能 様々な施策を実施する中で、1つ大きくハマったことがありましたので紹介しておきます。 施策をリリースしたら効果測定するようにしていますが、測定できなくなる事態が度々発生しました。主な原因は2つあります。 同じKPIに影響する複数の施策を同時期にリリースしてしまった セールなどのキャンペーンやTVCMの放送と施策のリリース時期が重なった 一つ目の施策が重なる問題については、KPIが改善されてもどの施策が効いているのか特定するのが困難になります。プロジェクト内でやってしまうケースや他のプロジェクトの施策と重なるケースがあり、前者の場合はプロジェクト内で注意しながらリリースのスケジュールを策定していれば回避できるのですが、後者の場合は他プロジェクトとリリース時期を地道に調整することで回避するしかないかなと思います。 二つ目のキャンペーン等については、 KPI/KGIへの影響が非常に大きく期間も長いため、完全にお手上げとなります。社内にアンテナを張って、キャンペーンが始まる時期を早めに察知し、リリースや開発のスケジュールを調整することで防いでいくしかないかなと思っています。 Androidアプリの開発について 最後になりますが、この1年でAndroidアプリ開発もいろいろ変化しました。 CI環境の移行(Bitrise + Danger) 昨年までは Jenkins(社内のMac miniで稼働)でビルドしていましたが、今年に入ってから Bitriseへ移行しました。Bitrise を選んだのは Circle CI のようなメモリ制限(4GB)がないのと、モダンなUIでカジュアルに利用できそうで周囲でも流行っていた、という理由でした。最初の立ち上げは他のメンバーが対応していましたが、比較的スムーズに移行できたと思います。 そして、せっかくBitriseを導入したのだからもっと活用しようと思い、Dangerを導入しました。Danger を使うと、Pull Request などをトリガーとして、PRの内容をチェックしてワーニングやエラーなどのコメントを自動で表示することができます。エラーの場合はマージ不可とすることも可能です。 Danger公式サイト Using Danger with Bitrise 実際の Dangerfile は次のような内容となっていて、PR作成・更新時にチェックが走ります。 is_release = github.pr_labels.include? "[RELEASE]" # WIP warn("PR is classed as Work in Progress") if github.pr_title.include? "WIP" # PRが大きすぎる(リリース用のPRは除外) warn("Big PR, over 1000 lines") if git.lines_of_code > 1000 && !is_release # 誰もアサインされていない has_assignee = github.pr_json["assignee"] != nil warn("Please assign", sticky: false) unless has_assignee # release以外からmasterへマージ is_to_master = github.branch_for_base == "master" is_from_release = github.branch_for_head.include?("release") fail("You can only merge to the master branch from the release branch") if is_to_master && !is_from_release # ファイルの変更検知 protected_files = ["build.gradle", "proguard-rules.pro", "version.properties", ".gitignore"] protected_files.each do |file| next if git.modified_files.grep(/#{file}/).empty? message("Changes have been made to the #{file} file") end Androidチームでは、次のようなブランチ運用を行なっています。 リリースの時期とスコープを決めてreleaseブランチを作成 feature ブランチを作成して開発 release ブランチへPull Request(WIPで早めに出していつでもレビュー可能に) レビューが完了したらマージ release ブランチでQAが完了したら masterブランチへPull Request master へマージすると同時に自動で本番ビルド開始 リリース このように develop ブランチが存在しないためシンプルな運用が可能です。しかし master をデフォルトブランチに設定していることで時々事故が起きていました。通常 Pull Request は release に向けて作成するべきですが、誤って master に向けて作成してしまうことがあり、レビューでも気づかれずそのままマージしてしまうことが何度か発生しました。本番ビルドが走ってしまったり(Publishは自動化していないのでセーフですが)、Revertする手間が発生したりと、地味に面倒な作業が発生します。これを防止するためDangerにチェック項目を追加してPR先が master の場合はマージ不可することで、このような事故は発生しなくなりました。 コードレビュー必須化 Androidチームのメンバーも増え、品質を維持したり技術的負債を増やさないためにも昨年末からコードレビューを必須とし、メンバー全員からapprovedされるまでマージできないルールとしました。 自分自身、前職くらいからコードレビューをやり始めてはいましたが、仕様を満たしているかのチェックがメインであまりコードレビューと言えるものではありませんでした。必須化した直後は要領よくレビューができずに、場合によってはほぼ「ノールックLGTM」していた時もありましたが、最近ではレビューの質もあがり主に次のような点を見るようにしています。 将来負債になったり不具合の原因となりそうな実装がされていないか MVVMモデルに則した実装となっているか Nonnull / Nullable の区別は適切か スコープ関数を利用したkotlinらしいコードになっているか kotlinで Utilsクラスや Stream を利用していないか また若いエンジニアからも鋭い指摘をもらうことがあり本当にありがたい限りです。Kotlinだとこんな書き方もできますよ、といった感じで知識を共有する場にもなったり、チーム開発&コードレビューって素晴らしいな〜と感じるようになりました。 ちなみにレビューの負荷軽減・レビューによる手戻り削減のため、作業を始めたらなるべく早く WIPで Pull Requestを出し、余裕のあるときにレビューするようにしています。突然「急ぎでレビューお願いします」と言われても、すぐに時間が取れず雑にLGTMしたり、ほんとは指摘したいけど修正しているとリリースに間に合わないから今回は指摘しないでおこう、など良くない状況が起こり得るため早めにレビューできる運用を心がけています。 TLS1.2対応とAndroid4.xサポート終了 BASEではセキュリティ対策の一環として、今年の6月にサーバーをTLS1.2へ移行する計画があり、これに合わせて Android4.x のサポートを終了することとなりました。 1ヶ月前からアプリ内のお知らせやGoogle Play のアプリページに告知を表示して、Android4.x の端末からは(TLS1.2に対応している)ChromeブラウザのWebページからご利用いただくようお願いしていました。(BASEの場合、アプリだけでなくWebページからも商品が購入できる点は強みだと感じました。) また、移行したタイミングで4.x端末でアプリを起動すると、サポートを終了した旨のメッセージを表示して起動を中断する仕組みを、早い段階で仕込んでいました。 普通であれば要求を受けた何かしらのAPIがOSのバージョンをチェックして4.xならエラーを返す、という設計を考えると思いますが、TLS1.2未対応のクライアントからはAPIに一切接続することができなくなるため、アプリ起動後最初のAPI接続の前に上記のような仕組みを入れることで、アプリがクラッシュしたり「ネットワークエラー」のような意味不明なメッセージを表示することがないようにしました。この仕組みはFirebase RemoteConfg を利用して実現しています。 結果として、一部のユーザー様にはご迷惑をおかけしましたが、大きなトラブルもなくスムーズに移行することができました。 Kotlin化 BASEアプリのKotlin化進捗状況です。 もともとオールJavaでしたが、2017年のGoogle I/OでKotlinの正式サポートが発表されたのをきっかけにKotlinの導入をはじめました。 ひとまず、 新機能/クラスはKotlinで実装しよう (あとは余裕あるときに徐々にやっていこう...) なノリで移行を続けて1年半が経ちましたが、思ったほどKotlin化が進まず、2020年になってもJavaを書いてるのは嫌だなー(バージョン1.1のころからJavaに触れている身としては切実です)と思い、 少しでも修正するJavaファイルはKotlinにコンバートする というルールを最近になって追加しました。 来年中にKotlin 100%を達成できるよう頑張りたいと思います。 AndroidX移行 AndroidXの移行については、 このスライド を見て詳細を把握し、直後にIssueを立てAndroid Studio3.2(正式版)がリリースされたタイミングで対応する予定でした。今後公開されるドキュメントはAndroidX前提で書かれ、AndroidXでしか利用できない機能・クラスも増えてくるだろうと考えて、放置していても負債にしかならいと判断したためです。 AndroidXは皆さんお馴染み Support Library の改良版です。Support Library は9月にリリースされた Revision 28.0.0 で終了しており、今後は AndroidX へ移行する必要があります。 Android Studio 3.2 以降では移行ツールが用意されドキュメントも整備されていますので、まだ対応されていない皆さんには早めの対応をお勧めします。 AndroidX Overview Migrate an existing project using Android Studio 実際に対応したのは他のメンバー(Android歴1年未満の若手エンジニア)で、QA含めて2週間くらいで完了し10月上旬にリリースしましたが、リリース後も特に問題はなくスムーズに移行できたと思います。もちろんコードレビューもしっかりやりました。 まとめ 2018年は、Androidアプリの開発だけでなくプロダクトやチームの成長にも熱中でき、SIer・受託開発歴の長い自分にとっては大変実りのある一年となりました。スタートアップだからこそできる貴重な経験だと思います。 来年もたくさん新しいことにチャレンジしていきたいと思います! 明日はビール部部長の氏原さんです!
これは「BASE Advent Calendar」16日目の記事です。 こんにちは、BASEのDesign Groupに所属している吉岡です。 先日BASE BANK株式会社初めてのプロダクトとして即時に資金調達ができる金融サービス「 YELL BANK 」をリリースしました。個人的にお金にまつわるデザインは初めての経験ということもあり、難しかったのですが、LPではAfterEffectsで作ったアニメーションをCanvasやSVGアニメーションにできるプラグインを使って表現しました。 今回はせっかくのアドベントカレンダーなので、下記の様なHolidayAnimationを書き出してみようと思います。 環境設定 Bodymovin をインストール creative.adobe.com プラグインインストールのためのzxp-installerもダウンロードします aescripts.com Lottieアニメーションの Bodymovin プラグインをダウンロードして、インストールする github.com bodymovinを解凍してzxpファイルをzxpインストーラーにドラッグしてインストールします。 AfterEffectsに拡張が入っているか確認する 問題なくインストールできれば、AfterEffectsのウィンドウ/拡張機能にBodyMovinが入っているはずです。 XDでデザインを作る 今回はテキストアニメーションを描いていこうと思うので、Adobe XDでまず描きたいテキストを配置します。この際にアートボードサイズが最終ブラウザに書き出すサイズになります。 テキストを配置したら、ファイル > 書き出し > After Effectsで書き出します(最近できた機能です。illustratorよりサクッとAfter Effectsに書き出せます。) After Effectsでアニメーションを作る アニメーションを作っていきますが、Lottieを使う注意点を先に記載します。 - After Effectsのエフェクトは使えないと思ってていい - Expressionも書き出さないと使えない - グラデーション効かない といった具合です。パスアニメーションができるよ、程度の認識で良いかもしれません。After Effectsで使える機能は こちら で確認できます。 前提が終わったところで...アニメーションを作っていきます。 まずはXDで作っていたテキストを、アウトライン化してシェイプとして配置しておきます。 今回は筆記体テキストが流れていく様なアニメーションを作りたいと思うので、パスに合わせてモーションが動くアニメーションを作っていきます。好きなシェイプを作り、テキストをなぞる様に位置のkeyframeを打っていきます。トランスフォーム > 自動方向でパスに沿って自動方向に設定します。こうすることでパスに沿ってシェイプが回転します。ここからは好きな様にパスを変形させてkeyframeを打っていきます。 パスに添わせたアニメーション部分はこんな感じです。 アルファマットでテキストを表示する パスに添わせたアニメーションに合わせて、テキストを表示するためのシェイプもパスkeyframeを描きます。 テキストにアルファマットでマスクした状態にします。 これでアニメーションは完成です。 JSONに書き出す アニメーションが完成したら、JSONファイルに書き出していきます。 ウィンドウ > 拡張機能 > Bodymovinを選びます。 selectedでコンポジションを、Destination Folderに書き出し先ディレクトリを選びます settingsでは今回はこの設定で書き出します。 - Glyphs(もしフォントが残っていてもシェイプにしてくれます) - Hidden (マスクなどを使っていると必要です) - Demo (HTMLに雑にしてくれるので確認が楽でおすすめです) 他にも、画像をJSONにincludeしてくれるAssetsの項目もあるので適宜必要あれば設定します。 確認してみる 書き出しフォルダにindex.htmlが生成されるので確認してみると... 作った通りのアニメーションが表示できています! 中身がどうなっているのかというと... AfterEffectsのレイヤーがちゃんとSVGのpathになって、transformされるのがわかります。 Lottieを使ってみて グラフィックだけでもholidayっぽさはあるのですが、アニメーションをつけることでより情緒的な抑揚をつけることができるので、デザイン表現が簡単に広げられるLottieはとても使いやすいプラグインだと思います。 今までYoutubeなどで上げていた動画より、サクサク動きます! これを機に、アニメーションまでデザインしてみては...! 明日はAndroid エンジニアの木下さんです!
はじめに これは「BASE Advent Calendar 2018」15日目の記事です。 devblog.thebase.in こんにちは、Backend Engineer Groupの 菊地陽介 です。今回は、BASEの育休エバンジェリストとして記事を書きたいと思います。今年の8月8日に第一子(綾瀬はるか似の娘)が生まれ、その後BASEの男性社員としては初めてとなる育児休業(以下、育休)を1.5ヶ月ほど取得しました。 育休取得直後に娘の心臓に先天性の疾患があることが分かり、一般的な赤ちゃんの倍くらい世話が必要だったので私が育休を取って妻と2人で育児をすることができたことは大変ありがたかったです(その後手術を行い現在は回復の方向に向かっています)。 なにより育休期間中の1.5ヶ月は娘の成長を間近で見ることができ、私の人生において生涯忘れないであろうかけがえのない日々となりました。そこで私が今回育休を取得して気付いたこと、思ったことを日本の全パパにお伝えしたい。 日本の男性社員が育休を取りにくい理由の一つとして、前例がまだ少なく情報があまりないということが挙げられると思います。今回育休に関する様々な知見を得ることができましたので紹介します。本記事をきっかけに育休に対する理解を深められたり、これまでより柔軟に考えてもらう機会になれたら幸いです。 (注) - 制度の内容は育休を取りやすい方向に変わっているので本記事で述べているものと現在の制度が異なっている可能性があります。 - 本記事は育休について大まかに知ってもらうことが目的なので詳細については言及していません。 日本のパパの育休について 私が育休を取得しようか検討する際に知りたかった情報を紹介します。 一ヶ月以上の育休取得率は1%以下 パパの育休取得率は年々上がってきてはいるもののそれでも平成27年度時点で2.65%程度しかありません。さらに5日未満しか育休を取得しない人が56%を占め、一ヶ月以上の育休を取っている割合は20%以下です。つまり一ヶ月以上の育休を取っているパパは日本には100人に1人以下しかいないというのが現状です。 (厚生労働省「 資料 「平成 27 年度雇用均等基本調査」の結果概要 」より) 休業前の手取り賃金の8割がもらえる 育休を取得しない理由の一つとして、育休期間中の収入が0になると思っている人が多いのではないでしょうか。その心配はいりません。雇用保険の育児休業給付金制度があります。(※支給要件があります)手取り賃金で比べると約8割が支給されます。下記資料が分かりやすかったです。ちなみに メルカリ さんのように育休期間中の給与を100%保障する会社もあるようです。 (厚生労働省「 育児休業給付金の資料 」より) ※その他にも健康保険から支給される「出産育児一時金」や「出産手当金」等があります。(※こちらも支給要件があります) 産後一年の間で取得可能、また延長も可 育休は子供が産まれてすぐに取得しなければいけないものではありません。出産のタイミングでは自分が関わっているプロジェクトが忙しかったり、業務の引き継ぎがたくさん必要で育休を取りにくいという場合があるかもしれません。しかし「子供が産まれてから1年の間であれば取得可能」ということであればその間で育休を取れるように調整することは難しくないのではないでしょうか。 また、産後一年以内であれば育休を延長することもできます。私の場合当初1ヶ月の予定でしたが、育休取得後に娘の心臓に疾患が見つかり検査や入院などが必要となったため半月ほど延長しました。 私の育休 育休を取得するまで 上司に伝える 出産予定日の半年ほど前に上司に「1ヶ月くらい育休とりたいんですけど」と週に1度行われている1on1ミーティングの際に相談してみました。 このとき嫌な顔されるといった心配はまったくしておらず、「お、いいね!ていうか一ヶ月だけでいいの?もっと取った方がいいよ!」と言われるほどでした。 出産予定日前後は自分がいなくても業務に差し支えがないように配慮してもらいました。感謝です。 チームメンバーに伝える チームメンバーには育休を取る一ヶ月前くらいに報告しました。 育休を取得しない理由の大きな理由の一つとして、自分が休むと会社が回らなくなってしまうと心配してしまう人が多いのではないでしょうか。もしそう思うのであれば本当に心配しなくてはいけないのは、自分がいないと会社が回らないほどに属人化してしまっている状況です。私の場合は属人化している業務がほぼなかったため、引き継ぎは隣の席の @tenkoma に15分ほど説明しただけでした。 赤ちゃんはいきなり産まれてくるわけではありません。自分も父になるんだという気持ちが湧いてから産まれるまでに半年以上の猶予があると思います。その間に自分の業務をチームのメンバーができるように引き継ぎを行い、気持ちよく育休を取得できるようにしたいですよね。 (ちなみに自分が休んでいても何一つ問題なく会社が回っていると寂しい気持ちになります) 申請の書類を提出する 育休の申請については、育休を取得する前に会社に簡単な申請書を提出し、あとの手続きは会社でやってもらえたのでとても簡単なものでした。 育休中 育休はバケーションじゃない 育休前は少なからず下記のような気持ちがありました。 知性を感じさせるパパを目指して自己啓発本をたくさん読もう カッコいいパパを目指して毎日筋トレして体を鍛えよう 子供に尊敬されるパパを目指して国旗とか覚えよう etc 結果的に何一つとしてできませんでした。 育休期間中に育児以外のことをする時間はないと思って間違いないと思います。おそらく日本では育休をバケーションのように考えている人が少なからずいらっしゃるようで、育休を取得することに対して後ろめたさを感じ、取得に踏み込めない人が多いのかなと感じます。 育休≠バケーションです。本音を言うと私にとって育休は仕事をしてるよりしんどかったです。 ママの期待値を調整する 産後クライシスという言葉があるように、出産を機に夫婦の関係性が悪い方向に大きく変わることも多いようです。 出産直後はホルモンバランスが崩れネガティヴ思考になったり、育児に対して過剰な責任を感じてしまう母親が多く、期待してるような行動を父親が取ってくれないと苛立ちやすくなってしまうようです。特段穏やかな私の妻に限ってそれはないと思っていたのですが甘かったです。 育児中の母親は父親に求めるハードル(期待値)が高くなりやすい一方で、世の多くの父親はそれをなかなか超えてこないので苛立ちが生じるのだと思います。ですので、ハードルを下げましょう。 具体的には「オムツ交換とミルクを作るのはパパ、お皿洗いと料理の準備はママ」といったように家事や育児の役割分担をできる限り明確にすることが重要だと思います。例えば「お皿洗いは気が付いた方がやるようにしよう」としておくと、「私は寝不足で疲れてるんだからパパが洗ってよ」とパパがお皿を洗うことを期待されることがあります。しかし事前にお皿洗いはママの役割と明確にしておけばそのような期待は起きないでしょう。逆にお皿洗いはママの役割としているのにパパがお皿を洗ったら感謝されるものです。 結果的にやってることは一緒でも期待値の調整次第でママからの評価は大きく変わるものです。 仕事と一緒ですね。 考え方が変わった 育児をすることで色々考え方が変わったなと感じます。私はたくさんある育児の中でオムツ交換が一番好きです。下記写真のように赤ちゃんのなされるがままにお股を広げている無力な様がたまらなく可愛いく思うのです。 あの人怖いな、苦手だな、堅物だなとこれまでは避けていたような人に対しても、「昔はオムツ交換してもらってたんだな」と思うと微笑ましく感じられるようになり、以前よりも余計な感情なくニュートラルに人と接することができるようになったと感じています。 また、育児がこれほどまでに大変なんだと実感することで自分を育ててくれた両親に対しての感謝の気持ちが強くなりましたし、世の中にいるパパママはみんなすごいなと尊敬の気持ちを抱くようになりました。 育休が終わってから 復帰初日は転職初日のような緊張感がありました。1.5ヶ月間の育休でしたが個人的には1年くらい休んでいた感覚でした。私が育休を取っている間に次のような変化がありこれぞベンチャー企業だなと思いました。 渋谷の2フロアに分かれていたオフィスから、六本木の高層ビルの37階に引っ越ししていた 新入社員がたくさん増えてた BASEの男性社員として初となる私の育休をきっかけに多くの男性社員から「次に子供が生まれる際には自分も育休を取ろうと思う」というふうに声をかけられました。 今後も育休エバンジェリストとして育休を取得することの意義を布教していきたいと思います。 出産&育児で得た知見 本記事の育休を勧めるという目的からは話が逸れるのですが、出産&育児の際にいくつか知見を得たので共有します。 日用品にかかるお金はけっこう節約できる 先輩パパママから「子供ができるとオムツ代とかミルク代がバカにならないよ!」とよく聞かされていました。 実際はそんなことありません。 そうです、ふるさと納税です。ふるさと納税を有効に使えばオムツ(メリーズ、ムーニーマン、グーン等なんでもある)、おしりふき、ミルクetcほとんどなんでも揃えることができます。ぜひ活用してみてはいかがでしょうか。 おすすめのアプリ 様々なアプリをたくさん比較した上で厳選したというわけではないですし、一番メジャーなものを使っていただけなのですが下記で紹介するアプリは大変素晴らしく感動したので個人的におすすめさせてください。 トツキトオカ 「 トツキトオカ 」は、夫婦で共有できる妊娠記録・日記アプリです。 日々アプリの中の赤ちゃんが成長していき、また話す言葉もグッとくるものなので父親になるんだなという実感が徐々に湧いてきました。 また妻が毎日このアプリで日記を更新していたのですが、口には出しづらい心配ごとなどを書いていたりして妻の心情を理解するのに役立ちました。 ( トツキトオカ 公式HP より) みてね 「 みてね 」は、子供の写真を家族で共有することができるアプリです。 スマホはLINEくらいしか使いこなせていなかった私の父と母もこのアプリなら使いこなせるくらい、UIUXが優れていて使いやすいです。 また、フォトブックやDVDをすごく簡単に作成することができます。しかもとても安価に作成できるので運営会社が今後も継続していけるのか心配になるほどです。 ( みてね 公式HP より) まとめ 本記事を読んで育休を取ってみようかなという気持ちになっていただけたなら幸いです。 私が育休をとるにあたって業務の調整を行ってくれた上司やフォローをしてくれたチームメンバー、復帰後も温かく迎えてくれたBASEの社員みんなにこの場を借りてお礼を伝えたいと思います。 本記事を読んで少しでも伝わったなら嬉しいのですが、BASEはみんないい人でとても働きやすい良い会社です。 BASEってどんな会社なの?会社に遊びに行ってみたい!育休の話もっと詳しく聞きたい!財テクの話が聞きたかった!と思っていただける方がいらっしゃればぜひ 私 までメッセをいただければと思います! 明日はデザイナーの吉岡さんがデザイン表現を広げるアレコレについて書くようです、ぜひご覧ください!
この記事は、「BASE Advent Calendar 2018」の14日目の記事です。 devblog.thebase.in こんにちは!Design Groupに所属している森( @ mrkzk )です! リードエンジニアのお兄さんに「森さん、寿司食いたくないですか?」と聞かれ「もちろん、食べたいです。」と答えたらアドベントカレンダーブログを書くことが決定していました!お寿司は隠語だったのでしょうか?びっくりです! では早速、タイトル通り デザイナーの私が初めてプロダクトのコードをコミットしてみたお話 をします。 どうしてコードを書くことになったの? 私の普段の業務はアプリのUIデザインなのですが、ときどきWebのクリエイティブ作成にも関わることがあり、いつもクリエイティブを作ったのちに「お願いします!」とこのようにエンジニアの方にお渡ししています。 今回は、既存バナーのUIやショップ数が古かったので更新するために差し替えが必要だったのですが、「お願いします!」と言いながら、画像の差し替えくらい自分でできたらな、、と思っていたところこのような流れが・・・ 「こんな綺麗な流れってあるんだ・・・」と感心しつつ、探り探りでやっていくことに・・・ まず、作成したクリエイティブをステージングへ、そして本番へアップロードしなければいけません。 そこで噂には聞いていた画像アップローダーの出番です! 画像アップローダーの実装に関しては、先日エンジニアリングマネージャーの加賀谷が記事に書いています! devblog.thebase.in 画像アップローダーくんの使い方 Slackの該当チャンネルに作成したクリエイティブを投稿する Slackで @image-uploader hey と話しかける   画像アップローダーくんからお返事がきたので快く yes を選択 すると・・・ ステージングにアップロードできちゃいました!こんな簡単に・・?と疑っていると、今度はタコとネコのハーフからお返事が来たので快く yes を選択。 すると・・・ できました!差し換え用のクリエイティブを本番にアップロードすることができました。すごい! と、ここまでは画像アップローダーくんに助けられていましたが、ここからは一人の戦いです。 OSの出し分け 今回私が作成したクリエイティブは、アプリへのダウンロード導線バナーです。 OS別にバナーを作成しているので、iOSユーザーには左のiPhone端末バナー、そしてAndroidユーザーには右のAndroidの端末バナーを出したいのです。 ところが、コードの書き方が全くわかりません。 とりあえず OS 出し分け で検索してみると、「JavaScriptで簡単にUA判定する方法」に関する記事が出てきました。どうやらUA判定というものがあって、これを使えばiOSかどうかがわかるらしいので、UAを利用してiOSを判定するコードを探しました。 こちらです。 var ua = navigator.userAgent var isIOS = ua.indexOf( "iPhone" ) >= 0 || ua.indexOf( "iPad" ) >= 0 || navigator.userAgent.indexOf( "iPod" ) >= 0 こちらを利用して、実際に画像を出し分けるコードを書いてみます。 imgタグはわかっていたので、このソースを切り替える方法を調べていくと「getElementByIdを使ってソースを書き換えると良い」とあったのでとにかく書いてみました。 < script > var ua = navigator.userAgent var isIOS = ua.indexOf ( "iPhone" ) >= 0 || ua.indexOf ( "iPad" ) >= 0 || navigator.userAgent.indexOf ( "iPod" ) >= 0 ; var img = document .getElementById ( 'appBannerImg' ) if ( isIOS ) { img.src = "//static.thebase.in/img/u/U1MK212HY/FER5CBE2D.png" } else { img.src = "//static.thebase.in/img/u/U1MK212HY/FERP402M8.png" } </ script > これでpushしてみると・・・ちゃんと動いてます!出し分け成功! なんとかこれをプルリクエストまで持っていくことができました!なんでしょうか、この達成感は・・!! プルリクエストー!!と舞い上がっているところに間髪入れずリードエンジニア兄さんからのつぶやき↑が聞こえてきました。コードを少し書くだけでも一苦労だったので正直勘弁してほしいなと思ってしまいましたが、どうせなら!と querySelector に書き換えることに。 - var img = document.getElementById('appBannerImg') + var img = document.querySelector('#appBannerImg') getElementById の部分を querySelector に変更し、imgタグの前に # をつけるだけ! これがイマドキなんですね(getElementByIdの方が響きはイカしてると思いますが) こうして無事リードエンジニアの兄貴からOKが出ました!リリースです🎉 おしまい ここまでの流れを簡単に書いてきましたが、実際はコマンド一つを実行するにも調べながら、質問しながら、とかなり苦労しました。 それでもターミナルがガガガーっと動くのは楽しいし、自分の制作物をエンジニアさんにお任せするのではなく、最後まで責任持って本番環境に届けることに気持ちの良さと達成感を覚えました! 私のようにこれからは一通り自分でやってみるぞ!!というデザイナーが増えると嬉しいです。 ちなみに Twitterトップ でLINEスタンプ販売中なので見てみてください! 明日の担当はBASEのイクメン・菊地さんです!
BASE Advent Calendar 2018 (13日目) この記事は、「BASE Advent Calendar 2018」の13日目の記事です。 devblog.thebase.in Backend Engineerの沖中 ( @okinaka ) です。 読者のみなさんはテストを書いてますか?テストが面倒くさいとか思ってませんか?(私はたまにあります) そんな時、モチベーションをあげるには、どのような工夫をしていますか? 私の場合、カバレッジ計測の結果のレポートがとても役に立っています。 レポートを眺めると、視覚的に 「どの行が実行された」とか 「カバレッジ率が◯%」だとか 「ここ複雑だけどテストがないクラスがあるよ」など、 いろいろ気づきがあります。 「ここマズイな、テスト書いて確認しなくちゃ!」という気持ちになるのでとても重宝しています。 とてもいいツールだと思うのですが、残念ながら BASE社内でもまだ十分に活用されていないのが現状です。ですので、この記事をきっかけに、広めていければいいのではないかと期待しています! 現状ではカバレッジレポート出力が時間がかかる問題があるのですが、今後、自動生成する仕組みを用意できればと考えています。 カバレッジレポートについて BASEでは、主にCakePHPでサービスが構築されており、ユニットテストも、若干手を加えていますが基本的にはCakePHPに用意された仕組みを利用しています。カバレッジレポートは、その機能を利用して生成しています。 カバレッジについての簡単な説明は、 CakePHP クックブック をご覧ください。 (内部的には PHPUnit を利用しています。詳細は こちら ) カバレッジレポートには出力形式がいくつかあるのですが、今回はモチベーションアップが目的なので、人が見てわかりやすいHTML出力を紹介します。 出力されるHTMLページは大きく分けて3つに分類されます。 各ディレクトリ内のファイル一覧 (index.html) ファイル毎の大まかなカバレッジ状況を一覧で確認できるページ *1 ファイル一覧(index.html) 各ファイルのカバレッジ詳細 (PHPファイル名.html) どの関数・行がテストされたかなど詳細を確認できるページ 次にどんなテストが必要かを考える際に役立ちます カバレッジ詳細(PHPファイル名.html) ダッシュボード (dashboard.html) 以下のカバレッジ状況を俯瞰的に確認できるページ クラス・メソッドのカバレッジ率 (Coverage) コードの複雑度 (Complexity) の分布図 カバレッジ率の低い順のクラス・メソッド一覧 リスク (CRAP値) の高い順のクラス・メソッド一覧 全体の状況を把握したり、次にどのファイルをテストすべきかをざっと見るのに便利! ダッシュボード(dashboard.html) テスト作成とカバレッジレポート出力 では、実際にレポートを出力して内容を見てみましょう。 まず最初に、とあるメソッドに対してテストを1つ書いてみました。 <?php public function testView () { // テスト対象を実行 $ this -> testAction ( ' /posts/view/1 ', [ ' method ' => ' get ', ' return ' => ' contents ' ]) ; // とりあえず、ステータスコードの確認 $ this -> assertSame ( 200 , $ this -> controller -> response -> statusCode ()) ; // その他、なんらかの結果の確認... } この時点で、カバレッジレポートを出力してみます。レポートを見ると、どうやら一部実行されていない行があるようです。 (注: 緑の部分 がテストされた行で、 赤い部分 が未テストな行です。 赤い 部分をなんとか消したくて、ウズウズしてきますね!) カバレッジ詳細(テスト1回目) 未テストだった行を確認してみると、 $id が未指定 ( null ) だった場合と、 データーベースに未登録な $id だった場合の処理がテストされてないようです。 このレポートを受けてテストケースを追加してみます。 <?php /** * @expectedException NotFoundException * @expectedExceptionMessage Invalid post */ public function testViewで、IDが未指定だった場合は例外発生 () { $ this -> testAction ( ' /posts/view/ ', [ ' method ' => ' get ', ' return ' => ' contents ' ]) ; } /** * @expectedException NotFoundException * @expectedExceptionMessage Invalid post */ public function testViewで、未登録なIDを指定した場合は例外発生 () { $ this -> testAction ( ' /posts/view/999 ', [ ' method ' => ' get ', ' return ' => ' contents ' ]) ; } 結果がこれ。 カバレッジ詳細(テスト2回目) やりました! 赤かった ところが 全部緑色 に!これで安心です。 ここで、注意点があります。 全部緑色 になって喜んでいましたが、 緑色の行 を増やすよりもむしろ テストの内容 の方が重要です。 たとえテストが実行されたとしても、ちゃんと動作を確認していなければ意味がありません。あくまで、モチベーションを高め、テスト状況を確認するためのツールと捉えていただければと思います。 明日はデザイナーの森さんです!お楽しみに! *1 : 注: CakePHP 公式のクックブックの チュートリアル を元に、独自のテストを実行した結果を表示しています。
この記事は、「BASE Advent Calendar 2018」の12日目の記事です。 devblog.thebase.in こんにちは、BASE BANKインターンの かわごえ( @heart_breakers2 )です。 今回は少し趣向を変えて、「鶴岡さん観察日記」と題して、BASE 代表取締役CEOおよびBASE BANK 代表取締役CEOである鶴岡の普段の様子をイラストを交えてカジュアルに伝えていきたいと思います。 (みなさんにもカジュアルな雰囲気で読んでいただきたいので、記事内ではあえて「鶴岡さん」と表記しています。) 私がインターンとしてBASE BANKにジョインし、鶴岡さんのななめ前の席に配属されてから半年が経ちました。 みなさんがきっと知らない鶴岡さんの素顔や、BASEの好きなところをまとめてみました。 この記事を読んでいただき鶴岡さんやBASEに興味を持っていただけると嬉しいです。 はじめに みなさんは、BASE代表の鶴岡さんをご存知ですか? BASEが提供するネットショップ作成サービス「BASE」は、「お母さんも使える」をコンセプトとしたネットショップを作成できるサービスで、現在は60万人を超える オーナーズ に利用されています。 鶴岡さんはBASEの創業者。 Forbes JAPANが発表した「 日本の起業家ランキング2019 」で3位に選出された、日本で最も注目されている起業家の一人です。 「60万ショップも使っているサービスを作っているんだ!すごい!」 「Forbesでも注目されているんだ!すごい!」 と思った方もいるのではないでしょうか。 私から見た鶴岡さんは、傾聴力と本質を見抜く力が圧倒的に高く、どんな人でも一緒にいて心地よい存在で社内外にファンが多いようです。 しかし、鶴岡さんが遠い存在と思われてしまっているのか、↓のようなツイートにだれもツッコめない状況になっているような気がします。 くだもの食べながら炭酸水飲んだら、ファンタになる — 鶴岡裕太 (@0Q7) 2018年11月10日 この記事では、社内での鶴岡さんはどのような様子なのか?何を大切にして事業を進めているのか? BASEの素敵な制度などもご紹介しつつ、鶴岡さんにまだお会いしたことがない方でも身近に感じていただけるよう、イラストと写真で紹介していきます💫 鶴岡さん観察日記 AM 11:00  Be Hopefulキャンディー 鶴岡さんの朝は、たいてい午前11時のミーティングで始まります。 鶴岡さんはミーティング中どんな感じなの?と気になる方も多いのではないでしょうか。 社内のミーティングの様子を覗いてみましょう。 鶴岡さんとの社内ミーティングは社長室で行われることが多く、鶴岡さんが座る席の近くにはBe Hopefulキャンディーが入ったガラス瓶が置かれています。 ミーティングではキャンディーを手に取り頬張っている鶴岡さんですが、発言はいつも本質的で、 「オーナーズのためになるどうか」 「オーナーズにとってわかりやすいかどうか」 をいつも大切にしているので、私たちもどのような判断をすべきかがクリアになります。 ちなみに、BASEの 行動指針 は Be Hopeful Move Fast Speak Openly の3つで、どれも欠かせない重要な指針となっています。 実際のBe Hopefulキャンディー。 行動指針の浸透のために作られたもので、キャンディーの中に"Be Hopeful"と書かれていてかわいいです。 キャンディーの色は、「BASE」のサービスロゴであるティピのマルチカラーを使用していて、社内のいたるところに置いてあります。 PM 0:30  みんなの食堂 先日からBASEでは、いわゆる社員食堂のサービスが毎週水曜日に提供されています。 鶴岡さんも毎週この社食を利用していて、メンバーと楽しく会話しながらランチをしています! 社食うまい pic.twitter.com/Qf3p0RwL7V — 鶴岡裕太 (@0Q7) 2018年11月15日 (鶴岡さんの写真は撮り忘れちゃいましたが、みなさんが食堂を楽しんでいる様子です💕) 現在は30食限定でいつもすぐに売り切れてしまうのですが、500円で定食を食べることができます!! (BASEは37階にあるので、ランチにいくにも時間がかかってしまうのです) ココロータス 別の日の様子です。 鶴岡さんはお昼頃になると、定期的に、大好きな神宮司さん(執行役員/Product Manager)にこう語りかけます。 ココロータス とは、アジア料理を中心に、多国籍のランチを提供するキッチンカーです。またココロータスは、お支払いアプリ「PAY ID」の加盟店で、スマホでQRコード決済が可能なのでお財布を持たなくてもランチを買うことができます。 メニューが提供されるのを今か今かと待ちわびているようです。 ココロータスのメニューはどれもボリューミーかつ1000円以内で注文できます。企業の社長はいつも豪華な食事をしているというイメージの方もいらっしゃるかもしれませんが、鶴岡さんのランチはいたって庶民的なんです。 ココロータスのキッチンカーは現在、江戸川橋と六本木三丁目で販売を行っています。六本木周辺に勤務されている方はぜひチェックしてみてくださいね! PM 3:00  カップスープ ある日出社すると、隣の机に大量のカップスープが置かれていました。 置いたのはもちろん鶴岡さん。 とのことだったので、3時のおやつにたまごスープをいただきました。 この時は特に何かのお祝いやイベント事があったわけではないですが、特に理由がなくともさらっとメンバーに差し入れをする様子を見て鶴岡さんの優しさや心遣いを感じました。まだ食べきれていないほど、大量に購入されていました! ちなみに、鶴岡さんが好きなのはコーンポタージュ。 PM 4:00  「順調?」 夕方になると、近くにいる人を中心に「順調?」と話しかけるのが鶴岡さんの癖です。 「え!?社長に進捗確認されるとかプレッシャー!!」と感じる方もいるのではないでしょうか。 でもBASEでは違います。 私から見ると、鶴岡さんの「順調?」という発言はメンバーにプレッシャーをかけたいという意図ではなく、「困ったことがあったらいつでも聞いて大丈夫だよ」という心配りなのではないかと思います。 なので、鶴岡さんに「順調?」と聞かれて正直に答えないメリットはありません。順調ならそう答えればいいし、何か詰まっている点があるなら打ち明けた方がよいです。 私自身も実際にこの言葉をかけられて、「ユーザーからの反応があまりなくて、次の施策をどうするか悩んでます!」と相談したことがあります。 なぜなら先ほども書きましたが、鶴岡さんは傾聴力が優れていて、本質的なことを見抜く力が高く、私たちの想像を超えるようなフィードバックをしてくれるからです。 BASEの行動指針に「Speak Openly」とあるように、たとえ物事が順調に進んでいない場合でも、正直に話すことで鶴岡さんから的確なフィードバックを得られるため本質を見失わずにプロダクトを作り続けることができます。 お気に入りのゴジラをつかみながら喋る鶴岡さん PM 5:00  ジャック・ドーシー氏 鶴岡さんが12/3に日経BP社によって行われたイベント「 スモールビジネス新潮流 「ポスト2020」を見据えて 」に登壇が決まった時の話です。 テーマは「スモールビジネスが秘める可能性と未来」について。Twitter、Squareの創業者であるジャックドーシー氏も参加するセッションです。 中小企業や個人で活動しているオーナーズをどのような方法で応援できるかについて、鶴岡さんの考えやBASEの取り組みを話したそうです。当日の様子が気になる方はぜひ、Twitterで「#ポスト2020」と調べてみてください! ちなみに鶴岡さんはかねてからジャックドーシー氏の大ファンで、このイベントでの登壇が決まったときは本当に嬉しそうでした。 It was great meeting you, @jack ! pic.twitter.com/EWtlZUYJ9x — 鶴岡裕太 (@0Q7) 2018年12月3日 (鶴岡さんの目がキラキラしてます!!) おわりに いかがでしたか。 鶴岡さんの普段の様子が伝わるように意識して書き上げたので、鶴岡さんの温かい人柄、飾らない素直な性格、そしてBASEの良さが伝わっていると嬉しいです。 明日は、沖中さんがカバレッジレポートについて書きます!
先日の締め会の様子 これは「BASE Advent Calendar」11日目の記事です。 devblog.thebase.in こんにちは。BASEで代表をしている鶴岡( @0Q7 )です。 11日目の記事を担当しています。 ある日、Slackでアドベントカレンダーを書く人を募集していたので、調子に乗りそれとなく書く予定にしていたら、書く内容が全く思い付かず悩みすぎたので今はすごく後悔しています。 本日12/11はBASEの設立記念日で、6年が経ちました。早いような遅いような。 ついこの前までは「今日のGMVは100万円は行きたい、そしていつかは500万くらいはいけるようなサービスにしたい。」なんて思いながら毎日帰宅していた気がしますが、その目標から桁が2つくらいは増えたので少しは成長できてるのかなと思います。 ただ何かを成し遂げたわけではないので昔話をしたいわけでもなく、とはいえエモくビジョンの話をするのもなんなので、この6年で実際に感じた学びを書こうと思います。 内容は個人的な主観ですが、誰かの役に立てれば嬉しいです。 殆どの戦いは負けても良い 社会人になって一番の学びかもしれないですが、殆どの戦いには負けても大丈夫なんだなと思いました。 戦いとは、議論や意思決定のことを指していますが、最終的に成し遂げたい目標があったときに、その途中で訪れる論点を全て自分の思い通りにする必要もないんだなと。全ての勝負に勝とうとするにはあまりにも今の人生では短いので、全部の駒を取る事が勝利なのではなく、王将を取る事が勝利なのだとあらゆる場面でゲームをしっかり理解する能力を磨きたいものです。そして王将だけは必ず取りましょう。 感情とは上手く付き合いたい 特に怒りという感情とは上手く付き合った方がいいかなと思いました。 怒りという感情を露わにする事が、物事を最短で進めるための手段になる事は殆どないです。自分の思う通りにしたければまず感情をコントロールできる人間になりたいです。 プロダクトが全て 自分たちが作っているプロダクトが全てを癒してくれます。学歴も地位も立場も関係ないです。最高のプロダクトを作ったチームが一番かっこいいです。「BASE」を使ってくれている60万のショップをみてもそう思います。最高のプロダクトを作ることが出来れば市場が評価してくれます。世の中にあった方がいいプロダクトは必ず成功すると思いますが、タイミングだけが変数です。諦めずチームで最高のプロダクトを作りましょう。 インプットは難しい 自分に合っていない情報のインプットがあると無駄な時間を使ってしまう事があります。情報がこれだけ溢れている昨今において、自分に適している情報はすごく少ないです。Twitterで流れてくる情報は自分のフェーズには早かったりしてほぼ役に立たないなと感じます。世の中で起きている事実だけを把握し、自ら考え自分が思うままに行動するのが一番かなと思います。 評論家にはなりたくない 評論するよりされる側の方がかっこいい!というのも勿論ありますが、これは評論家を批判してるわけではなく、自分のメンタルを保つためにあまりオススメしません。自分を追い込むことになる言動はなるべく慎みたいなと思います。 テクノロジーには超楽観的に テクノロジーがあらゆるものを便利にしていきます。プラットフォームがあらゆるリスクを巻き取っていきます。今不便だと感じる事は全て解決されるんだろうなと感じます。そうやって訪れる未来を幸せと呼ぶのだと信じています。 徳を積む そもそも徳が何かも分かっていないのと、どうやったら徳を積めるのか僕もよくまだ分かっていないですが、お金では買えないものである事は確かです。徳が高い人は凄いなと思います。日々の言動や所作を周りの方々に見ていただいて、自ずと積まれていくものだと思うので、常日頃から意識して生きていきたいです。必ずその徳に助けられる日が訪れると思います。 パッと思いつくところだと、こんな感じでしょうか。 こういうのを書くタイプでは無いのですごく疲れました。。。また黙々とプロダクト作りに励もうと思います。 普段は オーナーズ の為にEC・金融・決済領域でプロダクトを作っています。 もっと話聞いてみたい!BASEってどんな会社なの!会社に遊びに行ってみたい!と思っていただける方がいらっしゃればぜひ メッセ をいただければと思います。 明日はBASE BANKインターンのマリーちゃんです。 ではまた。
これは「BASE Advent Calendar」10日目の記事です。 devblog.thebase.in こんにちは。BASEで採用広報を担当している米田( @AiYoneda )です。普段はL'Arc-en-CielのHYDEさんの追っかけをしていて、来週にはきっと東京ドームでその御姿を拝んでいることでしょう・・・ さて、HYDEさんの話は置いておいて、私はテックブログこと「BASE開発チームブログ」の編集部として運営に関わっています。今回は、約8ヵ月続けてきたこの「BASE開発チームブログ」の運営についてのノウハウを余すことなく書いていこうと思います。 テックブログはエンジニア・デザイナー組織のプレゼンス向上や採用に効果があるなどと聞いているけど、なかなかうまく運営できていないという方もいらっしゃるかと思います。そういった方にこちらを読んでいただいて少しでも参考になれば幸いです。 テックブログって本当に効果あるの?約8ヵ月間、編集部として運営を続けてきた効果、成果 BASEでは2018年4月にテックブログ編集部を作り、以降テックブログの運営を担っています。下記は編集部が立ち上がって以降の効果や成果について記載したものになります。 公開記事数がめちゃくちゃ増えて30本以上公開できた 2017年:8本 ↓ 2018年4月以降:31本! (このAdvent Calendarで今年あと15本公開予定です!) 2017年は半年くらい更新していない期間もあり、かなりさみしい感じでしたが、2018年4月以降は月2本以上の更新ペースを維持できています。またこの数字はむやみに増やしたわけではなく、ひとつひとつの記事の内容やクオリティは一定に保った上での成果です(実際に記事を読んでいただければわかると思います)。 執筆に関わったメンバーの数ですと、このアドベントカレンダーを含めると約30名のメンバーに執筆してもらうことができました。またブログの読者数(はてなブログの機能で購読していただいている読者の数)は約3倍になりました。 イベント、勉強会での発表機会ができた 大規模Webサービスの開発にせまる「BASE Geek Night #1」 base.connpass.com レガシーコード改革!UT/CIでWebサービスの技術的負債を解消する取り組み base.connpass.com テックブログで書いてもらったネタをプレゼン形式にして勉強会やmeetupで発表してもらうことができました。上記は実際に開催したイベントです。中にはこのイベントで「人生で初めてLTをやった」というメンバーの声もあり、外部での発表機会の創出につながりました。 採用面談、面接で「テックブログを見てます!」との声が増えた 正確に数値を計測してはいないんですが、採用候補者とのカジュアル面談や面接を担当するメンバーより、候補者の方から「テックブログ見てます」と言っていただけることが明らかに増えたとのことです。 何より、このAdvent Calendarを実施できた! 日々の運営の積み重ねが実ったのか、2018年はBASEで初のアドベントカレンダーを開催することができました。 11月末に編集長がSlackに下記のように投稿したところ、 これから数時間後… 次々とメンバーが手を挙げてくれて、あっという間に25枠がすべて埋まりました…この怒涛の投稿の様子には正直かなり感動しました。 しかもアドベントカレンダーの開始は12/1、この投稿は11/28とかなりタイトな依頼だったのにメンバーが次々と手を挙げてくれて、BASEの行動指針の一つである「 Move Fast 」を体現していてすばらしいです。 テックブログの運営で挫折しないためのTips ここからは実際の運営のTipsを書いていきます。 テックブログの運営でネックなのは、運営担当者自身が人事など現場とは別部署に在籍していたり、入社したばかりという方や年上の方が多い方の場合、周りのメンバーをうまく巻き込めるか、途中で挫折しないか不安だという部分ではないでしょうか。私自身も入社してすぐの、まだメンバーの顔も覚えきれていないような状態で編集部として運営に携わるようになり、かつ前職とは業界や職種も違う状況で初挑戦なことばかりでした。 そんな私でも実行できたTipsですので、特に人事や広報、若手社員の方に試していただけると嬉しいです。 テックブログ運営の成功体験をもつメンバーを運営メンバーに入れる このメリットは下記の2つだと考えています。 運営ノウハウを転用できる エバンジェリストとして運用のモチベーションを保ってくれる いきなりテックブログの運営経験がない私が運営を始めてもスベるのは目に見えています。なのでそういう時には素直に成功体験を持つメンバーから運営ノウハウを教えてもらうのが得策だと思います。 また、テックブログ運営の成功体験のある人物とともに運用していくことで、自らのモチベーションを保つことができ、運用中の挫折を回避することができます。自分自身に成功体験がないと運営していく中でどうしても「これは本当に効果があるのだろうか?」、「現場メンバーには迷惑ではないか」と疑心暗鬼になってしまうこともあるのですが、成功体験のあるメンバーはそのような不安を解消してくれる心強い存在で、「 Be Hopeful 」に運営を続けることができます。 サポート体制を作る BASEのテックブログでは、現在編集部が中心となり運営をしています。 編集部が行っているのは下記です。 月1の編集会議でのネタ出しと、予備も含めてその月に公開したい記事を決める 該当のメンバーに執筆依頼 記事チェック(編集やタイトル案の相談など) 画像の作成・撮影のサポート 執筆マニュアルのメンテナンス 記事案の管理はスプレッドシートで行っています。「常設」がいわゆる予備記事です。 他の企業では、テックブログは書きたい人が書きたいときに自由に記事を公開するという運営方法を取っている場合もあるかと思います。もちろんBASEの場合も「このイベントで登壇したからその内容をブログ記事にしたい」、「こんな取り組みをやってみたんだけど、ブログネタとしてどう?」といった流れで記事を書いてもらうことはあります。 運営方法は様々だと思いますが、編集部が主導する体制を作ることのメリットは下記だと考えています。 投稿ペースを維持できる 社内のいろんな人に書いてもらいやすい 記事のテイストを一定に保てるため読者が読みやすい まず投稿ペースに関してです。現在は月に2本は必ず公開するという方針の下、編集部で予備も含めて公開したい記事を決めています。自由投稿だと投稿の頻度にバラつきが出てしまう可能性もあり、そうなるとブログの見栄えとしてはあまり好ましくありません。編集部がペースメーカーとなって更新頻度を維持することでブログの活気を保つことができると考えています。 「社内のいろんな人に書いてもらいやすい」についてですが、自由投稿の場合ですと、社内で素晴らしい取り組みを行っていたり、目覚ましい成果を上げているけどもブログはあまり書かないという人もいて、機会損失が発生する可能性もあります。編集部体制では、そういった取り組みを行っている人に注目して執筆依頼をしています。先述のように2018年4月以降は約30名のメンバーに執筆してもらうことができ、記事内容もPHPでのWebサービス開発からデザイン思想、データベースや機械学習などバラエティに富んだものになっていると思います。 もちろん、理想はどのメンバーからも「これブログで書きたいんだけど」と次々に提案をもらえ、さまざまな記事が投稿される状態だと思いますし、今回のアドベントカレンダーはまさに理想の形で開催することができ、とても嬉しかったです。 そして記事テイストの統一に関してですが、こちらは編集部でテックブログの執筆マニュアルを用意していたり、公開前に編集部が内容を確認することで実現できているかと思います。とはいえこれは最低限のチェックを行うのみで、執筆者の個性を最大限に活かすよう意識しています。 お祭り感を出す 前述のように、現在は編集部から記事の執筆を依頼する場合があり、依頼の仕方によっては執筆者が義務やタスクのようにネガティブに捉えてしまう可能性もあります。 そこで、記事の公開に関する要所要所でお祭り感を出すことで、執筆を依頼された人もまだ執筆したことのない人も、記事の執筆という行為をポジティブに捉えてもらうことができると考えています。 まず、当たり前ですが記事を公開したらメンバー全員がいるSlackチャンネルでお知らせします。記事を公開したら、Slackの #general で執筆した人に「こんなの書いたよ」と投稿してもらいます。そうすると代表の鶴岡やCTOの藤川も含め各メンバーがSNSでシェアしてくれるのでちょっとしたお祭り感が出ます。 またはてブのホットエントリ入りした時や、媒体で取り上げられたりしたときにはメンバーが随時共有してくれるので、執筆した本人も嬉しいですよね。 こんな感じでシェアしてくれます。 おわりに こうやって積極的なテックブログの運営ができるのも、現場のメンバーが日々のプロダクトづくりで様々なことにチャレンジしているからこそです。そして私がこうやって記事がかけるのも編集部のメンバーのサポートのおかげです。この場を借りて記事を執筆してくれるメンバー、編集部のメンバーにはお礼を伝えたいと思います。 今後ともみなさまにお楽しみいただけるようなテックブログの運営をコツコツと続けていきます。 BASEのメンバーは素敵な人たちばかりです。このテックブログを読んでBASEにご興味をもってくださった方は、ぜひ下記をご覧ください!一緒にBASEではたらきましょう! binc.jp 明日はBASE株式会社が創業して6周年ということで、代表の鶴岡が記事を書きます!乞うご期待!
この記事は、「BASE Advent Calendar 2018」の9日目の記事です。 devblog.thebase.in 前日は id:match_1 でした。こんにちは、10日ほど前に データベース移行についての記事 を書かせていただいた植木です。 今回はインデックスとBtreeのパフォーマンスチューニング系のお話をしたいと思います。 概要 Btreeの構造などを説明している資料は他にもあるし、SQLのアンチパターンもある程度あるけど、何故アンチパターンになるのかなど構造を理解しながらの説明が無いように思っていました。今回はBtreeの構造を説明しながら、どのように動いてパフォーマンスに影響しているのかを説明しようかと思います。SQLのパフォーマンスチューニングはBtreeの構造を理解しているかどうかで全く違うものになります。構造を意識しつつ、誤解しやすいところや何故この処理でインデックスが効くのかなど考えてみましょう。 Btreeの仕組み Btreeとは 情報処理試験などで出ますから知ってるよって人も多いですよね。ソート処理と木構造によって検索の高速化をするアルゴリズムとなります。このBtree構造がDBのインデックスの内部構造となります。弊社だとMySQL系ですので若干カスタマイズしたB+treeとなります。 下の図を見てほしいのですが、データを格納する単位であるノード内にはインデックス対象のキー値とそれ以外にリーフには実データへのポインタ情報(MySQLだとPK)が入っています。木構造を使った分岐で対象のリーフノードを選択したらポインタ経由で実テーブルにアクセスしてデータを取得します。 B+treeがBtreeと違う点はリーフノードにもブランチノードと同じ情報が入る事とリーフノードに次のリーフのポインタが入る事になります。これらの対応をする事で範囲検索やorder by、group by等の対応がしやすくなります。今回はこのB+treeを使っての説明をいたします。以降、Btreeと書いているものはB+treeです。 今回はわかりやすくしたいのでノード内に1データしか入らないと仮定してキー値に1−10のデータを入れた場合を想定します。実際にはノードに複数レコードが入りますが、ノードの先頭データと末尾データを使って同じような構造と比較をします。 また、参考に普通のBtreeだとこうなります。 何故この構造にデータを並べると早いの? 例えば、今回のように1〜10まであるデータの中で6を探したいと思った場合、通常なら10回6という数字と格納データとを比較する必要があります。ユニーク制約をつける事ができたとしても6回です。それに対して、木構造にしておけば、まずルートノードの5と比較して大きいので右のブランチへ行き、7と比較して小さいので左に行けばもう目当てのデータに辿りつきます。 インデックスをつけない状態なら検索はデータ量に比例した処理時間が必要ですが、木構造にする事で必要な時間はデータ量の対数に比例します。 実際のSQLでよくある問題などなど 範囲検索 下記のような検索をした場合に誤解している方がいます。 where id between 6 and 8 この時、Btree上で6と8の位置を検索してその間のデータを全て取るなんて器用な事はできません。今回の上図データだとおそらくDBが6を選んで検索し、6以降の全データを取得して一つずつ8より小さくないかを比較します。また、その際に6と8どちらかの数字を選択するかを判断するには統計情報を使います。 likeでインデックスが効く場合 ここで少しBtree構造がわかった事だと思うので、前方一致ならlike検索でもインデックスが効く事を説明してみます。例えば、yamada、tanaka、suzuki、yamakawaさんがいた場合にBtreeの構造にしたらsuzuki、tanaka、yamada、yamakawaの順番になりますね。この時に下記のような条件で検索すればyamadaさんの直前の位置まで木構造の動きで辿りつく事ができ、それ以降のデータを取得する動きができるという事になります。「%yama%」のような中間一致や後方一致では、Btreeのソート順が活かせないためBtree検索はできません。 where name like 'yama%' 検索キーに関数や演算を使うとインデックスが効かない Btreeはデータをソートしている事が重要な訳ですが、例えば、下記のように関数を使った場合、ソート順が変わる可能性があります。 where date(update_time)='2018-01-01' もっとわかりやすくreverse関数を使えばソート順は真逆になります。一つ一つの関数や演算の特徴までDBは把握しきれないためインデックスを利用できません。 複合インデックスの構造 続いて複合インデックスの場合のBtree構造です。購入などの情報をイメージしてもらえると良いかと思います。今回はユーザーと購入日をイメージしてみます。(user_id,update_dt)にインデックスをつけてuser_idが0001〜0004の人が1/1から1/3まで何らかの操作をした場合、インデックス内部のBtreeはこのような並びになります。 ここで下記のように検索すれば木構造の動きで(0003,2018-01-02)まで到達します(黄色塗り)。 where user_id='0003' and update_dt>='2018-01-02' 後はそれ以降の第一キーが0003のリーフを取得すればいいわけです。(本当はINSERT順考えたらこの木構造にはならないけど、今回は気にしない) 複合インデックスの順番誤り 日付とキーの順番を逆にしている場合がよくあります。(update_dt,userid)でインデックスをつけているわけです。そうなるとこういった構造になります。 この状態で先ほどと同じく「user_id='0003' and update_dt>='2018-01-02'」を検索しても、第一キーであるupdate_dtが'2018-01-02'の先頭(黄色塗り)を検索して、それ以降の8つのデータを全て取得し、user_idが0003と同じかを比較するという処理になります。このようにキーの順番を間違えると非効率な処理となります。 キー飛ばし ソート順が重要なので、基本的に第一キーを飛ばして第二キーのみを指定したクエリを実行してもインデックスは機能しません。第三キーまであるインデックスを作ってwhere句で第二キーを指定しない場合は第一キーまでのソート順が利用できるため第一キーだけのインデックスと同じ動きとなります。 最適な複合インデックスの順番づけ そんなものはありません。まず、=で検索するキーを上位に置きます。続いて上で書いたような範囲検索で使うキー(よくあるのが日付)やinで取得するようなキーを指定します。必須であればあるほど上位のキーにする事が重要です。そして範囲検索やINでの検索はそれによってどれだけ絞り込みができるかが重要なのでアプリケーション仕様にまで踏み込まないとなかなか判断は難しいです。 アプリケーション仕様によって、キーが指定される場合とされない場合などがありますので、そういう場合は(key1,key2,key3)のインデックス以外に(key1,key3)のインデックスも作るなどアプリケーションが指定するキーと実行頻度を考えて最適なインデックス構成を考える必要があります。 最後に Btreeの構造を理解すればわかるSQLパフォーマンスに関わる事をいくつかあげてみました。パフォーマンスチューニングにはジョインアルゴリズムの理解なども大きく響くのですが、まずはBtreeの理解をするのが一番だと思います。むしろ、ここを理解していないと確信を持ってのチューニングはできません。内部構造を理解して説明できる方が増えればSQL、DBのパフォーマンスもよくなりますので、是非ご理解いただけると良いかと思います。 BASEのSREチームではお客様に安心して買い物をしていただくために、サービスの安定性に責任を持ち、インフラ・アーキテクチャの改善に日々取り組み続けております。 ご興味を持たれた方いらっしゃいましたら是非ご連絡いただければ幸いです。 binc.jp
この記事は、「BASE Advent Calendar 2018」の8日目の記事です。 devblog.thebase.in こんにちは、BASE Design Groupマネージャーの早川( @match0129 )です。 今日は、ネットショップ作成サービス「BASE」の管理画面のリニューアルプロジェクトである「次世代管理画面」の話を少ししてみたいと思います。 次世代管理画面とは? ネットショップ作成サービス「BASE」は、現在「次世代管理画面プロジェクト」として大規模なリニューアルの真っ最中です。 プロジェクトが最初にはじまったのは今年の1月で、今は最初の大きな区切りのリリースに向けて開発が佳境を迎えているところです。 キックオフから早1年経とうとしているこのプロジェクトについて、やってきたことを少し振り返ってみたいと思います。 プロジェクトの方向性とコンセプトの定義 そもそもなぜ今リニューアルか?というのは以前 「BASE U」の記事 になっているので詳細はそちらをご覧いただきたいのですが、いくつかキーワードをピックアップして紹介します。 これまでの5年と、これからの5年 「BASE」はサービス開始から昨年11月で5周年を迎えました。5年間、機能をより早くリリースすることが優先されてきた中で、山積してきたUI/UX上の課題。 これからの5年もショップオーナーに使い続けてもらう管理画面とするためには、個々の課題をつぎはぎ的に修正していくのでは限界があり、全体のUXの見直しから入る必要があるということになりました。 「お母さんも使える」から「難しいことを簡単に」 「BASE」は、もともと代表の鶴岡が「ネットショップをやりたい」と言った自分のお母さんのために作ったサービスということもあり、「お母さんも使える」というコンセプトの元、シンプルなUIで誰でも簡単にネットショップが作れるサービスとして開発されてきました。 5年たった今、60万店舗の多種多様なニーズがある中で、「BASE」本来の「シンプル」さを担保しつつ、どのように機能を提供していくか。例えばインスタ連携など、これまでは「お母さんも使えるか」の判断から実装しなかったような機能も、「どうしたら簡単に提供できるか」という切り口で考えていく必要があります。 機能からパートナーへ 次世代管理画面の方向性として、以下のコンセプトを定義しました。 【ものづくりを行う全て人にとって無くてはならないパートナー】 「BASE」の管理画面は、「機能」から「パートナー」へ。 0から1を生み出せるのはオンリーワンな能力。そんな方々がそこだけに集中するために、 その能力でしっかり生きていってもらい豊かな世の中を創造してもらうために。 本質以外を全て巻きとるパートナー。 課題の抽出 最初の課題の整理だけでも、かなり時間を使いました。これまでに上がってきたユーザーからの声やredmineチケットの整理と分類をしつつ、デザイナー、エンジニア、ディレクター、マーケティングなど部署をまたいだチームでワークショップを実施し、中心的に使われる機能についてのカスタマージャーニーマップを作成。 自分としては初めての取り組みで進行上の反省点も多かったですが、チームの中にはガチでショップを運営しているメンバーもいたりして、ショップを運営してみないとわからない目からウロコのUXの問題も多数発覚し、大きな収穫となりました。 まだ全機能でやりきれてないので、またタイミングみて実施したいと思っています。 BASEらしさの定義とUIコンポーネントの作成 デザイン上で大きな課題だったのが、 昨日の北村の記事 にもあったように、「BASE」全体を通して統一されていないボタンやフォームのコンポーネントのデザイン。次世代管理画面に向けて、UIコンポーネントのデザインを再定義することに。 デザインに入る前に、Design Groupで1日社内合宿をし、「BASE」らしさとは?についてディスカッションをしました。そのときに作成したのが、 以前の記事 でも紹介したこの図です。「誠実」が中央にあるのがポイント! ちなみに、この社内合宿当時にはまだなかったのですが、10月に60万店舗を達成したときに「 We are Owners 」というLPをリリースしました。 このWe are Ownersのメッセージ自体は代表の鶴岡の発案ですが、デザインチームで話し合った「BASEらしさ」とスムーズにシンクロした感があり、個人的にはかなり腹落ちしました。 UIコンポーネントはAtomic Designの考え方をベースに。Sketchライブラリとして作成することで、その後のデザイン作成の効率が大幅にアップしました。このあたりの詳細は後日デザイナー小山が記事にしてくれる予定です。 デザインとプロトタイピング デザイン作業自体の効率はかなり上がったとはいえ、抽出された課題をいかにデザインに落とし込むかはやはり骨の折れる作業です。Sketchのプロトタイピング機能を使い、実際に画面遷移や動きをみながらのプロトタイピングを繰り返しながら進めています。 デザインをする中でこのコンポーネント必要だね、ということが出てくる場合も多々あり。コンポーネント化するかどうかの線引きは、現状「3回以上それが出現するかどうか」を基準としています。 フロントエンドチームの誕生、開発のスタート これまで「BASE」のフロントエンドは、デザイナーがjQueryを頑張って書いて担保するという状態でしたが、同じような重複コードの頻発、CSSのクラス・id名との闇依存、jQuery複数バージョンの共存など、サービス開始から5年分の負債が地獄絵図の様相を呈していました。この辺の負債をどうするかというのも次世代の課題の一つでした。 今回のリニューアルにあたってはフロントエンドチームが新たに発足し、フロントエンドエンジニアのメンバーが中心となって過去の負債の返済と、Vue.js + TypeSrcript の新しいアーキテクチャの構築を同時に進めてくれています。 フロントエンドだけでなく、バックエンド側もAPI化などかなりの大掛かりな開発作業が進行中です。 新しいUIコンポーネントは、Vue.jsのコンポーネントとして実装。スタイルガイドにはStorybookを導入しています。 自分もこれまでは「 漢は黙ってjQuery 」!的なデザイナーでしたが、今回ようやくVue.jsに着手しました。 jQuery脳からの脱却にしばらく時間がかかってしまいましたが、ようやく慣れてきたと思える今日この頃です。 プロジェクトのこれから 今後5年に向けて、デザインだけでなくフロントエンド・バックエンドも含めたフルリニューアルとなっており、この規模のリニューアルに関わるのは自分も初めてで、この1年を振り返ると試行錯誤の連続であっという間でした。 リリースは段階的にしていきますが、「BASE」の管理画面全体でいうとまだまだ入り口です。 一つめの大きな機能の実装である程度パターンが見えてきたところで、来年以降はデザイン・開発ともに関わるメンバーも増やして複数機能を同時に進められるようにして開発効率を上げていければと考えています。 デザインチームとしても、今後はページの表示を少し直すだけでもVue.jsのコンポーネントを触らざるを得なくなるので、その開発まで全員ができる必要はないものの、ある程度Vue.jsに慣れていってもらいたいなと思っています。 ということで、来週はデザイナー向け「Vue bootcamp」がフロントエンド 三佐和教官 !によって実施される予定。 こちらの様子もアドベントカレンダーの記事になる予定なので、お楽しみに☆ 明日はデータベースエンジニアの植木が書きます。こちらもお楽しみに!!
この記事は、「BASE Advent Calendar 2018」の7日目の記事です。 devblog.thebase.in こんにちは、BASEのデザインチームに所属している北村( @naomi_kun )です。 BASEのデザイン管理ツールに「 Abstract 」を導入してちょうど1年が経ったので、導入する前を振り返りながら、良かったところの所感をまとめたいと思います。 はじめに 突然ですが、デザインデータの管理ってみなさんどうしていますか? 共有するのが大変だったり、バージョン管理のルールを厳格にしておかないとメンテがしづらかったりと、デザインデータの管理って非常に面倒ですよね。 BASEもGoogleDriveやDropboxを用いてデータ共有していたものの、ファイルの置き場が煩雑になったり、新しいデータがどれなのか毎回他のデザイナーに確認しなければならないなど、多くの課題を抱えていました。 デザインデータもGit管理したかった! デザインデータもGit管理したい、と当時同じプロジェクトを進めていたエンジニアさんに相談したところ「 Abstractってツールが良いらしいよ! 」と教えていただいたので、まずはそのプロジェクト内で1ヶ月試験導入してみました。 Abstract導入前の課題と問題点 データの管理が全くされていない😱 誰がどのデータを持っているのかすら分からない😱 複数人でデータを共有できる体制になっていない😱 UIコンポーネントも管理されていなかったので、人によってデザインが違う😱 この他にも、デザインレビューの際に毎回GitHubにissueを建てなければならず、アプリなど短期間で細かな改修を行うプロジェクトではデザイナーの負担が大きかったので、デザイン画面上にレビュー出来るシステムが欲しかったという背景もあります。 導入して1年、現在の状況 Abstractに登録されているプロジェクト一覧 現在はネットショップ作成サービス「BASE」、ショッピングアプリ「BASE」含む全てのプロジェクトをAbstract上で管理しています。 無料アカウントでもコメント機能が使えるので、ディレクターさん、エンジニアさんも含めると既に約40人規模での運用になっています。 Abstract導入後の改善点 データのバージョン管理ができる🤗 複数人で同一データ編集・共有できる体制になった🤗 誰がどのデータを触ったのか分かるようになった🤗 デザインシステムのおかげで統一されたUIでデザインされるようになった🤗 導入してみて変化したところ 実際の開発フロー 新規開発タスクが発生次第、MasterからFeastureブランチを切る ブランチ名は機能ベースの名前にする こまめにコミット Abstract上でデザインレビューする デザインがFixしたら完成形をZeplinへアップする デザイン作業終了後、Masterへマージ diffの確認がとても楽 AbstractでDiffを確認 Gitのように前回のコミットとの差分が分かるので、作業内容の確認がとても楽になりました。 エンジニアさんにお願いするときの共有方法も楽ちんです。 レビューがAbstract上で出来るようになった 今までのデザインレビューはGitHubのissueに画面に直接コメントできるので、 コミュニケーションコストも、作業効率も劇的に改善されました。 実際のレビュー画面 エンジニアさんもコメントしてくれます。 できる! Abstract使っていてもツライことがある Abstractでの管理体制が整ってきているものの、Abstractだけでの運用ではまだまだかゆいところに手が届かない状況です。 複数人のデザイナーが同時に作業するので頻繁にコンクリフトしたり、マージするとアートボードが重なってしまったり…。 先日のAdobeMAX Japanで、XDもバージョン管理機能が出来るようになると発表があったので、今後もウォッチしたいです。 まとめ Abstractを導入して1年が経ちましたが、デザインチーム内での意識改善はもちろん、エンジニアも巻き込んでのAbstract運用フローが根付きつつあると思います。 チーム内の作業効率も格段に上がったので、Abstractを導入していないチームは是非検討してみてはいかがでしょうか。 明日は id:match_1 さんです。お楽しみに! devblog.thebase.in
これは、「BASE Advent Calendar 2018」の6日目の記事です。 DataStrategyの齋藤( @pigooosuke )が担当します。 devblog.thebase.in はじめに 機械学習エンジニアの人は、分類や回帰などの課題に取り組むにあたって、偉い人や導入先の部門から「その予測どれぐらい外れるの?」「学習モデルの予測に対してどうリスク評価をすればいいの?」と尋ねられることはありませんか? そのような場面で活躍するかもしれないQuantile Regression(分位点回帰)のお話をします。 回帰モデルの評価 カテゴリーを予測するような分類問題では、各クラスでの精度を確認することはできます。しかし、売上や何かしらの値を予測する回帰問題では、そのモデルにおける特定地点での単一の予測値しか出力することが出来ず、その分布を把握することは単純ではありません。 # scikit-learnの線形回帰サンプル >>> import numpy as np >>> from sklearn.linear_model import LinearRegression >>> X = np.array([[ 1 , 1 ], [ 1 , 2 ], [ 2 , 2 ], [ 2 , 3 ]]) # 入力値のセット >>> y = np.dot(X, np.array([ 1 , 2 ])) + 3 # 正解データ >>> reg = LinearRegression().fit(X, y) >>> reg.predict(np.array([[ 3 , 5 ]])) # 入力[3, 5]に対して、予測値は1つ array([ 16. ]) ここで説明にあたって予測の確度という言葉を使うと定義が甘いのでもう少し分解します。回帰予測の範囲を把握する上でよく出てくるのは、この2種類ではないでしょうか。混同しないように事前に再確認しましょう。 信頼区間 Confidence interval ex. 95%信頼区間。こちらは、同じ条件で100回測定したら、計算した回帰曲線がその信頼区間内に収まった測定が95回ありましたという意味になります。 予測区間 Prediction interval ex. 95%予測区間。こちらは、今後観測しうるデータが100回出現したら、予測区間内に収まる観測が95回ありましたという意味になります。 下図は、標本に対して回帰曲線を計算したものです。 回帰曲線は信頼区間に収まり、標本は予測区間に収まります。 基本的には予測区間のほうが信頼区間の外側に位置します。 使い分けとしては、 モデルそのものの精度を測りたいのであれば 信頼区間 モデルにおける特定地点での予測値のばらつきを調べたいのであれば 予測区間 が目安になると思います。 今回お話をするQuantile Regressionは、予測区間を説明するために利用します。 Quantile Regression ~ 分位点回帰 ~ Quantileとは、日本語で四分位のことです。データをソートして区切った場合、それぞれのデータが上位何%に位置するのかを表現するときに使います。 2 quantileは、中央値と一致します。 0 quantile = 0 %ile (percentile: パーセンタイル) 1 quantile = 25 %ile 2 quantile = 50 %ile = median(中央値) 3 quantile = 75 %ile 4 quantile = 100 %ile Quantile Regressionは、線形回帰の損失関数を拡張したもので、通常のように二乗誤差を求めて平均値を最適化するのではなく、予め設定したquantile(percentile) での損失関数を最適化していきます。年収など偏りがある分布を平均値ではなく、中央値で確認したい場合に利用されます。用途としても、単純に各分位点での予測値の開きをみるだけでなく、例えば、年収or家賃の大小によって格差を図る指標がどれぐらい変化するのかを比較することによって変数の理解に繋がることもあり、社会学や経済学の分野で活用される事例が多くあります。 ちなみに、Quantile Regressionの推定には、check functionと呼ばれる常に絶対値を取るインジケーター関数を利用して、 以下の損失関数を最適化していきます。 手短に説明すると、正解値と予測値の差が正のときに 、 負のとき(反転するので正確には正)に が重み付けされた和をLossとしています。 導出を詳しく知りたい人はこちらのリンクが詳しいです。 原著(pdf) QUANTILE REGRESSION : ROGER KOENKER wikipedia, Quantile Regression Statistics/Numerical Methods/Quantile Regression 理論的な部分の解説 リンク先を見ても細かな部分の省略が多かったので、勉強ついでに自分でも導出をやってみました。興味がなければ読み飛ばし推奨です。 を確率変数、 を平均値、 をquantile(percentile)、 を分布の中心として定義した場合、平均は誤差の平方和の最小値で表せるように、中央値は絶対偏差和の最小値で表すことができます。 が 以下のときの を以下のように累積分布関数 を用いて定義します。 これを逆関数で表すとこうなります。 上で中央値を定義しましたが、これを一般化すると、 ] ここでの が最初に出てきた非負となるインジケーター関数です。 このインジケーター関数を一行で表現するとこうなります。 確率変数 のときにおける、確率密度関数を 、累積分布関数を とします。そして、離散値として で、連続値として で表現すると、それぞれ以下の通りになります。 上記に対し、 で微分し、左辺を0と置いたとき、 となり、 と分位点 が等しくなりました。 Pythonで試してみる Python系ライブラリのいくつかでは、このQuantile Regressionの損失関数がサポートされており、サンプルとして少し紹介してみます。 みんな大好きscikit-learn import numpy as np import matplotlib.pyplot as plt from sklearn.ensemble import GradientBoostingRegressor #### sin波にノイズを加えたデータセットでやってみます。 n = 300 # 標本数 noise = 0.2 # noiseの強さ np.random.seed( 1 ) x = np.linspace( 0 , 2 *np.pi, n) y = np.sin(x) + noise * np.random.randn(n) x = x.reshape(- 1 , 1 ) # 95%予測区間を求めるため、上限・下限ともに5%を2で等分した0.025, 0.975の位置で予測する alpha = 0.975 # model 定義 clf = GradientBoostingRegressor(loss= 'quantile' , alpha=alpha, n_estimators= 250 , max_depth= 3 , learning_rate= .1 , min_samples_leaf= 9 , min_samples_split= 9 ) # 上限の予測 clf.fit(x, y) y_upper = clf.predict(x) # alphaを反転して下限の予測 clf.set_params(alpha= 1.0 - alpha) clf.fit(x, y) y_lower = clf.predict(x) # 損失関数を最小2乗法に設定して予測 clf.set_params(loss= 'ls' ) clf.fit(x, y) y_pred = clf.predict(x) # vizualization fig = plt.figure(figsize=( 8 , 4 )) plt.plot(x, y, 'b.' , markersize= 10 , label= "標本" ) plt.plot(x, y_upper, 'k-' ) plt.plot(x, y_lower, 'k-' ) plt.plot(x, y_pred, 'r-' , label= '予測値' ) plt.fill(np.concatenate([x, x[::- 1 ]]), np.concatenate([y_upper, y_lower[::- 1 ]]), alpha= .5 , fc= 'b' , ec= 'None' , label= '95%予測区間' ) plt.legend(loc= 'upper right' ) plt.show() 現在は、アンサンブルの GradientBoostingRegressor でしか、この 損失関数 は設定出来ません。 ちなみに、以前から線形モデルに対してQuantile Regressionを追加しようという動きはあるようです。続報が待たれますね。 https://github.com/scikit-learn/scikit-learn/issues/3148 勾配ブースティングのLightGBM import lightgbm as lgb # 95%予測区間を求めるため、上限・下限ともに5%を2で等分した0.025, 0.975の位置で予測する alpha = 0.975 # model 定義 clf = lgb.LGBMRegressor(objective= 'quantile' , alpha=alpha, n_estimators= 250 , max_depth= 3 , learning_rate= .1 , min_samples_leaf= 9 , min_samples_split= 9 ) # 上限の予測 clf.fit(x, y) y_upper = clf.predict(x) # alphaを反転して下限の予測 clf.set_params(alpha= 1.0 - alpha) clf.fit(x, y) y_lower = clf.predict(x) # 損失関数を最小2乗法に設定して予測 clf.set_params(objective= 'regression' ) clf.fit(x, y) y_pred = clf.predict(x) # vizualization fig = plt.figure(figsize=( 8 , 4 )) plt.plot(x, y, 'b.' , markersize= 10 , label= "標本" ) plt.plot(x, y_upper, 'k-' ) plt.plot(x, y_lower, 'k-' ) plt.plot(x, y_pred, 'r-' , label= '予測値' ) plt.fill(np.concatenate([x, x[::- 1 ]]), np.concatenate([y_upper, y_lower[::- 1 ]]), alpha= .5 , fc= 'b' , ec= 'None' , label= '95%予測区間' ) plt.legend(loc= 'upper right' ) plt.show() 実際、scikit-learnに実装されている損失関数自体も中身は pred = pred.ravel() diff = y - pred alpha = self.alpha mask = y > pred if sample_weight is None : loss = (alpha * diff[mask]. sum () - ( 1.0 - alpha) * diff[~mask]. sum ()) / y.shape[ 0 ] と、非常にシンプルな構造になっています。 ちなみに、LightGBMの実装は以下のようになっていました。 class QuantileMetric : public RegressionMetric<QuantileMetric> { public : explicit QuantileMetric( const Config& config) :RegressionMetric<QuantileMetric>(config) { } inline static double LossOnPoint(label_t label, double score, const Config& config) { double delta = label - score; if (delta < 0 ) { return (config.alpha - 1.0f ) * delta; } else { return config.alpha * delta; } } inline static const char * Name() { return "quantile" ; } }; それぞれのleaf_valueでの正解と予測の差に対して重みを付けているだけなので、根本は同じですね。 ただし、もう一つの勾配ブースティング代表格のXgboostでは標準実装されておらず、自分で損失関数を設定する必要がありそうです。 興味がある人は自作してみると面白いかもしれませんね。 今回は、回帰モデルの出力を説明するという点でQuantile Regressionを紹介しました。 回帰モデルの出力に関して説明を求められたときの一つの手法として覚えておくと良さそうですね。 明日は、 id:lllitchi さんがデザインについて語ってくれます。お楽しみに!