Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

625 views

Published on

数多くの新規事業を展開するDeNAでは、コーポレートシステムもまた業務の多様性と変化への対応力を常に求められます。
SaaS/PaaSの積極的利用による効率化と、内製開発による社内ニーズへの即応性を両立してみると、思わぬところでエンジニアとしての技量を問われるような場面に遭遇します。定型的なワークフローやロジックを大量に実装することが求められる中、低レイヤーなデータアクセスやイベントハンドリングの手段しか用意されていない状況は決して珍しくありません。
本セッションではコーポレートシステム開発チームが直面してきた課題とそれに対する試行錯誤を紹介してみたいと思います。

Published in: Technology
  • Be the first to comment

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

  1. 1. #denatechcon #denatechcon DeNAにおける CorpTechエンジニアリング 長谷川 淳 経営企画本部企画統括部IT戦略部システム開発グループ
  2. 2. #denatechcon はじめに #CorpTech #JavaScript
  3. 3. #denatechcon 趣味 • 年賀状を描くこと • ドラムを叩くこと • 書物を読むこと • 漫画 • 小説 • 技術書 • 映像を観ること • ボヘミアン・ラプソディ • STEINS;GATE
  4. 4. #denatechcon 東京大学 大学院時代 • 神経生理学の基礎研究に従事 • 遺伝子操作マウスの網膜神経細胞の電気信号測定 • 伝達物質拡散と受容体反応のモンテカルロシミュレーション
  5. 5. #denatechcon 最近開発したもの • Slack上のワークフロー承認
  6. 6. #denatechcon アジェンダ • 体制とミッション • DeNA CorpTechの大原則 • SaaS + アドオン開発 • 実例1. NetSuite • 実例2. kintone • まとめ
  7. 7. #denatechcon 体制とミッション
  8. 8. #denatechcon 体制 • 経営企画本部 企画統括部 • 経理部 • 経営管理部 • コーポレートコミュニケーション部 • 秘書室 • IT戦略部 • ユーザーサポートグループ • 業務改革推進グループ • 技術推進グループ • システム開発グループ 正社員6名 派遣社員4名 業務委託0名
  9. 9. #denatechcon ミッション ITで事業/経営にデライトをもたらす
  10. 10. #denatechcon 多種多様なシステムたち • 会計システム • 財務諸表など法的に要求される書類の数字に直結 • 債務処理 (≒取引先に対するお支払い) は会社の信用問題 • アカウント管理 • 人事情報と連動したアカウント生成と権限付与剥奪 • 資産管理 • PC/ソフトウェアの従業員への割当 • 各種ワークフロー • 申請と承認の証跡 • 他多数 (GUI/API のあるものだけで80以上)
  11. 11. #denatechcon DeNA CorpTechの大原則
  12. 12. #denatechcon 導入コストで考えるならとにかくSaaS ⭕ システム導入/拡大時のリードタイム抑制 ⭕ 従量課金という損をしないモデル ⭕ グループ会社通じてガバナンスも効かせやすい ❌ 業務の多様性 (個別要件) には対応しにくい
  13. 13. #denatechcon 個別要件対応はしない方がいい? No!!
  14. 14. #denatechcon ミッション ITで事業/経営にデライトをもたらす
  15. 15. #denatechcon SaaS + アドオン開発
  16. 16. #denatechcon SaaS + アドオン開発の絶対重要ポイント 1. バージョン管理とデプロイを連動させよう • GUIからデプロイできる手軽な仕組みに甘んじない • masterブランチを経てのみ本番デプロイされる状態を確立
  17. 17. #denatechcon SaaS + アドオン開発の絶対重要ポイント 2. フレームワークを作ろう+結合テストをしよう • 各機能をSaaSの標準仕様に直接依存させない • 各機能がやりたいことにだけ集中できる環境を提供する Framework FuncFunc Func Func Func SaaS
  18. 18. #denatechcon 実例1. NetSuite
  19. 19. #denatechcon NetSuiteとは • Enterprise Resource Planning • 企業の各種資源の一元管理 • 全グループ会社の会計・人事情報の統合DBのようなイメージ • クラウドERPの火付け役 • サブスクリプション方式により当時他社製品の中で抜群に安価 • オンプレミスでありがちな会社毎のインスタンス乱立が起こりづらい • DeNAでも2012年頃から導入検討
  20. 20. #denatechcon サーバサイドカスタマイズ (JavaScript) • DB/画面要素へアクセスする専用関数群 • DBレコード操作に対するトリガー的処理追加 • 画面表示時 • 永続化前後 • 独自REST APIエンドポイント作成 • 独自画面作成
  21. 21. #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 ); }
  22. 22. #denatechcon じゃあ早速開発するぞと思いきや • ちょっと待って • デプロイってどうやるの?
  23. 23. #denatechcon NetSuite上の標準的なデプロイ手順 • .jsファイルをGUIからアップロード
  24. 24. #denatechcon NetSuite上の標準的なデプロイ手順 • 機能ごとにいろいろ設定 • 1つのメインスクリプトファイル • 実行する関数名 (エントリポイント) • 複数のライブラリファイル
  25. 25. #denatechcon じゃあ早速開発するぞと思いきや • ちょっと待って • 「ライブラリ」ってどうやって参照するの? • CommonJS? • Asynchronous Module Definition?
  26. 26. #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(); }
  27. 27. #denatechcon webpackを使えばいいじゃない CommonJS方式で書いて モジュールバンドル (≒ファイル結合) して 1つだけの.jsファイルとしてアップロードしよう • グローバルスコープ汚染からの解放 • 謎な読込順も気にならなくなる
  28. 28. #denatechcon webpackを使えばいいじゃない 無い
  29. 29. #denatechcon webpackもBrowserifyも無かった • 正確にはあったが存在を知らなかった • でもファイル分割してモジュール管理したい!
  30. 30. #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 ...
  31. 31. #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 ・ ・ ・
  32. 32. #denatechcon これで1つのファイルをアップロードするだけです • ちょっと待って • 結局アップロードは手動のまま?
  33. 33. #denatechcon 容易に想像のつく光景 • 開発してNetSuiteにアップロード • 各種動作確認を終えて一安心 • commit/pushを忘れる
  34. 34. #denatechcon 後日エンドユーザーから質問が! • 普通git上のファイルを調べます • でも幾ら見てみてもユーザーの言う挙動と違う • そんな思いはしたくないですよね
  35. 35. #denatechcon アップロードも自動化すればいいじゃない • GitHub:e + Jenkins + アップローダー (自作) • .jsファイルを受け取るAPIエンドポイント (自作)
  36. 36. #denatechcon やったね! • 手動アップロード作業からの解放 • ファイルの二重管理からの解放 • ついでに監査にも強くなった
  37. 37. #denatechcon 実例2. kintone
  38. 38. #denatechcon kintoneとは • システム構築システム • UI/DBをD&Dで定義 • ステータスと作業者 (assignee) を定義すればワークフローに • 標準的なREST APIも提供 • CRUD • UI/DB定義そのものもjson管理可能 • DeNAでは2013年に導入
  39. 39. #denatechcon ノンプログラミングでワークフローが作れる
  40. 40. #denatechcon さらに画面にJavaScriptを埋め込める • scriptタグで呼び出される一般的な状態 • 画面要素などへアクセスする専用関数群 • イベントハンドラ方式 • 画面表示時 • 値入力時 • レコード保存前後 • ステータス遷移時 • 無茶なDOM操作だってその気になれば
  41. 41. #denatechcon じゃあ早速開発するぞと思いきや • ちょっと待って • 作るものがどれも似てる&とても多いのだけど? • システムアカウント申請 • メールアドレス発行・ドメイン追加申請 • BYOD設定申請 • PC/モニタ追加交換申請 • 副業・クロスジョブ申請 • …
  42. 42. #denatechcon kintone JavaScriptカスタマイズの具体例 • あるあるパターン
  43. 43. #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; });
  44. 44. #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; });
  45. 45. #denatechcon こんなの大量生産したくない • 長い • 状態判定→画面更新処理ってjQuery時代の気分 • もっと宣言的に書ける仕組みがほしい! 無さそう
  46. 46. #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)) ) 状態判定を表す 抽象オブジェクト 論理演算はイベントが 発生する度に解決される 定型的な処理を ひととおり提供
  47. 47. #denatechcon これなら大量生産してもいいかな • ちょっと待って • 大量生産してもいいけど機能個別に自動テストは 書かなくていいの? Framework FuncFunc Func Func Func SaaS
  48. 48. #denatechcon Framework FuncFunc Func Func Func SaaS いいよ • e2eテストしておくから • 検証のためだけの機能を用意 • フレームワーク自体の挙動を徹底検証 • あくまで個別機能開発はスピーディに! Framework Test Func Func Func Func Func SaaSSaaS
  49. 49. #denatechcon やったね! • やりたいことだけ書ける枠組みの提供 • 個別自動テスト無用のスピード開発 • 1ランク上のリードタイム抑制
  50. 50. #denatechcon まとめ
  51. 51. #denatechcon SaaS + アドオン開発の絶対重要ポイント (再掲) 1. バージョン管理とデプロイを連動させよう • GUIからデプロイできる手軽な仕組みに甘んじない • masterブランチを経てのみ本番デプロイされる状態を確立
  52. 52. #denatechcon SaaS + アドオン開発の絶対重要ポイント (再掲) 2. フレームワークを作ろう+結合テストをしよう • 各機能をSaaSの標準仕様に直接依存させない • 各機能がやりたいことにだけ集中できる環境を提供する Framework FuncFunc Func Func Func SaaS
  53. 53. #denatechcon やったね!
  54. 54. #denatechcon #denatechcon

×