DeNAにおけるCorpTechエンジニアリング [DeNA TechCon 2019]

DeNA
DeNADeNA
#denatechcon
#denatechcon
DeNAにおける
CorpTechエンジニアリング
長谷川 淳
経営企画本部企画統括部IT戦略部システム開発グループ
#denatechcon
はじめに
#CorpTech
#JavaScript
#denatechcon
趣味
• 年賀状を描くこと
• ドラムを叩くこと
• 書物を読むこと
• 漫画
• 小説
• 技術書
• 映像を観ること
• ボヘミアン・ラプソディ
• STEINS;GATE
#denatechcon
東京大学 大学院時代
• 神経生理学の基礎研究に従事
• 遺伝子操作マウスの網膜神経細胞の電気信号測定
• 伝達物質拡散と受容体反応のモンテカルロシミュレーション
#denatechcon
最近開発したもの
• Slack上のワークフロー承認
#denatechcon
アジェンダ
• 体制とミッション
• DeNA CorpTechの大原則
• SaaS + アドオン開発
• 実例1. NetSuite
• 実例2. kintone
• まとめ
#denatechcon
体制とミッション
#denatechcon
体制
• 経営企画本部 企画統括部
• 経理部
• 経営管理部
• コーポレートコミュニケーション部
• 秘書室
• IT戦略部
• ユーザーサポートグループ
• 業務改革推進グループ
• 技術推進グループ
• システム開発グループ
正社員6名
派遣社員4名
業務委託0名
#denatechcon
ミッション
ITで事業/経営にデライトをもたらす
#denatechcon
多種多様なシステムたち
• 会計システム
• 財務諸表など法的に要求される書類の数字に直結
• 債務処理 (≒取引先に対するお支払い) は会社の信用問題
• アカウント管理
• 人事情報と連動したアカウント生成と権限付与剥奪
• 資産管理
• PC/ソフトウェアの従業員への割当
• 各種ワークフロー
• 申請と承認の証跡
• 他多数 (GUI/API のあるものだけで80以上)
#denatechcon
DeNA CorpTechの大原則
#denatechcon
導入コストで考えるならとにかくSaaS
⭕ システム導入/拡大時のリードタイム抑制
⭕ 従量課金という損をしないモデル
⭕ グループ会社通じてガバナンスも効かせやすい
❌ 業務の多様性 (個別要件) には対応しにくい
#denatechcon
個別要件対応はしない方がいい?
No!!
#denatechcon
ミッション
ITで事業/経営にデライトをもたらす
#denatechcon
SaaS + アドオン開発
#denatechcon
SaaS + アドオン開発の絶対重要ポイント
1. バージョン管理とデプロイを連動させよう
• GUIからデプロイできる手軽な仕組みに甘んじない
• masterブランチを経てのみ本番デプロイされる状態を確立
#denatechcon
SaaS + アドオン開発の絶対重要ポイント
2. フレームワークを作ろう+結合テストをしよう
• 各機能をSaaSの標準仕様に直接依存させない
• 各機能がやりたいことにだけ集中できる環境を提供する
Framework
FuncFunc Func Func Func
SaaS
#denatechcon
実例1. NetSuite
#denatechcon
NetSuiteとは
• Enterprise Resource Planning
• 企業の各種資源の一元管理
• 全グループ会社の会計・人事情報の統合DBのようなイメージ
• クラウドERPの火付け役
• サブスクリプション方式により当時他社製品の中で抜群に安価
• オンプレミスでありがちな会社毎のインスタンス乱立が起こりづらい
• DeNAでも2012年頃から導入検討
#denatechcon
サーバサイドカスタマイズ (JavaScript)
• DB/画面要素へアクセスする専用関数群
• DBレコード操作に対するトリガー的処理追加
• 画面表示時
• 永続化前後
• 独自REST APIエンドポイント作成
• 独自画面作成
#denatechcon
DBレコードが変更されるたびにメールを送る例
sendNotification(type) {
if (type == 'create') return;
varloginUserEmail = nlapiGetContext().getEmail();
varrecordType = nlapiGetRecordType();
varrecordId = nlapiGetRecordId();
varsubject = 'YOURCHANGEHASBEEN SUBMITTED!!';
varbody = 'Record Type: ' + recordType+ 'n’+
'ID: '+ recordId;
nlapiSendEmail(
loginUserEmail, // author
loginUserEmail, // recipient
subject,
body
);
}
#denatechcon
じゃあ早速開発するぞと思いきや
• ちょっと待って
• デプロイってどうやるの?
#denatechcon
NetSuite上の標準的なデプロイ手順
• .jsファイルをGUIからアップロード
#denatechcon
NetSuite上の標準的なデプロイ手順
• 機能ごとにいろいろ設定
• 1つのメインスクリプトファイル
• 実行する関数名 (エントリポイント)
• 複数のライブラリファイル
#denatechcon
じゃあ早速開発するぞと思いきや
• ちょっと待って
• 「ライブラリ」ってどうやって参照するの?
• CommonJS?
• Asynchronous Module Definition?
#denatechcon
// lib-a.js
var doA =
function() { ... };
// lib-a.js
initB();
var doA =
function() { ... };
まさかのブラウザ方式 (よりもタチが悪い方式)
• 参照はすべてグローバルスコープ経由
• モジュールの概念がない
• 設定したライブラリファイルの読込順が謎
• どうもファイルの内部的なID順らしい
• IDは最初にアップロードしたタイミングで割り当てられる
// lib-b.js
var initB =
function() { ... };
// main.js
function main {
doA();
}
内部ID: 101 内部ID: 102// main.js
function main {
initB();
doA();
}
#denatechcon
webpackを使えばいいじゃない
CommonJS方式で書いて
モジュールバンドル (≒ファイル結合) して
1つだけの.jsファイルとしてアップロードしよう
• グローバルスコープ汚染からの解放
• 謎な読込順も気にならなくなる
#denatechcon
webpackを使えばいいじゃない
無い
#denatechcon
webpackもBrowserifyも無かった
• 正確にはあったが存在を知らなかった
• でもファイル分割してモジュール管理したい!
#denatechcon
無ければ作ればいいじゃない
• 自作モジュールバンドラー in Gruntfile.coffee
• grunt-contrib-concat (ファイル結合プラグイン) を悪用
concat:
basic:
options:
process: (src,filePath) ->
ifmatched = filePath.match(/^dist/(.+).js$/)
libName =matched[1]
"// #{libName}n_libs.#{libName} =
function(exports, require,module) {n#{src}n};"
else
''
src: ['dist/fi_lib_*.js']
dest: 'dist/fi_lib.js'
extra:
options:
banner: "var require=(function(){n var_libs={};n ...
#denatechcon
がちゃっ
varrequire= (function(){
var_libs={};
var_loaded={};
varrequire=function(name,force){
...
if(namein _libs){
...
return_loaded[name].exports;
}
};
//fi_lib_core
_libs.fi_lib_core=function(exports,require,module){
(function(){
module.exports=this.dena= {
...
};
}).call(this);
};
//fi_lib_environment
_libs.fi_lib_environment= function(exports,require,module){
(function(){
...
JS
JS
JS
JS
・
・
・
#denatechcon
これで1つのファイルをアップロードするだけです
• ちょっと待って
• 結局アップロードは手動のまま?
#denatechcon
容易に想像のつく光景
• 開発してNetSuiteにアップロード
• 各種動作確認を終えて一安心
• commit/pushを忘れる
#denatechcon
後日エンドユーザーから質問が!
• 普通git上のファイルを調べます
• でも幾ら見てみてもユーザーの言う挙動と違う
• そんな思いはしたくないですよね
#denatechcon
アップロードも自動化すればいいじゃない
• GitHub:e + Jenkins + アップローダー (自作)
• .jsファイルを受け取るAPIエンドポイント (自作)
#denatechcon
やったね!
• 手動アップロード作業からの解放
• ファイルの二重管理からの解放
• ついでに監査にも強くなった
#denatechcon
実例2. kintone
#denatechcon
kintoneとは
• システム構築システム
• UI/DBをD&Dで定義
• ステータスと作業者 (assignee) を定義すればワークフローに
• 標準的なREST APIも提供
• CRUD
• UI/DB定義そのものもjson管理可能
• DeNAでは2013年に導入
#denatechcon
ノンプログラミングでワークフローが作れる
#denatechcon
さらに画面にJavaScriptを埋め込める
• scriptタグで呼び出される一般的な状態
• 画面要素などへアクセスする専用関数群
• イベントハンドラ方式
• 画面表示時
• 値入力時
• レコード保存前後
• ステータス遷移時
• 無茶なDOM操作だってその気になれば
#denatechcon
じゃあ早速開発するぞと思いきや
• ちょっと待って
• 作るものがどれも似てる&とても多いのだけど?
• システムアカウント申請
• メールアドレス発行・ドメイン追加申請
• BYOD設定申請
• PC/モニタ追加交換申請
• 副業・クロスジョブ申請
• …
#denatechcon
kintone JavaScriptカスタマイズの具体例
• あるあるパターン
#denatechcon
kintone JavaScriptカスタマイズの具体例
const dom=require('dom'); // DOM操作用に処理を切り出し
const isJoining =record =>/^1. /.test(record.applicationTypes.value);
const isOtherSnackSelected =record=> /^9. /.test(record.snacks.value);
// 項目の値変更時の画面制御
kintone.events.on([
'app.record.create.change.applicationTypes', 'app.record.create.change.snacks',
'app.record.edit.change.applicationTypes', 'app.record.edit.change.snacks',
],event => {
const record =event.record;
if(isJoining(record) && isOtherSnackSelected(record)) {
record.otherSnackName.disabled =false;
dom.setRequiredSymbolById('otherSnackName', true);
} else {
record.otherSnackName.value =''; // 非活性にするときは値も空にする
record.otherSnackName.disabled =true;
dom.setRequiredSymbolById('otherSnackName', false);
}
return event;
});
#denatechcon
kintone JavaScriptカスタマイズの具体例 (続き)
// 保存時の必須項目未入力エラー表示
kintone.events.on([
'app.record.create.submit',
'app.record.edit.submit',
],event => {
const record =event.record;
if(!isJoining(record) || !isOtherSnackSelected(record)) return event;
if(record.otherSnackName) return event;
event.error ='入力項目を確認してください。'; // 画面トップ
event.otherSnackName.error ='必須です。'; // 該当フィールドの真下
return event;
});
#denatechcon
こんなの大量生産したくない
• 長い
• 状態判定→画面更新処理ってjQuery時代の気分
• もっと宣言的に書ける仕組みがほしい!
無さそう
#denatechcon
無ければ作ればいいじゃない
• 自作kintoneフレームワーク
define=require('define’)
{where,except} =define.condition
joining = where('applicationTypes',/^1./)
otherSnackSelected=where('snacks',/^9./)
define.fields( ->
otherSnackName:
require:joining.and(otherSnackSelected)
disableAndClear:except(joining.and(otherSnackSelected))
)
状態判定を表す
抽象オブジェクト
論理演算はイベントが
発生する度に解決される
定型的な処理を
ひととおり提供
#denatechcon
これなら大量生産してもいいかな
• ちょっと待って
• 大量生産してもいいけど機能個別に自動テストは
書かなくていいの?
Framework
FuncFunc Func Func Func
SaaS
#denatechcon
Framework
FuncFunc Func Func Func
SaaS
いいよ
• e2eテストしておくから
• 検証のためだけの機能を用意
• フレームワーク自体の挙動を徹底検証
• あくまで個別機能開発はスピーディに!
Framework
Test
Func
Func Func Func Func
SaaSSaaS
#denatechcon
やったね!
• やりたいことだけ書ける枠組みの提供
• 個別自動テスト無用のスピード開発
• 1ランク上のリードタイム抑制
#denatechcon
まとめ
#denatechcon
SaaS + アドオン開発の絶対重要ポイント (再掲)
1. バージョン管理とデプロイを連動させよう
• GUIからデプロイできる手軽な仕組みに甘んじない
• masterブランチを経てのみ本番デプロイされる状態を確立
#denatechcon
SaaS + アドオン開発の絶対重要ポイント (再掲)
2. フレームワークを作ろう+結合テストをしよう
• 各機能をSaaSの標準仕様に直接依存させない
• 各機能がやりたいことにだけ集中できる環境を提供する
Framework
FuncFunc Func Func Func
SaaS
#denatechcon
やったね!
#denatechcon
#denatechcon
1 of 54

More Related Content

What's hot(20)

脱RESTful API設計の提案脱RESTful API設計の提案
脱RESTful API設計の提案
樽八 仲川14K views
MongoDB Oplog入門MongoDB Oplog入門
MongoDB Oplog入門
Takahiro Inoue7.2K views
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
Akihiro Suda7.5K views
イミュータブルデータモデルの極意イミュータブルデータモデルの極意
イミュータブルデータモデルの極意
Yoshitaka Kawashima23.8K views
トランザクションの設計と進化トランザクションの設計と進化
トランザクションの設計と進化
Kumazaki Hiroki71.4K views
【BS4】時は来たれり。今こそ .NET 6 へ移行する時。 【BS4】時は来たれり。今こそ .NET 6 へ移行する時。
【BS4】時は来たれり。今こそ .NET 6 へ移行する時。
日本マイクロソフト株式会社10.1K views
分散トレーシング技術について(Open tracingやjaeger)分散トレーシング技術について(Open tracingやjaeger)
分散トレーシング技術について(Open tracingやjaeger)
NTT Communications Technology Development23.2K views

Similar to DeNAにおけるCorpTechエンジニアリング [DeNA TechCon 2019](20)

どっかのしたのほうどっかのしたのほう
どっかのしたのほう
_norin_2.6K views
EmbulkとDigdagとデータ分析基盤とEmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤と
Toru Takahashi22.5K views
私とOSSの25年私とOSSの25年
私とOSSの25年
MITSUNARI Shigeo11.9K views
Hadoop Source Code Reading #17Hadoop Source Code Reading #17
Hadoop Source Code Reading #17
Shingo Furuyama6.8K views
Xcode4 project template (slide)Xcode4 project template (slide)
Xcode4 project template (slide)
Wataru Kimura1.2K views
HaikaraHaikara
Haikara
jewel12694 views
Docker勉強会Docker勉強会
Docker勉強会
namikikazuma138 views
Dockerを使ってみようDockerを使ってみよう
Dockerを使ってみよう
Ryo Adachi493 views

More from DeNA(20)

DeNAにおけるCorpTechエンジニアリング [DeNA TechCon 2019]