SlideShare a Scribd company logo
1 of 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

More Related Content

What's hot

はじめよう 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
 

What's hot (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 to 【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 to 【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 という言語
 
サーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよサーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよ
 

More from 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
 

More from 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アプリ開発
 

Recently uploaded

モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...博三 太田
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)UEHARA, Tetsutaro
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfFumieNakayama
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfFumieNakayama
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NTT DATA Technology & Innovation
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineerYuki Kikuchi
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)Hiroshi Tomioka
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?akihisamiyanaga1
 

Recently uploaded (8)

モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
 

【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