SlideShare una empresa de Scribd logo
1 de 40
ES2015 の class で
アプリケーションを
書いてみた話
Hiroyuki Kusu ( @hkusu_ )
YAPC::Asia Hachioji 2016 mid in Shinagawa
7/3 LT
■ 〜2015年12月
・Android アプリの開発
■ 2016年1月〜
・JavaScript アプリケーションの開発
Javaに
慣れ親む
わりと Java っぽいクラスベースの
オブジェクト志向でいけた!
(あくまで「ぽい」)
ES2015
■ ES2015 で書く
・Babel (トランスパイラ)
・Browserify (ブラウザ用の場合)
■ エディタ
・WebStorm (JetBrains 社製 IDE)
・like Android Studio
前提となる環境
class
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
getName() {
return this.name
}
getAge() {
return this.age
}
hello() {
return `こんにちは! ${this.name} さん`
}
}
export default Person
Person.js
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
getName() {
return this.name
}
getAge() {
return this.age
}
hello() {
return `こんにちは! ${this.name} さん`
}
}
export default Person
Person.js
コンストラクタ
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
getName() {
return this.name
}
getAge() {
return this.age
}
hello() {
return `こんにちは! ${this.name} さん`
}
}
export default Person
Person.js
インスタンス変数
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
getName() {
return this.name
}
getAge() {
return this.age
}
hello() {
return `こんにちは! ${this.name} さん`
}
}
export default Person
Person.js
インスタンスメソッド
class SomeUtil {
static isObject(arg) {
return typeof arg === 'object' && arg !== null && !Array.isArray(arg);
}
}
export default SomeUtil
SomeUtil.js
クラスメソッド
import Person from './Person'
class Men extends Person {
hello() {
return `おす! ${this.name} さん`
}
}
export default Men
Men.js
継承
1ファイル、1クラス(原則)
import Person from './Person'
import SomeUtil from './SomeUtil'
// …
const person = new Person('山田', 45)
クラスをインポートして利用
列挙型
(ぽいもの)
const Week = {
SUN: Symbol(),
MON: Symbol(),
TUE: Symbol(),
WED: Symbol(),
THU: Symbol(),
FRI: Symbol(),
SAT: Symbol(),
}
export default Week
import Week from './Week'
// …
const myWeek = Week.SUN
Week.js
利用例
const Action = {
SEARCH: Symbol(),
REGISTER: Symbol(),
UPDATE: Symbol(),
DELETE: Symbol(),
}
export default Action
Action.js
キーとして利用
(例えば Redux などで)
Singleton
import axios from 'axios'
import { config } from './../config/Config'
class QiitaApiService {
constructor(config) {
this.baseUrl = config.QIITA_BASE_URL
}
search(searchWord, perPage = 10) {
return this.httpGet(`search?q=${searchWord}&per_page=${perPage}`)
}
httpGet(query) {
return axios.get(`${this.baseUrl}/${query}`)
}
}
export default QiitaApiService
export const qiitaApiService = new QiitaApiService(config)
QiitaApiService.js
インスタンス化したものを export
import { qiitaApiService } from './service/QiitaApiService'
// …
qiitaApiService.search('JavaScript', 10)
.then(() => {
// ...
})
アプリケーション内で
インスタンスが共有される
アクセス修飾子
(private / protected)
with WebStorm
& JSDoc
import axios from 'axios'
import { config } from './../config/Config'
class QiitaApiService {
constructor(config) {
/** @private */
this.baseUrl = config.QIITA_BASE_URL
}
search(searchWord, perPage = 10) {
return this.httpGet(`search?q=${searchWord}&per_page=${perPage}`)
}
/**
* @private
*/
httpGet(query) {
return axios.get(`${this.baseUrl}/${query}`)
}
}
// …
QiitaApiService.js
private変数
privateメソッド
型チェック
with WebStorm
& JSDoc
// …
class QiitaApiService {
/**
* @constructor
* @param {Config|SpecConfig} config
*/
constructor(config) {
/** @private */
this.baseUrl = config.QIITA_BASE_URL
}
/**
* @param {string} searchWord
* @param {number} [perPage=10]
* @returns {promise}
*/
search(searchWord, perPage = 10) {
return this.httpGet(`search?q=${searchWord}&per_page=${perPage}`)
}
/**
* @param {string} query
* @returns {promise}
* @private
*/
httpGet(query) {
return axios.get(`${this.baseUrl}/${query}`)
}
}
// …
/** @type {QiitaApiService} */
export const qiitaApiService = new QiitaApiService(config)
型が迷子になったら @type で指定
Test
Repository層
Service層
Dependency injection
Config
利用 利用 利用
クラス内で出来るだけ別クラスを new() しない
static な状態の保持は可能な限り避ける
import { config } from './../config/Config'
import ItemRepository from './../repository/ItemRepository'
import QiitaApiService from './../service/QiitaApiService'
const itemRepository = new ItemRepository(new QiitaApiService(config))
Dependency injection
// ...
describe('ItemRepository', () => {
let itemRepository
let qiitaApiService
before(() => {
qiitaApiService = new QiitaApiService(config)
itemRepository = new ItemRepository(qiitaApiService)
});
describe('#getItemByWord', () => {
let qiitaApiServiceSearchStub
before(() => {
qiitaApiServiceSearchStub = sinon.stub(qiitaApiService, 'search')
qiitaApiServiceSearchStub.resolves({ result: 'success' })
});
after(() => {
qiitaApiServiceSearchStub.restore()
});
it('be fulfilled', (done) => {
expect(itemRepository.getItemByWord('abc', 99)).to.be.fulfilled
.then((result) => {
expect(qiitaApiServiceSearchStub).to.have.been.calledWith('abc', 99)
expect(result).to.eql({ result: 'success' })
})
.then(done, done)
})
})
})
※Mocha、Chai、Sinon.JS および Promise系のライブラリを利用
class 単位
でテスト
// ...
describe('ItemRepository', () => {
let itemRepository
let qiitaApiService
before(() => {
qiitaApiService = new QiitaApiService(config)
itemRepository = new ItemRepository(qiitaApiService)
});
describe('#getItemByWord', () => {
let qiitaApiServiceSearchStub
before(() => {
qiitaApiServiceSearchStub = sinon.stub(qiitaApiService, 'search')
qiitaApiServiceSearchStub.resolves({ result: 'success' })
});
after(() => {
qiitaApiServiceSearchStub.restore()
});
it('be fulfilled', (done) => {
expect(itemRepository.getItemByWord('abc', 99)).to.be.fulfilled
.then((result) => {
expect(qiitaApiServiceSearchStub).to.have.been.calledWith('abc', 99)
expect(result).to.eql({ result: 'success' })
})
.then(done, done)
})
})
})
メソッドの
テスト
// ...
describe('ItemRepository', () => {
let itemRepository
let qiitaApiService
before(() => {
qiitaApiService = new QiitaApiService(config)
itemRepository = new ItemRepository(qiitaApiService)
});
describe('#getItemByWord', () => {
let qiitaApiServiceSearchStub
before(() => {
qiitaApiServiceSearchStub = sinon.stub(qiitaApiService, 'search')
qiitaApiServiceSearchStub.resolves({ result: 'success' })
});
after(() => {
qiitaApiServiceSearchStub.restore()
});
it('be fulfilled', (done) => {
expect(itemRepository.getItemByWord('abc', 99)).to.be.fulfilled
.then((result) => {
expect(qiitaApiServiceSearchStub).to.have.been.calledWith('abc', 99)
expect(result).to.eql({ result: 'success' })
})
.then(done, done)
})
})
})
テスト対象のインスタンス
の組み立て
(必要に応じてテスト用の
ものと差し替え)
// ...
describe('ItemRepository', () => {
let itemRepository
let qiitaApiService
before(() => {
qiitaApiService = new QiitaApiService(config)
itemRepository = new ItemRepository(qiitaApiService)
});
describe('#getItemByWord', () => {
let qiitaApiServiceSearchStub
before(() => {
qiitaApiServiceSearchStub = sinon.stub(qiitaApiService, 'search')
qiitaApiServiceSearchStub.resolves({ result: 'success' })
});
after(() => {
qiitaApiServiceSearchStub.restore()
});
it('be fulfilled', (done) => {
expect(itemRepository.getItemByWord('abc', 99)).to.be.fulfilled
.then((result) => {
expect(qiitaApiServiceSearchStub).to.have.been.calledWith('abc', 99)
expect(result).to.eql({ result: 'success' })
})
.then(done, done)
})
})
})
必要に応じてスタブを用意
ほか
■ 静的解析
・ESLint を利用
・Airbnb の規約がおすすめ
・WebStorm と連携しておく
・JSDoc 漏れを検査させるとよい
■ ドキュメント生成
・ESDoc を利用
・テストコードとも連動できる
■ HTTP通信ライブラリ
・axios .. Promise に対応
まとめ
■ ES2015で普通にクラスベースのオブジェ
クト志向でアプリケーションが書ける
ようになった
■ IDE(WebStorm)でクラス含む型のサポート
もある程度うけられる
⇒ 機能はできるだけ class で表現する
.. ちゃんとやるなら TypeScript がいいと思う
Sample code
hkusu/react-app-example
※React 周りのコードも含んじゃってます
END

