Upload
takuma-morikawa
View
1.894
Download
2
Embed Size (px)
Citation preview
第一回 目黒スタートアップ勉強会
Takuma Morikawa / eureka, inc.
Copyright © 2009-2015 eureka, inc. All rights reserved.
Copyright © 2009-2015 eureka, inc. All rights reserved.
なまえ Takuma Morikawa しょぞく たんとう (Go, JS, たまにインフラ)
じこしょうかい
株式会社エウレカ
専門分野以外の領域 でも活躍できる
エンジニア! 50人
非エンジニア! 25人
事業内容 自社サービスの企画・開発・運営 ・ オンライン・デーティング・サービス「pairs」 ・ カップル専用アプリ「Couples」
海外拠点 ・ 唯麗家股份有限公司(台湾) ・ EUREKA SG Pte. Ltd.(シンガポール)
社員数: 75名 インターン・業務委託含む
オンライン・デーティング・サービス「pa i rs」
12年9月 13年3月 13年9月 14年3月 14年9月 15年3月
225万
。゚+\\200万会員突破//+.゚
リリース 2012年 10月
会員数 210万人
プラットフォーム PC/SP/iOS/Android
135万
45万
90万
190万 2年で 200万人
カップル専用アプリ「Coup les」
。゚+\\200万DL突破//+.゚
リリース 2014年 5月
DL数 210万DL
プラットフォーム iOS/Android
14年5月 14年10月 15年3月
215万
170万
130万
85万
45万
国内 No.1
・おそらく採用の第一候補に上がるJS FW
・元々pairsでも使っていた - メンバーはみんな書ける(はず)
・状態遷移が非常に楽 - pairsと相性が良い
・SPAにしたい
- アクション増加 => マッチング数増加
Why Angu la rJS?
$ jshint hoge.js: line 17, col 187, Line is too long. hoge.js: line 25, col 174, Line is too long. hoge.js: line 27, col 126, Line is too long. hoge.js: line 31, col 126, Line is too long. hoge.js: line 145, col 124, Line is too long. hoge.js: line 22, col 42, Expected '===' and instead saw '=='. hoge.js: line 24, col 44, Expected '===' and instead saw '=='. hoge.js: line 306, col 11, Missing semicolon. …
Why TypeScr ip t?
「リリース日は何としても死守して下さい」>ʕʘʘʔ
「さもなくばサービスが死にます」>ʕʘʘʔ
(私の首も飛びます)0ooʕʘʘʔ
「それとGWに合宿入れておきましたw」>ʕʘʘʔ
Why TypeScr ip t?
ʕº ºʔ<「そうだ!」
ʕº ºʔ<「iOS/Androidと同じAPI使って」
ʕº ºʔ<「PCとスマホで同じJSコード使えば」
ʕº ºʔ<「工数を削減できるぞ!」
Why TypeScr ip t?
app/ - 機能群/ - ログイン/ - 検索/ - controller/ - service/ - directive/ - routing.ts - 共通ライブラリ/ - e2eテスト/
Angu la rJS d i rec to ry s t ruc tu re
Angu la rJS rou te
module pairs.search {!!angular.module('pairs.search', [!! !'ui.router',!! !'ipCookie',!!]).config([!! !'$stateProvider', !! !'$urlRouterProvider', !! !'$locationProvider', !! !states!!]).service('SearchService', [!! !'HttpService', !! !'$q', !! !'ipCookie', !! !SearchService!!]).controller(controller)!!.directive(directive);!
Angu la rJS rou te
!function states(!! !$stateProvider: ng.ui.IStateProvider,!! !$urlRouterProvider: ng.ui.IUrlRouterProvider,!! !$locationProvider: ng.ILocationProvider!!) {!! !$stateProvider!! ! !.state('search', {!! ! ! !url: '^/search/:type/{page:int}',!! ! ! !controllerAs: 'ctrl',!! ! ! !controller: controller.SearchController,!! ! ! !templateUrl: '/search/hoge'!! ! !});!!}
・ロジックは、ほぼ書かない前提
・ディレクティブ用のshared controllerな感じ
=> RIP controller in Angular2
Angu la rJS con t ro l le r
・ベーシックにKarma & Jasmine(の予定) => 実はまだ整っていない…
・TSコンパイルは通るけど、karma実行時にTSエラーになる
・駄目だったらJSで書く予定
Angu la rJS un i t tes t ing
・ベーシックにKarma & Jasmine(の予定) => 実はまだ整っていない…
・TSコンパイルは通るけど、karma実行時にTSエラーになる
・駄目だったらJSで書く予定(来週のタスク)
Angu la rJS un i t tes t ing
【ディレクトリ構成】
- 機能テスト/ // 単体テスト
- シナリオテスト/ // 結合テスト
- ページオブジェクト/
- ログインページ/
- 検索ページ/
- helper.js
- config.js
Angu la rJS p ro t rac to r d i rec to ry
【ディレクトリ構成】
- 機能テスト/ // 単体テスト
- シナリオテスト/ // 結合テスト
- ページオブジェクト/ - ログインページ/
- 検索ページ/
- helper.js
- config.js
Angu la rJS p ro t rac to r d i rec to ry
・特定のHTMLの塊の機能に関する処理を書く
・テストコードから直接HTML elementは操作しない
・HTMLに関する処理はページオブジェクトに書く
・1ページ1オブジェクトじゃなくてもOK
Angu la rJS page ob jec t
Angu la rJS page ob jec t var LoginPage = function() {!
!// ログインボタンのエレメント! this.loginButton = element(by.id('login'))!!
!// ログインページを開く! this.open = function(){! browser.get('/#/login');! }!!
!// ログインボタンを押下する! this.clickLoginButton = function(){! var loginButton = new LoginPage().loginButton;! return browser.wait(function(){! return loginButton.isPresent();! }).then(function(){! return loginButton.click();! });! };!};!module.exports = new LoginPage();
【ディレクトリ構成】
- 機能テスト/ // 単体テスト
- シナリオテスト/ // 結合テスト
- ページオブジェクト/
- ログインページ/
- 検索ページ/
- helper.js
- config.js
Angu la rJS p ro t rac to r d i rec to ry
Angu la rJS he lper
// time_helper.js!!var TimeHelper = function(){!
!// 現在のUNIXTIMEを取得する!!this.getCurrentUnixtime = function(){!! !return Math.floor(new Date/1000);!!};!!!
};!!module.exports = TimeHelper;
Angu la rJS he lper
// helper.js!!var Helper = function(){};!!// 外部で定義したヘルパー関数をHelperへ詰め込む(mixin的な?)!require('./time_helper').call(Helper.prototype);!require('./selectbox_helper').call(Helper.prototype);!require('./hoge_helper').call(Helper.prototype);!!module.exports = new Helper();
Angu la rJS page ob jec t w / he lper
// login.po.js!!var LoginPage = function() {! // load helper!
!var helper = require('../helper');!!// 都道府県のセレクトボックス !
this.stateSelect = element(by.model('vm.state_id'));!!
!// セレクトボックスから指定した都道府県を選択する! this.selectStateByName = function(name){! var el = new LoginPage().stateSelect;! helper.selectDropdownByText(el, name);! }!};!!module.exports = new LoginPage();
・CircleCIの失敗 - Slackに通知行く - エラーに慣れる - 非常に困る
・なんで失敗するのか
- e2eがタイムアウトしてる - Angular以外のページ
Angu la rJS e2e w/ C I
・CircleCIの失敗 - Slackに通知行く - エラーに慣れる - 非常に困る
・なんで失敗するのか
- e2eがタイムアウトしてる - Angular以外のページ => Facebookのログインポップアップ
Angu la rJS e2e w/ C I
ʕº ºʔ<「無理」
ʕº ºʔ<「ログアウト機能追加しても無理」
ʕº ºʔ<「クッキー全削除でも無理」
ʕº ºʔ<「シークレットモード(Chrome)でも無理」
Angu la rJS e2e w/ C I
Angu la rJS e2e w/ C I
// circle.yml!!test:! override:!
!# Goのテスト! - gvm use stable; ginkgo -tags=tests -r . -cover!
!# メインのe2e! - gulp e2e! - sleep 2!
!# ログインページ その1! - gulp e2e:login_success! - sleep 2!
!# ログインページ その2! - gulp e2e:login_error1! - sleep 2!
!# ログインページ その3! - gulp e2e:login_error2
「世界で愛されるサービス」を一緒に作りませんか?
セグメントNo1 サービス
グローバルビジネス
Business!
pairs Goフルスクラッチ
Engineering!
マッチングアルゴリズム
Big Data!
✕
ハイブリッドエンジニア 大規模行動データ解析