π Chapter 10: ν©ν 리 ν¨ν΄
π λ¨μ ν μ€νΈβ
μꡬμ¬ν: μλ°μ€ν¬λ¦½νΈ μ½νΌλ°μ€λ λ§μ νλ μ ν μ΄μ μΌλ‘ νμ±ν κ²μ΄λ€. μΉνμ νλ μ ν μ΄μ λͺ¨λΈλ§μ κ³ λ―Ό μ€μ΄λ€.
νλ μ ν μ΄μ μ νμ λ κ°μ§, μ¦ μΌλ°(regular) νλ μ ν μ΄μ κ³Ό λ²€λ(vendor) νλ μ ν μ΄μ μΌλ‘ λλλ€. μΌλ° νλ μ ν μ΄μ μ μ λͺ©κ³Ό λ°νμ(μ ν) μ λ³΄κ° μκ³ , λ²€λ νλ μ ν μ΄μ μ μ¬κΈ°μ λ²€λλͺ , μ ν(μ ν) μ λ³΄κ° μΆκ°λλ€.
μΌλ²€ νλ μ ν μ΄μ | λ²€λ νλ μ ν μ΄μ | |
---|---|---|
title(μ λͺ©) | νμ | νμ |
presenter(λ°νμ) | μ ν | μ ν |
vendor(λ²€λ) | - | νμ |
product(μ ν) | - | μ ν |
μΉνμ Object.create
λ©μλλ‘ νλ‘ν νμ
μμμ ν΄λ³΄λ €κ³ λ€μμ²λΌ μΌλ°, λ²€λ νλ μ ν
μ΄μ
ν΄λμ€λ₯΄ μ½λ©νλ€.
// μΌλ° νλ μ ν
μ΄μ
var Conference = Conference || {};
Conference.Presentation = function(title, presenter) {
'use strict';
if (!(this instanceof Conference.Presentation)) {
throw new Error(Conference.Presentation.messages.mustUseNew);
}
if (!title) {
throw new Error(Conference.Presentation.messages.titleRequired);
}
this.title = title;
this.presenter = presenter;
};
Conference.Presentation.messages = {
mustUseNew: 'Presentationμ λ°λμ "new"λ‘ μμ±ν΄μΌ ν©λλ€.',
titleRequired: 'titleμ νμ μ
λ ₯ νλͺ©μ
λλ€.',
};
- λ²€λ νλ μ ν μ΄μ
// λ²€λ νλ μ ν
μ΄μ
var Conference = Conference || {};
Conference.VendorPresentation = function(title, presenter, vendor, product) {
'use strict';
if (!(this instanceof Conference.VendorPresentation)) {
throw new Error(Conference.VendorPresentation.messages.mustUseNew);
}
if (!vendor) {
throw new Error(Conference.VendorPresentation.messages.vendorRequired);
}
// μ€μ§μ μΈ μμμ μμ±μμ μλ λ€μ μ½λμμ μΌμ΄λλ€.
Conference.VendorPresentation.call(this, title, presenter);
this.vendor = vendor;
this.presenter = presenter;
};
// νλ‘ν νμ
μμμ΄ μ΄λ£¨μ΄μ§λ€.
Conference.VendorPresentation.prototype
= Object.create(Conference.Presentation.prototype);
Conference.VendorPresentation.messages = {
mustUseNew: 'VendorPresentationμ λ°λμ "new"λ‘ μμ±ν΄μΌ ν©λλ€.',
vendorRequired: 'vendorμ νμ μ
λ ₯ νλͺ©μ
λλ€.',
};
μ½λλ λ¬Έμ μμ΄ λμκ°μ§λ§, λ°νμ μμ΄ VendorPresentation
μ μμ±νλ κ΄κ²½μ΄ μ‘°κΈ λΆμμ°μ€λ½λ€.
new VendorPresentation('The title', undefined, 'The Vendor', 'The Product');
λΉλμ€, μΈλ―Έλ λ± μ νμ΄ μ ν λ€λ₯Έ νλ μ ν
μ΄μ
λ μλ€. μ΄λ€κΉμ§ Presentation
κ°μ²΄λ₯Ό μμνλ©΄ μ΄μν μμ±μλ₯Ό κ°κ² λμ§ μμκΉ? λν, νλ μ ν
μ΄μ
μ νμ λ€ μ½λμμ μμμ νμ
ν΄μΌ ν΄μΌλμ§ μμκΉ?
presentationFactory
κ°μ²΄μ create
λ©μλλ₯Ό λ§λ€κ³ νλ‘νΌν° λμΉλ‘ μ΄λ£¨μ΄μ§ νλΌλ―Έν°λ₯Ό νλ λ°μ μμμ μ²λ¦¬μν€λ©΄ λ κ±° κ°λ€.
describe('presentationFactory', () => {
var factory = Conference.presentationFactory();
describe('create(objectLiteral)', () => {
it('νλΌλ―Έν°μ μ΄μν νλ‘νΌν°κ° μμΌλ©΄ μμΈλ₯Ό λμ§λ€', () => {
var badProp = 'badProperty';
function createWithUnexpectedProperties() {
var badParam = {};
badParam[badProp] = 'unexpected!';
factory.create(badParam);
}
expect(createWithUnexpectedProperties).toThrowError(
Conference.presentationFactory.messages.unexpectedProperty + badProp
);
});
});
});
presentationFactory
μ 첫 λ²μ§Έ μ무λ νλΌλ―Έν°μ μ΄μν νλ‘νΌν°λ μλμ§ μ΄νΌλ μΌμ΄λ€.
var Conference = Conference || {};
Conference.presentationFactory = function presentationFactory() {
'use strict';
return {
// obj μΈμμ νλ‘νΌν°μ λ°λΌ
// νλμ Presentation λλ κ·Έ νμ Presentation μ€ νλλ₯Ό μμ±νλ€.
create: function(obj) {
var baseProperties = ['title', 'presenter'];
var vendorProperties = ['vendor', 'product'];
var allProperties = baseProperties.concat(vendorProperties);
var p;
var ix;
for (p in obj) {
if (allProperties.indexOf(p) < 0) {
throw new Error(
Conference.presentationFactory.messages.unexpectedProperty + p,
);
}
}
// λμ€μ Presentationμμ μ λν κ°μ²΄λ₯Ό λ°νν μμ
}
};
};
Conference.presentationFactory.messages = {
unexpectedProperty: 'μ΄μν νλ‘νΌν°λ₯Ό μ§λ μμ± νλΌλ―Έν°κ° μμ΅λλ€.',
};
λ€κ±°ν°λΈ ν μ€νΈλ₯Ό ν΅κ³Όνκ³ κ΄λ ¨ μ½λ©μ΄ λλ¬λ€λ©΄ λ€μμ ν©ν 리 λ³Έμ°μ λ‘μ§μ ꡬνν μ°¨λ‘λ€.
첫째, νλΌλ―Έν°μ κΈ°λ³Έ Presentation
κ°μ²΄μ νλ‘νΌν°λ§ μμΌλ©΄ create
λ©μλλ κ·Έλ₯ μ΄ κ°μ²΄λ₯Ό λ°ννλ€. μ΄λ° νλΌλ―Έν°κ° λμ΄μ€λ©΄ μ λ§ Presentation
μ΄ λ°νλλμ§ νμΈνλ λ¨μ ν
μ€νΈλ₯Ό μμ±νκΈ°λ μ¬μλ λ κ°μ§ μ€μν κ³ λ―Όκ±°λ¦¬λ₯Ό λ¨κΈ΄λ€.
Presentation
μμ±μμ μ¬λ°λ₯Έ νλΌλ―Έν°κ° μ λ¬λλμ§ μ΄λ»κ² νμ ν κΉ?- κ·Έλ λ€κ³ νλλΌλ μμ±λ κ°μ²΄κ° μ λ°νλμλμ§ λ¬΄μ¨ μλ‘ λ³΄μ₯ν κΉ?
describe('presentationFactory', () => {
'use strict';
var factory = Conference.presentationFactory();
var baseParameter = {
title: 'μλ°μ€ν¬λ¦½νΈλ₯Ό λ©μ§κ² μ¬μ©ν΄λ³΄μΈμ',
presenter: 'λ°κΈΈλ²',
};
describe('create(objectLiteral)', () => {
/** μ΄μ ν
μ€νΈ μ€μ **/
describe('κΈ°λ³Έ νλ‘νΌν°λ§ μμ κ²½μ°', () => {
var fakePresentation = {
title: 'νλ μ ν
μ΄μ
μ λ² λΌλ λ°©λ²',
};
var spyOnConstructor;
var returnedPresentation;
beforeEach(() => {
spyOnConstructor = spyOn(Conference, 'Presentation')
.and.returnValue(fakePresentation);
returnedPresentation = factory.create(baseParameter);
});
it('λͺ¨λ κ°μ Presentation μμ±μμ λκΈ΄λ€', () => {
expect(spyOnConstructor).toHaveBeenCalledWith(
baseParameter.title, baseParameter.presenter,
);
});
it('Presentation μμ±μλ₯Ό λ± ν λ²λ§ νΈμΆνλ€', () => {
expect(spyOnConstructor.calls.count()).toBe(1);
});
it('μμ±μ Presentationμ λ°ννλ€', () => {
expect(factory.create(baseParameter)).toBe(fakePresentation);
});
});
});
});
μ μμ μ κΈ°λ³Έ νλ μ ν μ΄μ μ ν©ν λ¦¬κ° μ μμ±νλμ§ νμΈνλ μΌμ΄ κ±°μ λ€κ³ , λλ¨Έμ§λ λ²€λ νλ μ ν μ΄μ κ΄λ ¨ ν μ€νΈλ€μ΄λ€.
describe('presentationFactory', () => {
'use strict';
var factory = Conference.presentationFactory();
var baseParameter = {
title: 'μλ°μ€ν¬λ¦½νΈλ₯Ό λ©μ§κ² μ¬μ©ν΄λ³΄μΈμ',
presenter: 'λ°κΈΈλ²',
};
describe('create(objectLiteral)', () => {
/** μ΄μ ν
μ€νΈ μ€μ **/
describe('κΈ°λ³Έ νλ‘νΌν°λ§ μμ κ²½μ°', () => {
// ν
μ€νΈλ₯Ό μ€μ
});
describe('VendorPresentation νλ‘νΌν°κ° μ μ΄λ νλ μ΄μ μμ κ²½μ°', () => {
var vendorParameter = {
title: 'μλ°μ€ν¬λ¦½νΈλ₯Ό λ©μ§κ² μ¬μ©ν΄λ³΄μΈμ',
presenter: 'λ°κΈΈλ²',
vendor: 'κΈΈλ²μΆνμ¬',
product: 'μλ°μ€ν¬λ¦½νΈ ν¨ν΄κ³Ό ν
μ€νΈ',
};
var fakeVendorPresentation = {
title: vendorParameter.title,
};
var spyOnConstructor;
beforeEach(() => {
spyOnConstructor = spyOn(Conference, 'VendorPresentation')
.and.returnValue(fakeVendorPresentation);
});
it('VendorPresentationμ μμ±ν΄λ³Έλ€', () => {
var expectedCallCount = 0;
function createParam(propName) {
var param = {};
var p;
for (p in baseParameter) {
param[p] = baseParameter[p];
}
param[propName] = vendorParameter[propName];
return param;
}
// κ° vendor νλ‘νΌν°λ₯Ό μ°¨λ‘λ‘ μ§λ νλΌλ―Έν°λ₯Ό μμ±νλ€.
['vendor', 'product'].forEach(function(propName) {
var param = createParam(propName);
var presentation = factory.create(param);
expect(spyOnConstructor.calls.count()).toBe(++expectedCallCount);
});
});
it('λͺ¨λ κ°μ VendorPresentation μμ±μμ λκΈ΄λ€', () => {
factory.create(vendorParameter);
expect(spyOnConstructor).toHaveBeenCalledWith(
vendorParameter.title, vendorParameter.presenter,
vendorParameter.vendor, vendorParameter.product,
);
});
it('VendorPresentation μμ±μλ₯Ό λ± ν λ²λ§ νΈμΆνλ€', () => {
factory.create(vendorParameter);
expect(spyOnConstructor.calls.count()).toBe(1);
});
it('μμ±ν VendorPresentationμ λ°ννλ€', () => {
expect(factory.create(vendorParameter)).toBe(fakeVendorPresentation);
});
});
});
});
π ν©ν 리 ν¨ν΄ ꡬνβ
ν μ€νΈλ‘ κΈ°λ₯μ λ€ μ 건νμΌλ μ΄μ ν©ν 리λ₯Ό ꡬννμ.
var Conference = Conference || {};
Conference.presentationFactory = function presentationFactory() {
'use strict';
return {
// obj μΈμμ νλ‘νΌν°μ λ°λΌ
// νλμ Presentation λλ κ·Έ νμ Presentation μ€ νλλ₯Ό μμ±νλ€.
create: function(obj) {
var baseProperties = ['title', 'presenter'];
var vendorProperties = ['vendor', 'product'];
var allProperties = baseProperties.concat(vendorProperties);
var p;
var ix;
for (p in obj) {
if (allProperties.indexOf(p) < 0) {
throw new Error(
Conference.presentationFactory.messages.unexpectedProperty + p,
);
}
}
// μΆκ°
for (ix = 0; ix < vendorProperties.length; ++ix) {
if (obj.hasOwnProperty(vendorProperties[ix])) {
return new Conference.VendorPresentation(
obj.title, obj.presenter, obj.vendor, obj.product,
);
}
}
return new Conference.Presentation(obj.title, obj.presenter);
}
};
};
Conference.presentationFactory.messages = {
unexpectedProperty: 'μ΄μν νλ‘νΌν°λ₯Ό μ§λ μμ± νλΌλ―Έν°κ° μμ΅λλ€.',
};
ν©ν λ¦¬κ° νλ μΌμ μ 리ν΄λ³΄μ.
create
μ νλΌλ―Έν°λ, μ΄μ μ κ°μ²΄ 리ν°λ΄λ‘ λκ²Όμ λundefined
λ‘ μ리 λΌμνλ 보기 νν ννμμ μμ ν λ²μ΄λ¬λ€.- νλΌλ―Έν°μ 무μμ΄λ μ 건λ€μ£ΌκΈ°λ§ νλ©΄ λ·μΌμ ν©ν λ¦¬κ° μμμ μ²λ¦¬νλ€.
- λμ€μ μ νμ΄ λ€λ₯Έ νλ μ ν μ΄μ λ μΌλ§λ μ§ μΆκ°ν μ μλ€.
new
ν€μλλ‘ κ°μ²΄λ₯Ό μμ±ν΄μΌ νλ€λ μ¬μ€μ ν©ν λ¦¬κ° λμ κΈ°μ΅ν΄μ€λ€.
π λ€λ₯Έ ν©ν 리 μ νβ
μ€μ§ ν κ°μ§ μ νμ κ°μ²΄λ§ μμ±νλ ν©ν λ¦¬κ° μλ€. κ°λ Ή μ¬κΈ°μ λ³Έ κ°μ²΄ 리ν°λ΄μ presentationParameterFactory
ν©ν λ¦¬λ‘ λ§λ€μ΄λΌ μ μλ€.
μ΄ μ₯μ ν©ν 리λ create
ν¨μ νλλ§ μμ§λ§, μ©λμ νΉνλ μ νλ³ create
λ©μλκ° μ¬λΏ μλ ν©ν 리λ μλ€.
ν©ν 리λ μ νλ³λ‘ νμν νκ²½μ ꡬμΆν μ μλ νΈλ¦¬ν κ³³μ΄λ€. νμ₯μμλ λ¨μ ν μ€νΈ, κΈ°λ₯ ν μ€νΈ, μ νλ§λ€ νκ²½μ΄ λ¬λΌμ§λ κ²½μ°κ° λ§μλ°, μμ‘΄μ±μ μ£Όμ νλ©΄ μν©μ λ§κ² μ μ ν ν©ν 리λ₯Ό μ μ©ν μ μλ€.
λμΌλ‘, ν©ν 리λ μ±κΈν€μΌλ‘λ λ°κΏ μΈ μ μμ΄μ 9μ₯μμ μ€λͺ ν μ¬λ¬ κ°μ§ μ±κΈν€μ μ μ©ν μ μλ€.
π μ 리νκΈ°β
μ°κ΄λ κ°μ²΄ μ€ νλλ₯Ό κΊΌλ΄ μμ±ν μ μλ ν©ν 리λ₯Ό μμ±νλ€. ν©ν 리μ λλΆλΆ create
κ°μ μ΄λ¦μ, νλ λλ κ·Έ μ΄μμ νλΌλ―Έν°λ₯Ό λ°λ λ©μλκ° νλ μλ€. μ΄ λ©μλλ μ λ¬λ°μ νλΌλ―Έν°λ₯Ό μ΄ν΄λ³΄κ³ μλ§μ κ°μ²΄λ₯Ό λ΄μ΄μ€λ€.
ν©ν 리λ κ°μ²΄ μμ±μ κ°λ ₯νκ² λ€μ€λ¦¬κ³ ν κ²Ή λ μΆμννλ€.
ν©ν 리 λ¨μ ν μ€νΈμμλ λ€μμ νμΈνμ.
create
ν¨μλ μλͺ»λ νλΌλ―Έν°λ₯Ό λ°μ§ μλλ€.- νλΌλ―Έν°κ° μ μμ μΌλ‘ μ λ¬λλ©΄ κ·Έμ λ°λ₯Έ, μκ°μ²΄μ μμ± ν¨μλ₯Ό μ νν νΈμΆνλ€.
- μ΄λ κ² νμ¬ λ°νλ κ°μ²΄κ² λ°λ‘
create
κ° λ°νν κ°μ²΄λ€.