Más contenido relacionado

La actualidad más candente

はじめよう Backbone.js
はじめよう Backbone.jsはじめよう Backbone.js
はじめよう Backbone.jsHiroki Toyokawa
 
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門Kazunori Tatsuki
 
最強オブジェクト指向言語 JavaScript 再入門!
最強オブジェクト指向言語 JavaScript 再入門!最強オブジェクト指向言語 JavaScript 再入門!
最強オブジェクト指向言語 JavaScript 再入門!Yuji Nojima
 
Deep dive into oss written in swift
Deep dive into oss written in swiftDeep dive into oss written in swift
Deep dive into oss written in swiftYuki Asai
 
ECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミングECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミングTanUkkii
 
JavaScriptユーティリティライブラリの紹介
JavaScriptユーティリティライブラリの紹介JavaScriptユーティリティライブラリの紹介
JavaScriptユーティリティライブラリの紹介Yusuke Hirao
 
入門ClojureScript
入門ClojureScript入門ClojureScript
入門ClojureScriptsohta
 
Ruby Sapporo Night Vol.4
Ruby Sapporo Night Vol.4Ruby Sapporo Night Vol.4
Ruby Sapporo Night Vol.4Koji SHIMADA
 
クライアントサイドjavascript簡単紹介
クライアントサイドjavascript簡単紹介クライアントサイドjavascript簡単紹介
クライアントサイドjavascript簡単紹介しくみ製作所
 
第4回勉強会 Groovyの文法からSpockまで
第4回勉強会 Groovyの文法からSpockまで第4回勉強会 Groovyの文法からSpockまで
第4回勉強会 Groovyの文法からSpockまでMugen Fujii
 
React+TypeScriptもいいぞ
React+TypeScriptもいいぞReact+TypeScriptもいいぞ
React+TypeScriptもいいぞMitsuru Ogawa
 
JavaScript基礎勉強会
JavaScript基礎勉強会JavaScript基礎勉強会
JavaScript基礎勉強会大樹 小倉
 
Riot.js と戦った話 (8月26日 oRo LT 会)
Riot.js と戦った話 (8月26日 oRo LT 会)Riot.js と戦った話 (8月26日 oRo LT 会)
Riot.js と戦った話 (8月26日 oRo LT 会)kata shin
 
Deep dive into oss written in swift
Deep dive into oss written in swiftDeep dive into oss written in swift
Deep dive into oss written in swiftYuki Asai
 
Flux with RxSwift
Flux with RxSwiftFlux with RxSwift
Flux with RxSwiftYuji Hato
 
これからのJavaScriptー関数型プログラミングとECMAScript6
これからのJavaScriptー関数型プログラミングとECMAScript6これからのJavaScriptー関数型プログラミングとECMAScript6
これからのJavaScriptー関数型プログラミングとECMAScript6TanUkkii
 
React.jsでクライアントサイドなWebアプリ入門
React.jsでクライアントサイドなWebアプリ入門React.jsでクライアントサイドなWebアプリ入門
React.jsでクライアントサイドなWebアプリ入門spring_raining
 
ng-japan 2015 TypeScript+AngularJS 1.3
ng-japan 2015 TypeScript+AngularJS 1.3ng-japan 2015 TypeScript+AngularJS 1.3
ng-japan 2015 TypeScript+AngularJS 1.3Masahiro Wakame
 

La actualidad más candente (20)

はじめよう Backbone.js
はじめよう Backbone.jsはじめよう Backbone.js
はじめよう Backbone.js
 
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
 
最強オブジェクト指向言語 JavaScript 再入門!
最強オブジェクト指向言語 JavaScript 再入門!最強オブジェクト指向言語 JavaScript 再入門!
最強オブジェクト指向言語 JavaScript 再入門!
 
Deep dive into oss written in swift
Deep dive into oss written in swiftDeep dive into oss written in swift
Deep dive into oss written in swift
 
ECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミングECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミング
 
JavaScriptユーティリティライブラリの紹介
JavaScriptユーティリティライブラリの紹介JavaScriptユーティリティライブラリの紹介
JavaScriptユーティリティライブラリの紹介
 
覚醒!JavaScript
覚醒!JavaScript覚醒!JavaScript
覚醒!JavaScript
 
入門ClojureScript
入門ClojureScript入門ClojureScript
入門ClojureScript
 
Ruby Sapporo Night Vol.4
Ruby Sapporo Night Vol.4Ruby Sapporo Night Vol.4
Ruby Sapporo Night Vol.4
 
クライアントサイドjavascript簡単紹介
クライアントサイドjavascript簡単紹介クライアントサイドjavascript簡単紹介
クライアントサイドjavascript簡単紹介
 
第4回勉強会 Groovyの文法からSpockまで
第4回勉強会 Groovyの文法からSpockまで第4回勉強会 Groovyの文法からSpockまで
第4回勉強会 Groovyの文法からSpockまで
 
React+TypeScriptもいいぞ
React+TypeScriptもいいぞReact+TypeScriptもいいぞ
React+TypeScriptもいいぞ
 
JavaScript基礎勉強会
JavaScript基礎勉強会JavaScript基礎勉強会
JavaScript基礎勉強会
 
Riot.js と戦った話 (8月26日 oRo LT 会)
Riot.js と戦った話 (8月26日 oRo LT 会)Riot.js と戦った話 (8月26日 oRo LT 会)
Riot.js と戦った話 (8月26日 oRo LT 会)
 
Rubyize
RubyizeRubyize
Rubyize
 
Deep dive into oss written in swift
Deep dive into oss written in swiftDeep dive into oss written in swift
Deep dive into oss written in swift
 
Flux with RxSwift
Flux with RxSwiftFlux with RxSwift
Flux with RxSwift
 
これからのJavaScriptー関数型プログラミングとECMAScript6
これからのJavaScriptー関数型プログラミングとECMAScript6これからのJavaScriptー関数型プログラミングとECMAScript6
これからのJavaScriptー関数型プログラミングとECMAScript6
 
React.jsでクライアントサイドなWebアプリ入門
React.jsでクライアントサイドなWebアプリ入門React.jsでクライアントサイドなWebアプリ入門
React.jsでクライアントサイドなWebアプリ入門
 
ng-japan 2015 TypeScript+AngularJS 1.3
ng-japan 2015 TypeScript+AngularJS 1.3ng-japan 2015 TypeScript+AngularJS 1.3
ng-japan 2015 TypeScript+AngularJS 1.3
 

Similar a 【YAPC::Asia Hachioji 2016】ES2015のclassでアプリケーションを書いてみた話

New Generation Build System "Fly"
New Generation Build System "Fly"New Generation Build System "Fly"
New Generation Build System "Fly"deepblue will
 
JavaScript/CSS 2015 Autumn
JavaScript/CSS 2015 AutumnJavaScript/CSS 2015 Autumn
JavaScript/CSS 2015 AutumnKoji Ishimoto
 
JavaのGenericsとは?
JavaのGenericsとは?JavaのGenericsとは?
JavaのGenericsとは?Kenji Nakamura
 
JavaScriptおよびXPages Vote技術解説
JavaScriptおよびXPages Vote技術解説JavaScriptおよびXPages Vote技術解説
JavaScriptおよびXPages Vote技術解説賢次 海老原
 
cloud_firestore_schema_code_generation_for_flutter.pdf
cloud_firestore_schema_code_generation_for_flutter.pdfcloud_firestore_schema_code_generation_for_flutter.pdf
cloud_firestore_schema_code_generation_for_flutter.pdfKosuke Saigusa
 
SpringOne 2GX 2014 参加報告 & Spring 4.1について #jsug
SpringOne 2GX 2014 参加報告 & Spring 4.1について #jsugSpringOne 2GX 2014 参加報告 & Spring 4.1について #jsug
SpringOne 2GX 2014 参加報告 & Spring 4.1について #jsugToshiaki Maki
 
「Windows 8 ストア アプリ開発 tips」 hokuriku.net vol.11 (2013年1月26日)
「Windows 8 ストア アプリ開発 tips」  hokuriku.net vol.11 (2013年1月26日)「Windows 8 ストア アプリ開発 tips」  hokuriku.net vol.11 (2013年1月26日)
「Windows 8 ストア アプリ開発 tips」 hokuriku.net vol.11 (2013年1月26日)Fujio Kojima
 
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframeworkSpring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframeworkToshiaki Maki
 
DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~
DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~
DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~decode2016
 
ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用Yatabe Terumasa
 
traceur-compilerで ECMAScript6を体験
traceur-compilerで ECMAScript6を体験traceur-compilerで ECMAScript6を体験
traceur-compilerで ECMAScript6を体験Toshio Ehara
 
絶対落ちないアプリの作り方
絶対落ちないアプリの作り方絶対落ちないアプリの作り方
絶対落ちないアプリの作り方Fumihiko Shiroyama
 
TDC20111031_Groovy_Geb
TDC20111031_Groovy_GebTDC20111031_Groovy_Geb
TDC20111031_Groovy_GebNobuhiro Sue
 
速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-Kazunari Hara
 
第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」yoshiaki iwanaga
 
WordBench京都12月、WordCampUSからのWP REST APIな話
WordBench京都12月、WordCampUSからのWP REST APIな話WordBench京都12月、WordCampUSからのWP REST APIな話
WordBench京都12月、WordCampUSからのWP REST APIな話Hidetaka Okamoto
 
TypeScript & 関数型講座 第2回 TypeScript という言語
TypeScript & 関数型講座 第2回 TypeScript という言語TypeScript & 関数型講座 第2回 TypeScript という言語
TypeScript & 関数型講座 第2回 TypeScript という言語gypsygypsy
 
サーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよサーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよkoji lin
 

Similar a 【YAPC::Asia Hachioji 2016】ES2015のclassでアプリケーションを書いてみた話 (20)

New Generation Build System "Fly"
New Generation Build System "Fly"New Generation Build System "Fly"
New Generation Build System "Fly"
 
JavaScript/CSS 2015 Autumn
JavaScript/CSS 2015 AutumnJavaScript/CSS 2015 Autumn
JavaScript/CSS 2015 Autumn
 
JavaのGenericsとは?
JavaのGenericsとは?JavaのGenericsとは?
JavaのGenericsとは?
 
JavaScriptおよびXPages Vote技術解説
JavaScriptおよびXPages Vote技術解説JavaScriptおよびXPages Vote技術解説
JavaScriptおよびXPages Vote技術解説
 
cloud_firestore_schema_code_generation_for_flutter.pdf
cloud_firestore_schema_code_generation_for_flutter.pdfcloud_firestore_schema_code_generation_for_flutter.pdf
cloud_firestore_schema_code_generation_for_flutter.pdf
 
SpringOne 2GX 2014 参加報告 & Spring 4.1について #jsug
SpringOne 2GX 2014 参加報告 & Spring 4.1について #jsugSpringOne 2GX 2014 参加報告 & Spring 4.1について #jsug
SpringOne 2GX 2014 参加報告 & Spring 4.1について #jsug
 
「Windows 8 ストア アプリ開発 tips」 hokuriku.net vol.11 (2013年1月26日)
「Windows 8 ストア アプリ開発 tips」  hokuriku.net vol.11 (2013年1月26日)「Windows 8 ストア アプリ開発 tips」  hokuriku.net vol.11 (2013年1月26日)
「Windows 8 ストア アプリ開発 tips」 hokuriku.net vol.11 (2013年1月26日)
 
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframeworkSpring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
 
20141129-dotNet2015
20141129-dotNet201520141129-dotNet2015
20141129-dotNet2015
 
DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~
DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~
DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~
 
ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用
 
traceur-compilerで ECMAScript6を体験
traceur-compilerで ECMAScript6を体験traceur-compilerで ECMAScript6を体験
traceur-compilerで ECMAScript6を体験
 
Rx java x retrofit
Rx java x retrofitRx java x retrofit
Rx java x retrofit
 
絶対落ちないアプリの作り方
絶対落ちないアプリの作り方絶対落ちないアプリの作り方
絶対落ちないアプリの作り方
 
TDC20111031_Groovy_Geb
TDC20111031_Groovy_GebTDC20111031_Groovy_Geb
TDC20111031_Groovy_Geb
 
速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-
 
第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」
 
WordBench京都12月、WordCampUSからのWP REST APIな話
WordBench京都12月、WordCampUSからのWP REST APIな話WordBench京都12月、WordCampUSからのWP REST APIな話
WordBench京都12月、WordCampUSからのWP REST APIな話
 
TypeScript & 関数型講座 第2回 TypeScript という言語
TypeScript & 関数型講座 第2回 TypeScript という言語TypeScript & 関数型講座 第2回 TypeScript という言語
TypeScript & 関数型講座 第2回 TypeScript という言語
 
サーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよサーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよ
 

Más de Hiroyuki Kusu

【東京Node学園祭2016】Node.js × Babel で AWS Lambda アプリケーションを開発する
【東京Node学園祭2016】Node.js × Babel で AWS Lambda アプリケーションを開発する【東京Node学園祭2016】Node.js × Babel で AWS Lambda アプリケーションを開発する
【東京Node学園祭2016】Node.js × Babel で AWS Lambda アプリケーションを開発するHiroyuki Kusu
 
【Potatotips #30】RxJavaを活用する3つのユースケース
【Potatotips #30】RxJavaを活用する3つのユースケース【Potatotips #30】RxJavaを活用する3つのユースケース
【Potatotips #30】RxJavaを活用する3つのユースケースHiroyuki Kusu
 
【Potatotips #26】Replace EventBus with RxJava/RxAndroid
【Potatotips #26】Replace EventBus with RxJava/RxAndroid【Potatotips #26】Replace EventBus with RxJava/RxAndroid
【Potatotips #26】Replace EventBus with RxJava/RxAndroidHiroyuki Kusu
 
【Potatotips #23】手軽にHTTPでJSONにアクセスできる環境を用意する
【Potatotips #23】手軽にHTTPでJSONにアクセスできる環境を用意する【Potatotips #23】手軽にHTTPでJSONにアクセスできる環境を用意する
【Potatotips #23】手軽にHTTPでJSONにアクセスできる環境を用意するHiroyuki Kusu
 
【Roppongi.aar #1】Activity/FragmentからControllerへ処理を委譲する
【Roppongi.aar #1】Activity/FragmentからControllerへ処理を委譲する【Roppongi.aar #1】Activity/FragmentからControllerへ処理を委譲する
【Roppongi.aar #1】Activity/FragmentからControllerへ処理を委譲するHiroyuki Kusu
 
【DroidKaigi2015】初学者に嬉しいAndroid開発環境(あとMVCとか)
【DroidKaigi2015】初学者に嬉しいAndroid開発環境(あとMVCとか)【DroidKaigi2015】初学者に嬉しいAndroid開発環境(あとMVCとか)
【DroidKaigi2015】初学者に嬉しいAndroid開発環境(あとMVCとか)Hiroyuki Kusu
 
【eLV勉強会】AngularJSでのモバイルフロントエンド開発
【eLV勉強会】AngularJSでのモバイルフロントエンド開発【eLV勉強会】AngularJSでのモバイルフロントエンド開発
【eLV勉強会】AngularJSでのモバイルフロントエンド開発Hiroyuki Kusu
 
エンジニアにMacを薦める理由
エンジニアにMacを薦める理由エンジニアにMacを薦める理由
エンジニアにMacを薦める理由Hiroyuki Kusu
 
ソーシャルアプリで人を熱中させる要素を説明する一枚絵
ソーシャルアプリで人を熱中させる要素を説明する一枚絵ソーシャルアプリで人を熱中させる要素を説明する一枚絵
ソーシャルアプリで人を熱中させる要素を説明する一枚絵Hiroyuki Kusu
 
【ABC2014Spring LT】AngularJSでWEBアプリ開発
【ABC2014Spring LT】AngularJSでWEBアプリ開発【ABC2014Spring LT】AngularJSでWEBアプリ開発
【ABC2014Spring LT】AngularJSでWEBアプリ開発Hiroyuki Kusu
 

Más de Hiroyuki Kusu (10)

【東京Node学園祭2016】Node.js × Babel で AWS Lambda アプリケーションを開発する
【東京Node学園祭2016】Node.js × Babel で AWS Lambda アプリケーションを開発する【東京Node学園祭2016】Node.js × Babel で AWS Lambda アプリケーションを開発する
【東京Node学園祭2016】Node.js × Babel で AWS Lambda アプリケーションを開発する
 
【Potatotips #30】RxJavaを活用する3つのユースケース
【Potatotips #30】RxJavaを活用する3つのユースケース【Potatotips #30】RxJavaを活用する3つのユースケース
【Potatotips #30】RxJavaを活用する3つのユースケース
 
【Potatotips #26】Replace EventBus with RxJava/RxAndroid
【Potatotips #26】Replace EventBus with RxJava/RxAndroid【Potatotips #26】Replace EventBus with RxJava/RxAndroid
【Potatotips #26】Replace EventBus with RxJava/RxAndroid
 
【Potatotips #23】手軽にHTTPでJSONにアクセスできる環境を用意する
【Potatotips #23】手軽にHTTPでJSONにアクセスできる環境を用意する【Potatotips #23】手軽にHTTPでJSONにアクセスできる環境を用意する
【Potatotips #23】手軽にHTTPでJSONにアクセスできる環境を用意する
 
【Roppongi.aar #1】Activity/FragmentからControllerへ処理を委譲する
【Roppongi.aar #1】Activity/FragmentからControllerへ処理を委譲する【Roppongi.aar #1】Activity/FragmentからControllerへ処理を委譲する
【Roppongi.aar #1】Activity/FragmentからControllerへ処理を委譲する
 
【DroidKaigi2015】初学者に嬉しいAndroid開発環境(あとMVCとか)
【DroidKaigi2015】初学者に嬉しいAndroid開発環境(あとMVCとか)【DroidKaigi2015】初学者に嬉しいAndroid開発環境(あとMVCとか)
【DroidKaigi2015】初学者に嬉しいAndroid開発環境(あとMVCとか)
 
【eLV勉強会】AngularJSでのモバイルフロントエンド開発
【eLV勉強会】AngularJSでのモバイルフロントエンド開発【eLV勉強会】AngularJSでのモバイルフロントエンド開発
【eLV勉強会】AngularJSでのモバイルフロントエンド開発
 
エンジニアにMacを薦める理由
エンジニアにMacを薦める理由エンジニアにMacを薦める理由
エンジニアにMacを薦める理由
 
ソーシャルアプリで人を熱中させる要素を説明する一枚絵
ソーシャルアプリで人を熱中させる要素を説明する一枚絵ソーシャルアプリで人を熱中させる要素を説明する一枚絵
ソーシャルアプリで人を熱中させる要素を説明する一枚絵
 
【ABC2014Spring LT】AngularJSでWEBアプリ開発
【ABC2014Spring LT】AngularJSでWEBアプリ開発【ABC2014Spring LT】AngularJSでWEBアプリ開発
【ABC2014Spring LT】AngularJSでWEBアプリ開発
 

Último

NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NTT DATA Technology & Innovation
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルCRI Japan, Inc.
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video UnderstandingToru Tamaki
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Gamesatsushi061452
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイスCRI Japan, Inc.
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Hiroshi Tomioka
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...Toru Tamaki
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)Hiroshi Tomioka
 

Último (11)

NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 

【YAPC::Asia Hachioji 2016】ES2015のclassでアプリケーションを書いてみた話

  • 1. ES2015 の class で アプリケーションを 書いてみた話 Hiroyuki Kusu ( @hkusu_ ) YAPC::Asia Hachioji 2016 mid in Shinagawa 7/3 LT
  • 2.
  • 3. ■ 〜2015年12月 ・Android アプリの開発 ■ 2016年1月〜 ・JavaScript アプリケーションの開発 Javaに 慣れ親む
  • 5. ■ ES2015 で書く ・Babel (トランスパイラ) ・Browserify (ブラウザ用の場合) ■ エディタ ・WebStorm (JetBrains 社製 IDE) ・like Android Studio 前提となる環境
  • 7. class Person { constructor(name, age) { this.name = name this.age = age } getName() { return this.name } getAge() { return this.age } hello() { return `こんにちは! ${this.name} さん` } } export default Person Person.js
  • 8. class Person { constructor(name, age) { this.name = name this.age = age } getName() { return this.name } getAge() { return this.age } hello() { return `こんにちは! ${this.name} さん` } } export default Person Person.js コンストラクタ
  • 9. class Person { constructor(name, age) { this.name = name this.age = age } getName() { return this.name } getAge() { return this.age } hello() { return `こんにちは! ${this.name} さん` } } export default Person Person.js インスタンス変数
  • 10. class Person { constructor(name, age) { this.name = name this.age = age } getName() { return this.name } getAge() { return this.age } hello() { return `こんにちは! ${this.name} さん` } } export default Person Person.js インスタンスメソッド
  • 11. class SomeUtil { static isObject(arg) { return typeof arg === 'object' && arg !== null && !Array.isArray(arg); } } export default SomeUtil SomeUtil.js クラスメソッド
  • 12. import Person from './Person' class Men extends Person { hello() { return `おす! ${this.name} さん` } } export default Men Men.js 継承
  • 14. import Person from './Person' import SomeUtil from './SomeUtil' // … const person = new Person('山田', 45) クラスをインポートして利用
  • 16. const Week = { SUN: Symbol(), MON: Symbol(), TUE: Symbol(), WED: Symbol(), THU: Symbol(), FRI: Symbol(), SAT: Symbol(), } export default Week import Week from './Week' // … const myWeek = Week.SUN Week.js 利用例
  • 17. const Action = { SEARCH: Symbol(), REGISTER: Symbol(), UPDATE: Symbol(), DELETE: Symbol(), } export default Action Action.js キーとして利用 (例えば Redux などで)
  • 19. import axios from 'axios' import { config } from './../config/Config' class QiitaApiService { constructor(config) { this.baseUrl = config.QIITA_BASE_URL } search(searchWord, perPage = 10) { return this.httpGet(`search?q=${searchWord}&per_page=${perPage}`) } httpGet(query) { return axios.get(`${this.baseUrl}/${query}`) } } export default QiitaApiService export const qiitaApiService = new QiitaApiService(config) QiitaApiService.js インスタンス化したものを export
  • 20. import { qiitaApiService } from './service/QiitaApiService' // … qiitaApiService.search('JavaScript', 10) .then(() => { // ... }) アプリケーション内で インスタンスが共有される
  • 22. import axios from 'axios' import { config } from './../config/Config' class QiitaApiService { constructor(config) { /** @private */ this.baseUrl = config.QIITA_BASE_URL } search(searchWord, perPage = 10) { return this.httpGet(`search?q=${searchWord}&per_page=${perPage}`) } /** * @private */ httpGet(query) { return axios.get(`${this.baseUrl}/${query}`) } } // … QiitaApiService.js private変数 privateメソッド
  • 23.
  • 25. // … class QiitaApiService { /** * @constructor * @param {Config|SpecConfig} config */ constructor(config) { /** @private */ this.baseUrl = config.QIITA_BASE_URL } /** * @param {string} searchWord * @param {number} [perPage=10] * @returns {promise} */ search(searchWord, perPage = 10) { return this.httpGet(`search?q=${searchWord}&per_page=${perPage}`) } /** * @param {string} query * @returns {promise} * @private */ httpGet(query) { return axios.get(`${this.baseUrl}/${query}`) } } // …
  • 26.
  • 27. /** @type {QiitaApiService} */ export const qiitaApiService = new QiitaApiService(config) 型が迷子になったら @type で指定
  • 28. Test
  • 29. Repository層 Service層 Dependency injection Config 利用 利用 利用 クラス内で出来るだけ別クラスを new() しない static な状態の保持は可能な限り避ける
  • 30. import { config } from './../config/Config' import ItemRepository from './../repository/ItemRepository' import QiitaApiService from './../service/QiitaApiService' const itemRepository = new ItemRepository(new QiitaApiService(config)) Dependency injection
  • 31. // ... describe('ItemRepository', () => { let itemRepository let qiitaApiService before(() => { qiitaApiService = new QiitaApiService(config) itemRepository = new ItemRepository(qiitaApiService) }); describe('#getItemByWord', () => { let qiitaApiServiceSearchStub before(() => { qiitaApiServiceSearchStub = sinon.stub(qiitaApiService, 'search') qiitaApiServiceSearchStub.resolves({ result: 'success' }) }); after(() => { qiitaApiServiceSearchStub.restore() }); it('be fulfilled', (done) => { expect(itemRepository.getItemByWord('abc', 99)).to.be.fulfilled .then((result) => { expect(qiitaApiServiceSearchStub).to.have.been.calledWith('abc', 99) expect(result).to.eql({ result: 'success' }) }) .then(done, done) }) }) }) ※Mocha、Chai、Sinon.JS および Promise系のライブラリを利用 class 単位 でテスト
  • 32. // ... describe('ItemRepository', () => { let itemRepository let qiitaApiService before(() => { qiitaApiService = new QiitaApiService(config) itemRepository = new ItemRepository(qiitaApiService) }); describe('#getItemByWord', () => { let qiitaApiServiceSearchStub before(() => { qiitaApiServiceSearchStub = sinon.stub(qiitaApiService, 'search') qiitaApiServiceSearchStub.resolves({ result: 'success' }) }); after(() => { qiitaApiServiceSearchStub.restore() }); it('be fulfilled', (done) => { expect(itemRepository.getItemByWord('abc', 99)).to.be.fulfilled .then((result) => { expect(qiitaApiServiceSearchStub).to.have.been.calledWith('abc', 99) expect(result).to.eql({ result: 'success' }) }) .then(done, done) }) }) }) メソッドの テスト
  • 33. // ... describe('ItemRepository', () => { let itemRepository let qiitaApiService before(() => { qiitaApiService = new QiitaApiService(config) itemRepository = new ItemRepository(qiitaApiService) }); describe('#getItemByWord', () => { let qiitaApiServiceSearchStub before(() => { qiitaApiServiceSearchStub = sinon.stub(qiitaApiService, 'search') qiitaApiServiceSearchStub.resolves({ result: 'success' }) }); after(() => { qiitaApiServiceSearchStub.restore() }); it('be fulfilled', (done) => { expect(itemRepository.getItemByWord('abc', 99)).to.be.fulfilled .then((result) => { expect(qiitaApiServiceSearchStub).to.have.been.calledWith('abc', 99) expect(result).to.eql({ result: 'success' }) }) .then(done, done) }) }) }) テスト対象のインスタンス の組み立て (必要に応じてテスト用の ものと差し替え)
  • 34. // ... describe('ItemRepository', () => { let itemRepository let qiitaApiService before(() => { qiitaApiService = new QiitaApiService(config) itemRepository = new ItemRepository(qiitaApiService) }); describe('#getItemByWord', () => { let qiitaApiServiceSearchStub before(() => { qiitaApiServiceSearchStub = sinon.stub(qiitaApiService, 'search') qiitaApiServiceSearchStub.resolves({ result: 'success' }) }); after(() => { qiitaApiServiceSearchStub.restore() }); it('be fulfilled', (done) => { expect(itemRepository.getItemByWord('abc', 99)).to.be.fulfilled .then((result) => { expect(qiitaApiServiceSearchStub).to.have.been.calledWith('abc', 99) expect(result).to.eql({ result: 'success' }) }) .then(done, done) }) }) }) 必要に応じてスタブを用意
  • 36. ■ 静的解析 ・ESLint を利用 ・Airbnb の規約がおすすめ ・WebStorm と連携しておく ・JSDoc 漏れを検査させるとよい ■ ドキュメント生成 ・ESDoc を利用 ・テストコードとも連動できる ■ HTTP通信ライブラリ ・axios .. Promise に対応
  • 40. END