ããã¯ãªã«ïŒ
ãããºã a.k.a. ç«åèé³æ©ããMVVMãšCleanArchitectureã®è§£èª¬ã®ããã«äœã£ããã¢ã¢ããªã±ãŒã·ã§ã³ã§ãããç¶æ ããããããã€ããã®ãšããŠããã©ã ã·ãŒã±ã³ãµãŒãå®è£ ããŸããããã¢ãGithubPagesã§å ¬éããŠããŸãã
MVVM ã LayeredArchitectureãClean Architectureã®ååã¯ç¥ã£ãŠãããæ··ä¹±ããŠããããšããã²ãšã察象èªè ãšããŠæ³å®ããŠããŸãã
ãŸãã¯ãMVVMãLayered Architectureã®æŠèŠããèŠãŠãããŸãããã
MVVM ãš DDD-like Layered Architecture
MVVMãã¿ãŒã³ã¯ãGUIã®ã¢ãŒããã¯ãã£ãã¿ãŒã³ã®äžçš®ã§ãPresentationãšDomainã®åé¢ïŒPDSïŒãç®çãšãããã¿ãŒã³ã§ããMVVMãã¿ãŒã³ãæ¡çšããããšã«ãã£ãŠããã©ãããã©ãŒã äŸåãªUIãå®çŸãããã¬ãŒã³ããŒã·ã§ã³å±€ãViewãšViewModelã«æžãããã®ä»ãã¹ãŠãModelã«æžãããšã«ãã£ãŠããè€éã ããã©ãããã©ãŒã äŸåã§ãã¹ããã«ããUIã®ã³ãŒãããšãã¢ããªã±ãŒã·ã§ã³ã®æåãã¢ããªã³ã°ããã³ãŒãããåé¢ããããšãã§ããŸãã
ãã®äžæ¹ã§ãMVVMã¯ãã¢ãã«ã¯ããèšèšããŸãããããšããããšã«ã€ããŠã¯æéããããŸãããããã¯ãèšãæ¹ãå€ããã°ãMVVMãæ¡çšãããããšãã£ãŠã¢ããªã±ãŒã·ã§ã³å šäœã®èšèšã決ãŸãããã§ã¯ãªããMVVMã¯ããã¬ãŒã³ããŒã·ã§ã³ãšãã®ä»ãã©ããã£ãŠåããããã«ã€ããŠæéããããã ãããšããããšã§ãã
ãšããã§ãæ··ä¹±ãèµ·ãããããã€ã³ãã§ãããPDSã®è©±ãããŠãããšãDomainããšããèšèãåºãŠããŸããããã®ãDomainããšããèšèã¯ãããããDDDã®è©±ãããŠãããšãã®ãDomainããšããèšèãšæå³ãç°ãªããŸãããªã®ã§ããDomainããšããèšèãåºãŠãããšãã«ã¯ããä»ã¯ã©ã®æèã§ããDomainã®ããšã ããããšç¢ºèªããªããé²ãããã«ããŠãã ããã
äžæ¹ãLayered Architectureã¯ããã®åã®ãšããããã¢ããªã±ãŒã·ã§ã³å šäœãå±€ã«åããŠèšèšããŸããããããšããæéã§ããDDDã®æèã§ã¯ãããããã¬ãŒã³ããŒã·ã§ã³ããã¢ããªã±ãŒã·ã§ã³ãããã¡ã€ã³ããã€ã³ãã©ã¹ãã©ã¯ãã£ãã®å±€ã«åããããšã«ãã£ãŠããã¡ã€ã³ç¥èãããã¡ã€ã³å±€ïŒããã§èšããã¡ã€ã³å±€ã¯PDSã®æèã«ããããã¡ã€ã³å±€ã®ããšã§ã¯ãªããŠãDDDã®æèã«ããããã¡ã€ã³å±€ã§ãïŒã«åé¢ããããšããæ¹éãåãããããšãå€ãããã§ãããããããã§ã¯ãDDD-like Layered ArchitectureããšåŒã³ãŸãããã
ãŸãæ··ä¹±ãèµ·ãããããã€ã³ããªã®ã§åŒ·èª¿ããŠãããŸãããDDDãšããèãæ¹èªäœã¯ç¹å®ã®ã¢ãŒããã¯ãã£ã«äŸåããèãæ¹ã§ã¯ãããŸããããŸããä»åããã§DDD-like Layered ArchiterãšåŒãã§ããã¢ãŒããã¯ã㣠== DDDãšããããã§ããããŸããã
- äžå®ä»¥äžã«è€éãªã¢ããªã±ãŒã·ã§ã³ã¯ã(PDSã®æèã§èšã)Domainå±€ã®äžãå€å±€ã«åããã»ããè¯ã
- äžå®ä»¥äžã«è€éãªã¢ããªã±ãŒã·ã§ã³ã¯ãDDDã®èãæ¹ãåãå ¥ãããšèŠéãããããªãããšããã
- DDDã®èãæ¹ãåãå
¥ãããããããªå±€å士ã®åé¢ã®ä»æ¹ããããã§ã¯DDD-like Layered ArchitectureãšåŒãã§ãã
- ãã®åãæ¹ãšã¯ãã¢ããªã±ãŒã·ã§ã³å šäœãããã¬ãŒã³ããŒã·ã§ã³ããã¢ããªã±ãŒã·ã§ã³ãããã¡ã€ã³ããã€ã³ãã©ã¹ãã©ã¯ãã£ãã®4å±€ã«åãããšããåãæ¹ã§ãã
ãšããããšã ãšæã£ãŠãã ããã
ããŠãããã¡ã€ã³å±€(PDSã®æè)ã®èšèšã®ãããã ã£ãŠããããããããšãã話ãMVVMã¢ãŒããã¯ãã£ã®ã¡ãªããã«ã€ããŠãåéã®é¢ä¿äžãä»åã¯ããŸã詳ãã説æã§ããŠããŸããããããã§ã«äœãèšã£ãŠããã®ãããããâŠâŠããšããåãã«ã¯ãæåå³åã§ãã以äžã®è³æãããããã§ãããã¡ããèªãã ããšã«ããäžåºŠãã®READMEãèªãã§ããã ããšãããç解ãããããããããŸããã
- see ããã®æ¥èŠãM V Whateverã®Modelãåãã¡ã¯ãŸã ç¥ããªããå®æ³äžç¶
- see å®æ³äžç¶ã·ãªãŒãº Vue.jsã§å®çŸããMVVMãã¿ãŒã³ Fluxã¢ãŒããã¯ãã£ãšã®è·é¢
ããŠãPDSãMVVMãDDD-like Layered Architectureãšããã¿ã£ã€ã®æŠå¿µãåºãŠããŸããããã¹ãŠããã¢ããªã±ãŒã·ã§ã³ãã©ã®ããã«åå²ããããã«ã€ããŠã®æéã§ãããæèãç°ãªããŸãã®ã§ããããæŽçããŠã¿ãŸãããã
PDSã¯ããã¬ãŒã³ããŒã·ã§ã³ãšãã®ä»ãåããŸãããããšããæéã§ãã
MVVMã¯ããå®éã«ãã¬ãŒã³ããŒã·ã§ã³ãšãã®ä»ãåãããšãã«ã¯ãããããµãã«ãããšãããããšããæéããããŸãã
DDD-like Layered Architectureã¯ããã®ããã®ä»ãã®éšåãããã«çŽ°ãããApplicationããDomainããInfrastructureãã«åãããDDDã®èãããã«ããããããããªã¢ããªã±ãŒã·ã§ã³å šäœã®åãããã¯ããããããµãã«ãããšããããšãå€ããããšããæéããããŸãã
ãããã®é¢ä¿ãå³ã«è¡šããšãäžå³ã®ããã«ãªããŸãã
å³ïŒïŒPDSãšMVVMãšDDD-like Layered Architectureã®é¢ä¿
ãã®ããã¥ã¡ã³ãã§ã¯ãå®éãã®ãªããžããªã§éçºãããŠããã¢ããªã±ãŒã·ã§ã³ã®å®è£ äŸãéããŠããããããã®ã¬ã€ã€ãŒããããããã©ã®ããã«åŒã³åºãããäŸåãããããã«ãŒã«ã«ãããšãããã«ãããã®å±€ãåé¢ã§ããã®ããã«ã€ããŠèŠãŠãããŸãã
MVVMã«ããPDSã®å®çŸ
ãŸãã¯ãMVVMãå°å ¥ããããšã§PDSãã©ã®ããã«å®çŸãããã®ããèŠãŠãããŸãããã
ViewModelã®æã€ã¿ã£ã€ã®è²¬å
MVVMã«ãããŠãïŒPDSã®æèã«ãããïŒPresentationãšDomainãšã®ãããšããå®çŸããŠãããã®ã¯ViewModelã§ããViewModelã¯ãã¿ã£ã€ã®è²¬åãæã€ããšã§PresentationãšDomainã仲ä»ããŸãã
- Viewã®æç»ã®ããã«å¿ èŠãªããŒã¿ã®ä¿æ
- Viewããã®ã€ãã³ãã«å¿ããŠãModelã®voidãªã¡ãœãããåŒã³åºã
- ã¢ãã«ã®å€åã€ãã³ãã«å¿ããŠãã¢ãã«ã®å€ãèªã¿åºããŠèªèº«ã®ããŒã¿ãæŽæ°ãã
ã§ã¯ãããã§å®éã«ãViewãšViewModelã®å®è£
ãèŠã«è¡ã£ãŠã¿ãŸããããä»åã®ã¢ããªã±ãŒã·ã§ã³ãªãã°ã/presentation/vue_components
ã«ããããŠãããã®ãViewãšViewModelã«ãªããŸããããã§ã¯ã³ã³ãããŒã«ããã«ã®ã³ã³ããŒãã³ããèŠãŠã¿ãŸãããããã®ã³ã³ããŒãã³ãã§ã¯ããã¢ã¢ããªã®ãåçãã¿ã³ãšãbpmã¹ã©ã€ããŒãããéšåãã®ViewãšViewModelãå®çŸ©ãããŠããŸãã
å³ïŒïŒåçãã¿ã³ãšãbpmã¹ã©ã€ããŒãããéšå
Viewã®æç»ã®ããã«å¿ èŠãªããŒã¿ã®ä¿æãšãã責å
ãŸãã¯ãViewã®æç»ã®ããã«å¿
èŠãªããŒã¿ã®ä¿æãšãã責åã«ã€ããŠèŠãŠãããŸããããscriptã®äžèº«ã«ãdata
ãšããã¡ãœãããšcomputed
ãšããããããã£ããããŸãïŒVue.jsãå®çŸ©ããŠãããŠããã€ã§ããïŒããVue.jsã«ãããŠã¯ãããããŸãã«ãViewã®ããã®ããŒã¿ã®ä¿æãã®åœ¹å²ã§ãã
data(){
return {
bpm: this.usecase.player.bpm,
selectedPatternId: this.usecase.sequencer.selectedPatternId,
playingState: this.usecase.player.playingState,
isSoundsInited: this.usecase.player.isSoundsInited
}
},
computed:{
playButtonIcon(){
if (this.playingState) {
return 'stop';
} else {
return 'play_arrow';
}
}
}
ãŸãã¯data
ãèŠãŠã¿ãŸããããããšãã°ãbpmã¹ã©ã€ããŒã®äœçœ®ãããçŸåšã®BPMããæç»ããããã«ã¯ãçŸåšèšå®ãããŠããbpmãããã€ãªã®ããšããæ
å ±ãå¿
èŠã«ãªããŸãããã©ãžãªãã¿ã³ã®ã©ããéžæãããŠããããæç»ããããã«ã¯ãä»ã©ã®ãã¿ãŒã³ãéžæãããŠããããšããæ
å ±ãå¿
èŠã«ãªããŸããåãããã«ããã¿ã³ã«åçããŒã¯ãåºããåæ¢ããŒã¯ãåºããã決ããããã«ã¯ãçŸåšåçäžãªã®ãåçäžã§ãªãã®ããšããæ
å ±ãå¿
èŠã«ãªããŸãããããã®æ
å ±ããdata
ã§è¿ããªããžã§ã¯ãã®ããããã£ãšããŠå®çŸ©ããŠããŸãã
ãŸãããã®ã¢ããªã±ãŒã·ã§ã³ã¯materializeãšããcssãã¬ãŒã ã¯ãŒã¯ãå©çšããŠããŸãããmaterializeã§ã¯åçããŒã¯ãåºãããã«ã¯play_arrow
ãšããæååããåæ¢ããŒã¯ãåºãããã«ã¯stop
ãšããæååãå¿
èŠã«ãªããŸããã©ã¡ãã®æååãViewã«æž¡ãã¹ãããšããã®ã¯ãplayingState
ã決å®ããã°èªåçã«æ±ºå®ããŸããããããã£ãããŒã¿ã«ã€ããŠã¯ãcomputed
ãšããããããã£ã«å®çŸ©ããŠããããšããã§ãããã
ããã§å®çŸ©ãããããããã£ã¯ãtemplate
ã®ãªãã§Vue.jsãçšæããŠããããã£ã¬ã¯ãã£ããªã©ããèªã¿åºãããšãã§ããŸããVue.jsã®è©³ãã䜿ãããã«ã€ããŠèª¬æãå§ãããšé·ããªã£ãŠããŸãã®ã§ïŒãšã¯ããåŠç¿ã³ã¹ãã®äœããã¬ãŒã ã¯ãŒã¯ã§ã¯ãããŸãïŒã詳ããã¯Vue.jsã®å
¬åŒã®ããã¥ã¡ã³ããåœãã£ãŠãã ããã
Viewããã®ã€ãã³ãã«å¿ããŠãModelã®voidãªã¡ãœãããåŒã³åºã責å
次ã«ãViewããã®ã€ãã³ãã«å¿ããŠãModelã®voidãªã¡ãœãããåŒã³åºã責åã«ã€ããŠèŠãŠãããŸããmethods
ãšããããããã£ããã®è²¬åãå®çŸããŠããŸãã
methods: {
setBpm(){
const bpm = document.getElementById("bpm-slider").value;
this.usecase.setBpm(bpm);
},
setPatternId() {
this.usecase.selectPattern(this.selectedPatternId);
},
togglePlayingState(){
this.usecase.togglePlayingState();
}
}
bpmã¹ã©ã€ããŒã®Viewã¯
<input type="range" id="bpm-slider" min="10" max="240" :value="bpm" @input="setBpm"/>
ãšå®çŸ©ãããŠããŸããããŠãŒã¶ãã¹ã©ã€ããŒãå€åããããšãHTMLäžã«å®çŸ©ãããŠãã@input="setBpm"
ã€ãã³ããçºç«ããmethods
ããããã£å
ã«å®çŸ©ãããŠããsetBpm
ã¡ãœãããåŒã³åºãããŸãããããããViewããã®ã€ãã³ãã«å¿ããã®éšåã§ããsetBpm
ã¡ãœããã®äžèº«ãèŠãŠã¿ããšãDOMãããçŸåšéžæãããŠããbpmããèªã¿åºããthis.usecase
ã®ã¡ãœãããåŒã³åºããŠããŸããthis.usecase
ã«ã€ããŠã詳ããã¯åŸè¿°ããŸãããViewModelãä¿æããŠããããModelå±€ã®çªå£ãã ãšæã£ãŠãã ãããããããModelã®voidãªã¡ãœãããåŒã³åºããã®éšåã§ãã
ã¢ãã«ã®å€åã€ãã³ãã«å¿ããŠãã¢ãã«ã®å€ãèªã¿åºããŠèªèº«ã®ããŒã¿ãæŽæ°ãã責åã«ã€ããŠ
æåŸã«ãã¢ãã«ã®å€åã€ãã³ãã«å¿ããŠãã¢ãã«ã®å€ãèªã¿åºããŠèªèº«ã®ããŒã¿ãæŽæ°ãããšãã責åã«ã€ããŠèŠãŠãããŸãããã
ããã»ã©ããViewããã®ã€ãã³ãã«å¿ããŠãModelã®voidãªã¡ãœãããåŒã³åºãã責åã«ã€ããŠèŠãŸãããããããåœãããŸãã§ãããvoidãªã¡ãœããã«ã¯è¿ãå€ããããŸãããããã§ã¯ããViewModel -> Modelãã®ã³ãã¥ãã±ãŒã·ã§ã³ã¯ã§ããŸããããModel -> ViewModelãã®ã³ãã¥ãã±ãŒã·ã§ã³ãã§ããŸãããã
MVVMã¢ãŒããã¯ãã£ã§ã¯ãModelããViewModelãžã®ã³ãã¥ãã±ãŒã·ã§ã³ã¯ãModelãå€åãããããšããã€ãã³ããéç¥ãã圢ã§è¡ããŸããViewModelã¯ããã®ã€ãã³ããåãåã£ãããModelã®å
容ãèªã¿åã£ãŠãèªèº«ã®ããŒã¿ã«æžãæ»ããŸãããããè¡ã£ãŠããã®ãcreated
ããããã£ã§ãã
created(){
this.subscriptions.push(
// (1)
this.usecase.selectedPatternChanged.subscribe(() => {
this.selectedPatternId = this.usecase.sequencer.selectedPatternId;
})
);
this.subscriptions.push(
this.usecase.playingStateChanged.subscribe(() => {
this.playingState = this.usecase.player.playingState;
})
);
this.subscriptions.push(
this.usecase.bpmChanged.subscribe(() => {
this.bpm= this.usecase.player.bpm;
})
);
this.subscriptions.push(
this.usecase.isSoundsInitedChanged.subscribe(() => {
console.debug(this.usecase.player);
this.isSoundsInited = this.usecase.player.isSoundsInited;
})
);
},
ãŸãã¯
//(1)
this.usecase.selectedPatternChanged.subscribe(() => {
this.selectedPatternId = this.usecase.sequencer.selectedPatternId;
})
ã®éšåãèŠãŠãã ããããModelã®çªå£ãã«åœããusecase
ããselectedPatternChanged
ãšããããããã£ãæã£ãŠããŸããModelãä¿æããŠãããä»ã©ã®ãã¿ãŒã³ãéžæãããŠãããããšããæ
å ±ãå€åãããšãã«ããã®ããããã£ã¯ã€ãã³ããçºç«ãããŸãïŒãšããããModelå±€ã«ããããåŠçãæžãããŠããŸãïŒã
ã§ããã®ããããã£ã«å¯ŸããŠãsubscribe
ããããšã§ããªã¹ããŒãç»é²ããŠããŸãããªã¹ããŒã®äžèº«ã¯ãthis.selectedPatternId = this.usecase.sequencer.selectedPatternId;
ãšãªã£ãŠããããã¢ãã«ã®å€ãèªã¿åºããŠããŠãèªèº«ã®ããŒã¿ïŒdata
ããããã£ã§å®çŸ©ãããã€ã§ãïŒã«æžãæ»ããŠããŸãããViewModelã®ããŒã¿ãããããŠæŽæ°ããããšãVue.jsã®ãããŒã¿ãã€ã³ããã®ä»çµã¿ã§ãç»é¢ãæžãæããããšããããã§ãã
this.subscriptions
ãšãã¯ãBase.js
ã§å®çŸ©ãããŠããã€ã§ãããã«ç»é²ããŠããããªã¹ããŒã¯ã³ã³ããŒãã³ããç Žæ£ããããšãã«åæã«unsubscribe
ããŠãããããã«ãªã£ãŠããŸãã
created
ã¯ã³ã³ããŒãã³ããäœããããšãã«åŒã°ããhookã§ãããã³ã³ããŒãã³ããäœããããšãã«ãModelãå€åããã£ãŠããã€ãã³ããåãåã£ãããã®å
容ãèªåã«æžãæ»ãããšãããªã¹ããŒãç»é²ããŠããããã§ããã
ViewModelã®æã€ã¿ã£ã€ã®è²¬åãŸãšã
ããŠãããã§ã
- Viewã®æç»ã®ããã«å¿ èŠãªããŒã¿ã®ä¿æ
- Viewããã®ã€ãã³ãã«å¿ããŠãModelã®voidãªã¡ãœãããåŒã³åºã
- ã¢ãã«ã®å€åã€ãã³ãã«å¿ããŠãã¢ãã«ã®å€ãèªã¿åºããŠèªèº«ã®ããŒã¿ãæŽæ°ãã
ãšããViewModelã®ã¿ã£ã€ã®è²¬åã確èªã§ããŸããã
éèŠãªã®ã¯ãModelã®ã¡ãœããåŒã³åºããvoidã§ããããšãšãModelããã®å€æŽéç¥ã¯ã€ãã³ããéããŠè¡ãããšããéšåã§ãã
ããã«ãã£ãŠãã¢ãã«ã®ã¡ãœããåŒã³åºããšãããæŽæ°ç³»ãã®çªå£ãã¢ãã«ã®ç¶æ èªã¿åºããšãããåç §ç³»ãã®çªå£ãåé¢ãããŸãããã®åé¢ãè¡ãããšã§ãPDSã®æèã«ããããPresentationããšãDomainããççµåã«ä¿ã€ããšã«æåããŠããã®ããMVVMã¢ãŒããã¯ãã£ã§ããããšèããŠãã ããã
DDD-like Layered Architectureã«ããã¢ãã«å±€ã®åå²
ããŠãMVVMãã¿ãŒã³ãå©çšããããšã«ãã£ãŠã(PDSãšããæèã«ããã)ãã¬ãŒã³ããŒã·ã§ã³å±€ãšãã¡ã€ã³å±€ã®åé¢ã«æåããŸãããããããã¯ãPDSã®æèã«ããããã¡ã€ã³å±€ãããã«è©³ããèŠãŠãããŸããPDSã®æèã«ãããããã¡ã€ã³å±€ãã¯ãMVVMã®æèã«ãããŠã¯ã¢ãã«å±€ã«çžåœããŸãããDDD-like Architectureã«ãããã¡ã€ã³å±€ããšããèšèãåºãŠããŸããæ··ä¹±ã®ããšãªã®ã§ãããããå ã¯(PDS)ã«ãããããã¡ã€ã³å±€ãã®ããšããã¢ãã«å±€ããšåŒç§°ããŸãã
ããŠãDDD-like Layered Architectureã§ã¯ãã¢ãã«å±€ããApplicationããDomainããInfrastructureãã®å±€ã«åé¢ããŸããããããã¯ãããããã®åœ¹å²ãèŠãŠãããŸããããåæã¯ããã¡ã€ã³å±€ã«ãããŸãã®ã§ããŸãã¯ãã¡ã€ã³å±€ããèŠãŠãããŸãã
ãã¡ã€ã³å±€
ãã¡ã€ã³ã¬ã€ã€ãŒã¯ãåé¡é åã®ããŠããã¿ã¹èšèªããè¡šçŸããããã«ã¢ããªã³ã°ããŸããããŠããã¿ã¹èšèªãïŒãŸãæ°ããæŠå¿µãåºãŠããŸãããããŠããã¿ã¹èšèªãã¯DDDã®æ žãšãªããããªæŠå¿µã®äžã€ã§ãããDDDã«ã€ããŠã¯ä»åæ·±å ¥ãããŸããã®ã§ãç°¡åãªèª¬æã§æžãŸããŸãããŠããã¿ã¹èšèªãšããã®ã¯ãé¢ããã²ãšãã¡ã¿ããªãåãããã«æã€ããã«èª¿æŽããããã€ã³ãã¢ãã«ãèšèªåãããã®ã ãšæã£ãŠãã ããã
ã§ã¯ãä»åã®ã¢ããªã±ãŒã·ã§ã³ïŒè§Šã£ãŠãªãã²ãšã¯è§Šã£ãŠã¿ãŠãã ããïŒã®æŠå¿µãæŽçããŠã¿ãŸãããã
- ãŸãããã·ãŒã±ã³ãµãŒããšããã¬ã€ã€ãŒããååšããŸãã
- ã·ãŒã±ã³ãµãŒã¯ããŠãŒã¶ãå
¥åãããã©ã ãã¿ãŒã³ãä¿æãã圹å²ãæã¡ãŸãã
- ã·ãŒã±ã³ãµãŒã¯ã4ã€ã®ããã¿ãŒã³ããæã€ããšãã§ããŸãã
- ãŠãŒã¶ãŒã¯ãã·ãŒã±ã³ãµãŒãã1ã€ã®ããã¿ãŒã³ããéžæããŸãã
- ããããã®ãã¿ãŒã³ã¯ãBDïŒãã¹ãã©ã ïŒãSDïŒã¹ãã¢ãã©ã ïŒãHHïŒãã€ãããïŒãRSïŒã©ã€ãã·ã³ãã«ïŒãšãã4ã€ã®ããã©ãã¯ããæã¡ãŸãã
- ãŠãŒã¶ãŒã¯ãã·ãŒã±ã³ãµãŒãã1ã€ã®ããã©ãã¯ããéžæããŸãã
- åãã©ãã¯ã¯ããã¹ã³ã¢ãïŒæ¥æ¬èªã§èšããšæ¥œèã§ãïŒãæã¡ãŸãã
- ã¹ã³ã¢ã¯ã16åã®ãããŒãããããªããŸããããã16åé³ç¬Š/16åäŒç¬Šã«çžåœããŸãã
- ããŒãã¯ãªã³ãšãªãã®ç¶æ ãæã¡ãŸãããªã³ã®ããŒãã¯é³ç¬Šããªãã®ããŒãã¯äŒç¬Šã«çžåœããŸãã
- ãŠãŒã¶ãŒã¯ãéžæããããã¿ãŒã³ã®éžæããããã©ãã¯ã®ããŒãã«å¯ŸããŠããªã³ãšãªããšãã°ã«ããããšãã§ããŸãã
- ãã¿ãŒã³ã®åæç¶æ ã¯ãã1æç®3æç®ã®é ã«BDãã2æç®4æç®ã®é ã«SDãã8åé³ç¬Šå»ã¿ã§HHããšããŸã
- ãã¬ã€ã€ãŒã¯ãã·ãŒã±ã³ãµãŒã«ä¿åããããã©ã ãã¿ãŒã³ãæŒå¥ãã圹å²ãæã¡ãŸãã
- ãã¬ã€ã€ãŒã¯ãåçäžã§ãããåæ¢äžã§ããããšããç¶æ ãæã¡ãŸã
- ãŠãŒã¶ãŒã¯ããã¬ã€ã€ãŒã®åçç¶æ ããã°ã«ããããšãã§ããŸã
- ãã¬ã€ã€ãŒã¯ãBPMãæã¡ãŸãã
- ãŠãŒã¶ãŒã¯ããã¬ã€ã€ãŒã®BPMãå€æŽããããšãã§ããŸãã
- ãã¬ã€ã€ãŒã¯ãçŸåšåçäžã®äœçœ®ãšããæ å ±ãæã¡ãŸã
- ãã¬ã€ã€ãŒãåçäžã®ãšããBPMã«å¿ããã¿ã€ãã³ã°ã§ãçŸåšåçäžã®äœçœ®ã次ã®äœçœ®ã«ç§»åããŸããåæã«ãã·ãŒã±ã³ãµãŒã®ãã®äœçœ®ã«ä¿åããã
- ãã¬ã€ã€ãŒã¯ããã©ãã¯ã«å¿ãããBDããSDããHHããRSãã®é³ãåºåã§ããŸãã
ãã®ãããã§ããããã
ä»åã¯ã²ãšãã§äœã£ãã¢ããªã±ãŒã·ã§ã³ãªã®ã§ããšãã«ã ãããšãã®æŠå¿µãããåãããå¿ èŠããããŸããããDDDã§ã¯ãæ¬æ¥ã¯ãã®æŠå¿µãé¢ä¿è å šå¡ã§ããããããŠãå šå¡ããåãããšã°ãã§åãããšãç®æšãšããŸãïŒãšã¯ãããããã¯ãªããªãã§ããããšã§ã¯ãªãâŠâŠïŒã
ããŠãããããŠæŠå¿µãæŽçãããããããããããã®ãŸãŸãdomainå±€ã«ã¢ããªã³ã°ããŠãããŸããä»åã®ã¢ããªã±ãŒã·ã§ã³ãªãã°ãdomainå±€ã¯src/js/domain/
以äžã«æžãããŠããŸããäŸãšããŠãŸãã¯ã·ãŒã±ã³ãµãŒã®ã³ãŒããã¿ãŠã¿ãŸãããã
class {
get selectedPattern(){
return this.patterns[this.selectedPatternId];
}
constructor(){
this.patternIds = ["1", "2", "3", "4"];
this.patterns = {};
for (const id of this.patternIds) {
this.patterns[id] = new Pattern();
}
this.selectedPatternId = this.patternIds[0];
}
selectPattern(id) {
this.selectedPatternId = id;
console.debug("pattern selected: " + this.selectedPatternId);
}
- 4ã€ã®ãã¿ãŒã³ãæã¡ããããéžæããããšãã§ãã
ãšããæŠå¿µãããã®ãŸãŸæçŽã«ã³ãŒãã«èœãšã蟌ãŸããŠããŠãããããããã§ããïŒèªç»èªè³ïŒã
ã§ã¯ãä»åºŠã¯ãã¿ãŒã³ã®ã³ãŒããšã¹ã³ã¢ã®ã³ãŒããèŠãŸãã
// Pattern
class {
get selectedScore(){
return this.scores[this.selectedTrack];
}
constructor(){
this.tracks = ["BD", "SD", "HH","RS"];
const initialNotes = {
"BD": [
true, false, false, false, false, false, false, false,
true, false, false, false, false, false, false, false
],
"SD": [
false, false, false, false, true, false, false, false,
false, false, false, false, true, false, false, false
],
"HH": [
true, false, true, false, true, false, true, false,
true, false, true, false, true, false, true, false
],
"RS": [
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false
],
};
this.scores = {};
for (const track of this.tracks) {
this.scores[track] = new Score(initialNotes[track]);
}
this.selectedTrack = this.tracks[0];
}
selectTrack(track){
this.selectedTrack = track;
console.debug("track selected: " + track);
}
}
// Score
class {
constructor(initialNotes){
this.notes = initialNotes;
}
toggleNote(index) {
this.notes[index] = ! this.notes[index];
}
}
ãããããã¿ãŒã³ã®åæç¶æ ãæçŽã«ããããŠãããã4ã€ã®ãã©ãã¯ããã€ããšãããããã®ãã©ãã¯ãã¹ã³ã¢ãæã€ããšãã¹ã³ã¢ã¯16ã®ããŒããæã€ããšãããŒãã¯ãã°ã«å¯èœãªããšãæçŽã«ã³ãŒãã«èœãšã蟌ãŸããŠããŸãïŒãã®ãããã¯ããã£ãšãŸããã«ããã°ãNoteãå€ãªããžã§ã¯ããšããŠã¢ããªã³ã°ãããªã©ãããã«ãããã«ã¢ããªã³ã°å¯èœã ãšæããŸãããä»åã¯ãšããããããã§ãä»ã®ãšããããã§ååã«ããããããã§ããããããã«ä»æ§ãè€éåããŠããããã£ãšãŸããã«ãããŸãããïŒã
ãã®ããã«ãæŽçããæŠå¿µããŠããã¿ã¹èšèªããæçŽã«ã³ãŒãã«ã¢ããªã³ã°ãããã®ãããã¡ã€ã³ã¢ãã«ããšåŒã³ãŸãããã¡ã€ã³å±€ãããããŠãã¿ããªã䜿ã£ãŠãèšèã®éãã«ãã¢ããªã³ã°ããããšã§ãã¹ããŒã¯ã¹ãã«ãå šå¡ãå®éã«æžãããã³ãŒããããšã«è°è«ãããã§ããããããŒã ã¡ã³ããŒãã³ãŒãã®ç解ããããããªããŸãïŒãšããã®ããDDDã®ç®æãçæ³ã§ããããããçæ³ã¯çæ³ã§ããçŸå®ã¯çããªãããã©ãããã¯ç®æãã«å€ããçæ³ã ãšèšããã§ãããïŒã
次ã«ãããã¬ã€ã€ãŒãã®éšåã®domainããŸãã¯èŠãŠã¿ãŸãããããã¬ã€ã€ãŒã¯å°ãè€éãªã®ã§ãå°ããã€ã¿ãŠãããŸãããŸãã¯ã³ã³ã¹ãã©ã¯ã¿ããèŠãŠãããŸãããã
constructor(ticker, sequencer, sounds){
this._sequencer = sequencer;
this._sounds = sounds;
this._ticker = ticker;
this.isSoundsInited = false;
this.playingState = false;
this.playingNoteIndex = null;
this.bpm = 120;
}
ãã¬ã€ã€ãŒãã·ãŒã±ã³ãµãŒãä¿æããã®ã¯ããã§ããããã·ãŒã±ã³ãµãŒå ã«ä¿åããããã¿ãŒã³ãç¥ãããã«ã¯ãã·ãŒã±ã³ãµãŒãä¿æããå¿ èŠãããã®ã¯çŽåŸããããŸããã
soundsãšããã®ã¯ã鳎ããé³ãè¡šãããªããžã§ã¯ãã§ããBDã ã£ãããããïŒãã£ãŠé³ã ããSDã ã£ãããã¿ã³ïŒããšããé³ã§ããã
ãŸããtickerãšããã®ã¯ãBPMã«å¿ããŠã€ãã³ããçºè¡ããŠãããã¿ã€ããŒã§ããtickerã«bpmãã»ããããŠstart
ãããšãBPMãæ©ããã°ããã«å¿ããŠæ©ãã¿ã€ãã³ã°ã§ã€ãã³ããå®æçã«çºè¡ããŠãããŸããtickerã«ã»ããããBPMãé
ãããã°ãããã«å¿ããŠé
ãã¿ã€ãã³ã°ã§ã€ãã³ããå®æçã«çºè¡ããŠãããŸãã
isSoundInited
ã«ã€ããŠã¯åŸã»ã©èŠãããšã«ããã®ã§ãä»ã¯æšãŠçœ®ããŠãã ãããplayingState
ãplayingNoteIndex
ãbpm
ã¯ããã¡ã€ã³ã¢ãã«ãã¢ããªã³ã°ããŠãããšãã«åºãŠããæŠå¿µãªã®ã§ãããã¯ãŸãããã§ããããç¶ããŠå
¬éã¡ãœããé¡ãèŠãŠãããŸãã
initSounds() {
//snip
}
togglePlayingState(){
if ( ! this.isSoundsInited ) {
return;
}
if (this.playingState) {
this._stop();
} else {
this._play();
}
}
setBpm(bpm){
this.bpm = bpm;
this._ticker.bpm = bpm;
}
initSound
ãªã©ã®ãSoundInitedãŸããã«ã€ããŠã¯åŸè¿°ããã®ã§ãä»ã¯ç¡èŠããŠãããŠãã ããã
togglePlayingState
ãšsetBpm
ã¯ããŸãã«ãŠããã¿ã¹èšèªãæŽãããšãã«æŽçããæŠå¿µããã®ãŸãŸã¢ããªã³ã°ãããã®ã«ãªã£ãŠããŸãããç¹çãã¹ãã¯this._ticker.bpm = bpm
ã®ãšããã§ãããããBPMãèšå®ããããšãã«ã¯ãã¿ã€ããŒã®BPMãèšå®ããŠããå¿
èŠãããã®ã§ããã§èšå®ããŠããŸãã
ã§ã¯ãtogglePlayingState
ã®äžã§äœ¿ãããŠãã_play()
ãš_stop()
ã«ã€ããŠèŠãŠãããŸãããã
_play(){
this.playingState = true;
this._ticker.start(this.bpm, () => this._playNextSound());
}
_stop(){
this.playingState = false;
this._ticker.stop();
}
ãŸããplayingState
ãå€åãããŠãããšããã¯ããã§ãããã
play
ãããšãã«ã¯ãã¿ã€ããŒãèµ·åããªããšãããªãã§ãããçŸåšãšbpmãšãã¿ã€ããŒãã€ãã³ãçºè¡ãããšãã«å©ããããªã¹ããŒãç»é²ããŸãã
stop
ãããšãã«ã¯ãã¿ã€ããŒãã¹ãããããŠããŸãããã®ã¿ã€ããŒã¯ãstopããããšã«å¿
ãäžåºŠã ãã€ãã³ããçºè¡ãããŠããåæ¢ããããã«ãªã£ãŠããŸãã
ããŠãã§ã¯ããªã¹ããŒã®äžèº«ãèŠãŠã¿ãŸãããã
_playNextSound(){
if (this.playingState == false) {
this.playingNoteIndex = null;
return;
}
if (this.playingNoteIndex == null || this.playingNoteIndex == 15) {
this.playingNoteIndex = 0;
} else {
this.playingNoteIndex += 1;
}
this._playSound()
}
_playSound(){
const i = this.playingNoteIndex;
for (const track of this._sequencer.selectedPattern.tracks) {
if (this._sequencer.selectedPattern.scores[track].notes[i]) {
this._sounds[track].play();
}
}
}
ãŸããããããã§ã«ãã¬ã€ã€ãŒãåæ¢æžã¿ã ã£ãå Žåã¯ããåçäœçœ®ããåæç¶æ ã«æ»ããŠããŸãã
ããã«ãåçäœçœ®ãåæç¶æ
ããæåŸãŸã§è¡ã£ãŠããå Žåã¯ãåçäœçœ®ã0ã«ãã©ããŠããŸãããããã§ãªãå Žåã¯åçäœçœ®ã1é²ããããšã_playSound
ãå©ããŠããŸãã
_playSound
ã§ã¯ãã·ãŒã±ã³ãµãŒã®ãéžæããããã¿ãŒã³ãã®åãã©ãã¯ã«ã€ããŠãããåçäœçœ®ã«ããããŒãããªã³ã§ããã°ãã®ãã©ãã¯ã«åœãããµãŠã³ããåçããŠããŸãã
ã€ã³ãã©ã¹ãã©ã¯ãã£å±€
ãšããã§ããã®ããµãŠã³ãããšããã®ã¯ãã¡ãã£ãšåä»ããã ãšæããŸãããïŒãŸãããã©ãŠã¶äžã§é³ãã ãããã«ã¯ããWebAudio APIããšãããã©ãŠã¶åºæã®æè¡ãå©çšããªããã°ãªããŸãããããããããã©ãŠã¶åºæã®æè¡ããšããã®ã¯ãããŠããã¿ã¹èšèªãã«å«ãŸããã§ããããïŒãŠããã¿ã¹èšèªã¯ãã¹ããŒã¯ã¹ãã«ãå šå¡ã§äœãäžãããã®ã§ãããšããããšã¯ããŠããã¿ã¹èšèªã«è§Šãã®ã¯ããã°ã©ãã ãã§ã¯ãããŸããããããŸã§ããŠããã¿ã¹èšèªäžã§ã¯ããµãŠã³ããåçããããšãããããªè¡šçŸã«ãªãããWebAudioãå©çšããŠããšããã®ã¯ããããããã°ã©ãåãã®ããŒã«ã«ãªèšèªãã ãšèšã£ãŠããã§ãããã
ãããããæè¡çãªè©³çŽ°ãã«ã€ããŠã¯ããã€ã³ãã©ã¹ãã©ã¯ãã£å±€ãã«æžããŠãããŸãããã
let context = null;
export default class {
constructor(fileURL){
this._fileURL = fileURL;
this._buffer = null;
try {
const AudioContext = window.AudioContext || window.webkitAudioContext;
if (context == null) {
context = new AudioContext();
}
console.debug("audio context created");
} catch (e) {
throw new Error("can't create AudioContext");
}
}
setup(){
const request = new XMLHttpRequest();
request.open('GET', this._fileURL , true);
request.responseType = 'arraybuffer';
return new Promise((resolve, reject) => {
request.onload = () => {
context.decodeAudioData(request.response, (buffer) => {
this._buffer = buffer;
resolve();
}, (e) => {
reject(e);
});
};
request.send();
});
}
play(){
console.debug("playing sound");
const source = context.createBufferSource();
source.buffer = this._buffer;
source.connect(context.destination);
source.start(0);
}
}
ãã¡ã€ã³å±€ã®ã³ãŒãã¯ãæŠå¿µãæçŽã«æžãäžãããŠãããããéããã°ã©ãã§ããªããšãªãèªãããããªé°å²æ°ã ã£ããšæããŸããããã«æ¯ã¹ããšãã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã¯ããã®æè¡ã«ã€ããŠãã¡ããšç解ããŠãªããšããããããªããããªã³ãŒãã«ãªã£ãŠããŸããããããã£ããæè¡çãªè©³çŽ°ã¯ãã¡ã€ã³å±€ã«æã¡èŸŒãŸããã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã«æŒã蟌ããããšã§ããã¡ã€ã³å±€ããã¥ã¢ã«ãç解ããããããããšããã¢ããªã±ãŒã·ã§ã³ã®æ¬è³ªçãªéšåããããã«æžãã³ãã§ããããšããç¥èŠãããã«ã¯ãããšèšã£ãŠããã§ãããã
ããŠãå®ã¯ãä»åã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯BPMã«å¿ããŠã€ãã³ããçºè¡ããŠãããåã§ãããšããã®tickerã«ã€ããŠãBpmTickerãšããååã§ã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã§å®è£ ããŠããŸãããšããã®ããã¿ã€ããŒã€ãã³ããçºè¡ããããã«ã¯ããã©ãããã©ãŒã åºæã®APIã§ããsetTimeoutãsetIntervalãªã©ãå¿ èŠã«ãªãã§ããããããã¯ãã¡ã€ã³ã®ç¥èã§ã¯ãªããã€ã³ãã©ã¹ãã©ã¯ãã£ã®ç¥èã§ããã¯ãã§ãããã®ãããBpmTickerã¯ã€ã³ãã©ã¹ãã©ã¯ãã£ã«é èœãããã¡ã€ã³å±€ããã¯ãããå©çšããã ãã«ããŠãããŸãã
ãŸããä»åã¯ååšããŸããããå€éšAPIãå©ãã³ãŒãã ãšããRDBMSãå©ãå±€ã ãšãããããã£ããã®ããæè¡çãªè©³çŽ°ãã«å«ãŸããã®ã§ãã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã«æžãããããšã«ãªãã§ãããã
ããŠãããã§ããã¡ã€ã³å±€ã§æŸçœ®ããŠããiniteSound
ç³»ã®ã¡ãœãããããããã£ã«ã€ããŠãå床èŠãŠã¿ãŸãããã
//Player.js
constructor(ticker, sequencer, sounds){
// snip
this.isSoundsInited = false;
// snip
}
initSounds() {
const promises = [];
for (const key in this._sounds) {
promises.push(this._sounds[key].setup());
}
return Promise.all(promises).then(()=>{
this.isSoundsInited = true;
});
}
togglePlayingState(){
if ( ! this.isSoundsInited ) {
return;
}
// snip
}
Soundãšããã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã®æè¡çèŠè«ã§ãwavãã¡ã€ã«ãéåæã§èªã¿èŸŒãå¿ èŠãåºãŠããŠããŸããwavãã¡ã€ã«ãèªã¿èŸŒã¿ããåã«ããããã¬ã€ã€ãŒãåçããŠããŸã£ãããèªã¿èŸŒãŸããŠããªãé³ã¯åºãªããããããã¯ã¢ããªã±ãŒã·ã§ã³ãã¯ã©ãã·ã¥ããŠããŸãã§ãããããã®ããããã¬ã€ã€ãŒã¯ãããé³ãæºåã§ãããããé³ããŸã æºåã§ããŠãªããããšããç¶æ ãæã€å¿ èŠãåºãŠããŠããŸããŸããããã®ããã«ãæè¡çå¶çŽãããã¢ããªã±ãŒã·ã§ã³ã®ä»æ§ã圱é¿ãåããããšããããŸããä»åãªãã°ããããåå ã§ãŠããã¿ã¹èšèªã®äžã«
- æè¡çå¶çŽããããã¬ã€ã€ãŒã¯ãé³ãæºåã§ããããã§ããŠããªããã®ç¶æ ãæã€
- ãŸã é³ãæºåã§ããŠããªããšãã¯åçç¶æ ãå€æŽã§ããªã
ãšããæ°ããå¶çŽãçãŸãããšèããããã§ãããããªã®ã§ããã®ãããªæè¡çãªå¶çŽãdomainå±€ããŠããã¿ã¹èšèªã«æŒãåºããŠããŸããŸããããã¯ãããçšåºŠã¯ãããããªãããšã§ããããšèããã¹ãã§ããããããèããäžã§ããªãã¹ãæè¡ç詳现ã¯ã€ã³ãã©ã¹ãã©ã¯ãã£ã«é èœããã»ããšãã«æè¡çã«ã©ããããããªããŠä»æ§ã«åœ±é¿ãäžãããšãã«ã¯ããæè¡çãªå¶çŽã§ãã®ãããªä»æ§ã«ãªã£ãŠããããšãããŠããã¿ã¹èšèªããä»æ¹ãªãã«ãå ããããšããããšã¯ããã£ãŠãããã®ã§ã¯ãªããããšããã®ããããã®æèŠã§ãã
ã¢ããªã±ãŒã·ã§ã³å±€
ã¢ããªã±ãŒã·ã§ã³å±€ã¯ããã¡ã€ã³å±€ãã€ã³ãã©ã¹ãã©ã¯ãã£å±€ãçµã¿åãããŠããŠãŒã¹ã±ãŒã¹ãå®çŸããå±€ã§ããã€ã¡ãŒãžãšããŠãªãŒã±ã¹ãã©ã«äŸãããšããã¡ã€ã³å±€ãã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã¯åã ã®ãã¬ã€ã€ãŒãã¢ããªã±ãŒã·ã§ã³å±€ã¯ãã®ãã¬ã€ã€ãŒãã¡ã«æ瀺ãåºãææ®è ããšãã£ããšããã§ãããããååã«åçŽãªã¢ããªã±ãŒã·ã§ã³ãªãã°ãViewModelãçŽæ¥ãã¡ã€ã³ã¢ãã«ãå©ããŠãããã§ããããããã¡ã€ã³ãè€éã«ãªããäºããã³ãã¥ãã±ãŒã·ã§ã³ããªããã°ãããªãå Žåããããã®ãŠãŒã¹ã±ãŒã¹ãå®çŸããããã«ã¯ãã®ãã¡ã€ã³ã¢ãã«ã«å¯ŸããŠããããæäœãããŠããã®ããšãã®ãã¡ã€ã³ã¢ãã«ã«å¯ŸããŠããããæäœãããªããã°ãªããªãããšãããããªèŠä»¶ãããå Žåãããã¬ãŒã³ããŒã·ã§ã³ãã®ã¬ã€ã€ãŒã«ããViewModelã«ãã®æäœãæžããŠããŸã£ããããã¬ãŒã³ããŒã·ã§ã³ã«ããžãã¯ãæŒãåºããŠããŸããŸãã
ãŸããéåæåŠçãšããã®ã¯æ¬è³ªçã«å®è¡é åºãäžå®ãšããç¹åŸŽãæã¡ãŸããæè¡çå¶çŽã§éåæåŠçãè¡ãããã°ãããªãããã¢ããªã±ãŒã·ã§ã³ã®ä»æ§ãšããŠã¯å®è¡é åºã倧ããªæå³ãæã€ããšããå Žåããã¡ããããã§ãããããè€æ°ã®éåæåŠçãåæã«èµ°ã£ãŠãããšãã«ãã¬ãŒã¹ã³ã³ãã£ã·ã§ã³ãèµ·ãããªãããã«éåæåŠçã®çµæãé©çšããé åºãä¿èšŒããªããã°ãªããªãããšãããããªããšãããã§ãããããã®ãšããè€æ°ã®éåæåŠçã®çµæããããŒãžã¡ã³ãããŠèª¿æŽãã圹å²ãã©ãããæ ãå¿ èŠããããŸãã
ãŸãããã¬ãŒã³ããŒã·ã§ã³ã®ã³ã³ããŒãã³ãã®åå²ã®ãããããšããã¡ã€ã³ã¢ãã«ã®åå²ã®ããæ¹ãç°ãªãå Žåãšããã®ããããŸããä»åã®ã¢ããªã±ãŒã·ã§ã³ãªãã°ãããã¿ãŒã³ããšããæŠå¿µã¯ããã¬ãŒã³ããŒã·ã§ã³ã¬ã€ã€ãŒã§ã¯ã³ã³ãããŒã«ããã«ã«ãããŠãããŸããããã¡ã€ã³å±€ã§ã¯ããã¬ã€ã€ãŒãã§ã¯ãªããã·ãŒã±ã³ãµãŒããä¿æããŠããŸããã
ãããã£ãè€éãªã¢ããªã±ãŒã·ã§ã³ã®å Žåããè€æ°ã®ãã¡ã€ã³ã¢ãã«å士ã®ãšããŸãšããããŠãããŠããã¬ãŒã³ããŒã·ã§ã³ã¬ã€ã€ãŒã®çªå£ã«ãªã£ãŠããã圹å²ãããããšãåViewModelã¯ãã¡ã€ã³ã®è©³çŽ°ãç¥ãããšãªããçªå£ã«å¯ŸããŠããããã£ãšããŠããšäŸé Œããã ãã§æžã¿ãŸãã
ãã®åœ¹å²ãæ ãã®ããã¢ããªã±ãŒã·ã§ã³å±€ã§ãã
ä»åã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãsrc/js/usecase
ãã¢ããªã±ãŒã·ã§ã³ã¬ã€ã€ãŒãæ
ã£ãŠããŸããã»ããšãã«ãçªå£ãã«ãªã£ãŠããŠãã€ãã³ããåããŸãšããããã¡ã€ã³ã¢ãã«ãdispatchããŠããã ããªã®ã§ãäžæ°ã«èŠãŠããŸããŸãããã
// SequencerUsecase
class {
constructor(ticker, sounds){
this.sequencer = new Sequencer();
this.player = new Player(ticker, this.sequencer, sounds);
//Events
this.initializationFailed = new Notificator();
this.isSoundsInitedChanged = new Notificator();
this.selectedPatternChanged = new Notificator();
this.selectedTrackChanged = new Notificator();
this.notesChanged = new Notificator();
this.playingStateChanged = new Notificator();
this.playingNoteIndexChanged = new Notificator();
this.bpmChanged = new Notificator();
// subscribe _ticker events
ticker.ticked.subscribe(() => {
console.debug("ticked");
this.playingNoteIndexChanged.notify();
});
}
initSound(){
this.player.initSounds().then(()=>{
this.isSoundsInitedChanged.notify();
}).catch((e) => {
console.error(e);
this.initializationFailed.notify();
});
}
selectPattern(id) {
this.sequencer.selectPattern(id);
this.selectedPatternChanged.notify();
this.selectedTrackChanged.notify();
this.notesChanged.notify();
}
selectTrack(track) {
this.sequencer.selectedPattern.selectTrack(track);
this.selectedTrackChanged.notify();
this.notesChanged.notify();
}
toggleNote(index) {
this.sequencer.selectedPattern.selectedScore.toggleNote(index);
this.notesChanged.notify();
}
togglePlayingState() {
this.player.togglePlayingState();
this.playingStateChanged.notify();
this.playingNoteIndexChanged.notify();
}
setBpm(bpm) {
this.player.setBpm(bpm);
this.bpmChanged.notify();
}
}
ç¹çãã¹ããã€ã³ãã¯ãinitSound
ãããã§ãããããinitSoundã¯ãäžã§éåæåŠçãè¡ã£ãŠããŸããããã®çµæãã€ãã³ããéããŠæžãæ»ããŠããŸããã»ãã®ã¡ãœããã¯ãåæåŠçã§ãããåããã€ãã³ããéããŠçµæãæžãæ»ããŠããŸãããusecaseå
ã«éåæåŠçãã©ãããé èœããããšã§ããã¬ãŒã³ããŒã·ã§ã³ã¬ã€ã€ãŒããã¯ãã®æäœãåæçã«è¡ãããã®ãéåæåŠçã§è¡ãããã®ããæèããªããŠæžãããã«ãªã£ãŠãããšããããã€ã³ãã§ãã
ãŸããä»åã¯ããã®èŠæš¡ã ã£ããusecaseãã€ãã³ãå šéšçºè¡ãã¡ãã£ãã»ããèŠéããããããªãããšæã£ãŠusecaseãã€ãã³ããçºè¡ããŠããŸããããã£ãšè€éãªã¢ããªã±ãŒã·ã§ã³ã«ãªã£ãŠããããããããããåDomainModelãèªèº«ãé¢å¿ãæã€ã€ãã³ãã管çããŠãããã»ããèŠéãããããªããããããŸãããããã®ãããã®èšèšã¯ïŒãšããããã©ã®èšèšãïŒã¢ããªã±ãŒã·ã§ã³ã®ç¹åŸŽã«å¿ããŠé©åãªããæ¹ãå€ãã£ãŠããã§ãããã
Clean Architectureã«ããäŸåæ§ã®æŽç
Clean Architectureãšã¯ãªã«ã§ãã£ãŠãªã«ã§ãªãã®ã
ããŠãæè¿ã¯ãClean Architectureããšããèšèãããèãããã«ãªããŸããããã§ã¯ãClean Architectureã¯ãMVVMãšããããã¯DDD-like Layered Architectureãšã©ã®ãããªé¢ä¿ãããã®ã§ããããããããç¥ãããã«ã¯ããŸãã¯Clean Architectureãšã¯ããªã«ã§ãã£ãŠãããªã«ã§ãªãã®ããã«ã€ããŠèŠãŠãããŸãããã
åå žã¯ããã§ããããããã¡ããšèªããšã
- Clean Architecture ã¯ãLayered Architecture ã ãã®æŽŸçã§ããHexagonal Architectureãªã©ãæ§ã ãªäŒŒéã£ãã¢ãŒããã¯ãã£ãã¿ãŒã³ãç·åããããã®ã³ã³ã»ããã§ããã
- ãã€ã³ãã¯ããå±€å士ã®äŸåã®æ¹åæ§ãã§ãã
- å
·äœçã«ãã©ãããå±€ã«åå²ãã¹ãã§ããããããã©ããã責åãæã€ã¹ãã§ãã©ããããã¶ã€ã³ãã¿ãŒã³ãå©çšããã¹ããªã®ãããšããããšã決ããã¢ãŒããã¯ãã£ãã¿ãŒã³ã§ã¯ãªã
- ããšã®èšäºã§ãããã¹ã€ã«åã¯4ã€ãããªããŠããããã®ãšãããããªããŠãããã£ãŠèšã£ãŠãã
ãšããããšãèŠããŠããŸãã
éèŠãªãã€ã³ããªã®ã§éããŠåŒ·èª¿ããŸãããClean Architectureãšããã®ã¯ å±€å士ã®äŸåã®æ¹åæ§ã«é¢ããã³ã³ã»ãã ã§ãã£ãŠãå ·äœçã«ã¢ããªã±ãŒã·ã§ã³ãã©ã®ããã«åå²ãã¹ããã決ãããã®ã§ã¯ãããŸããã
ãããŠããã®ã³ã³ã»ããã¯ããæè¡çãªè©³çŽ°ããã©ãããã©ãŒã ããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã«è¿ã"å€åŽ"ã®ã¬ã€ã€ãŒã¯ãã¢ããªã±ãŒã·ã§ã³ã®æåããã¡ã€ã³èšèšãå®çŸãã"å åŽ"ã®ã¬ã€ã€ãŒã«äŸåããŠããããéã®æ¹åã®äŸåã¯ããŠã¯ãããªãããšããã³ã³ã»ããã§ãã
ãããŠããã®ã³ã³ã»ãããå®ãããšã«ãã£ãŠãã¢ããªã±ãŒã·ã§ã³ã®ãã¹ã¿ããªãã£ãå€æŽå®¹ææ§ãæ ä¿ã§ãããããšèšã£ãŠããããã§ããã
ãããç解ããäžã§ããã®ãªããžããªã®ã¢ããªã±ãŒã·ã§ã³ã®åå±€ãã©ã®ãããªäŸåé¢ä¿ã«ãªã£ãŠããã®ã確ãããŠã¿ãŸãããã
ãã¬ãŒã³ããŒã·ã§ã³å±€ / ã¢ããªã±ãŒã·ã§ã³å±€ãã®å¢çã«ã€ããŠ
ããŠãããããã¡ã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãMVVMãã¿ãŒã³ïŒãšãããObserverãã¿ãŒã³ïŒãå©çšããããšã«ãã£ãŠ
- ãã¬ãŒã³ããŒã·ã§ã³å±€ã¯ã¢ããªã±ãŒã·ã§ã³å±€ãä¿æãããã®ã¡ãœãããå©ã
- ã¢ããªã±ãŒã·ã§ã³å±€ã¯ã€ãã³ããçºè¡ããã ãã§ããã¬ãŒã³ããŒã·ã§ã³å±€ãä¿æããªã
ãšããç¶æ ã«ãªã£ãŠããŸããããã¯ãäŸåæ§ã«æ³šç®ãããšã
- ãã¬ãŒã³ããŒã·ã§ã³å±€ã¯ã¢ããªã±ãŒã·ã§ã³å±€ã«äŸåããŠãã
- ã¢ããªã±ãŒã·ã§ã³å±€ã¯ãã¬ãŒã³ããŒã·ã§ã³å±€ã«äŸåããŠããªã
ãšãã圢ã«ãªã£ãŠããŸãããã¬ãŒã³ããŒã·ã§ã³å±€ãšã¢ããªã±ãŒã·ã§ã³å±€ã¯ããã¬ãŒã³ããŒã·ã§ã³å±€ã®ã»ããå€åŽãªã®ã§ããã¡ããšãå€åŽããå åŽã«äŸåããããå åŽããã¯å€åŽã«äŸåããªãããšãªã£ãŠããŸããã
ããã«ãã£ãŠããå åŽãã§ããã¢ããªã±ãŒã·ã§ã³å±€ããã¹ãããéã«ãå€åŽãã®ãã¬ãŒã³ããŒã·ã§ã³å±€ã®ããšãèããã«ãã¹ãã§ããããã«ãªã£ãŠããŸãã
ã¢ããªã±ãŒã·ã§ã³å±€ / ãã¡ã€ã³å±€ã®å¢çã«ã€ããŠ
ã¢ããªã±ãŒã·ã§ã³å±€ã¯ãããã¬ãŒã³ããŒã·ã§ã³å±€ã«å¯Ÿããçªå£ãã§ãããããã¯ããã¡ã€ã³å±€ãããå€åŽã«ãã£ãŠããã¬ãŒã³ããŒã·ã§ã³å±€ããå åŽã«ãããå±€ã ãšèšããã§ãããã
ã§ã¯ãã¢ããªã±ãŒã·ã§ã³å±€ãšãã¡ã€ã³å±€ã®å¢çã«ã€ããŠèŠãŠã¿ãŸããããã¢ããªã±ãŒã·ã§ã³å±€ããã¡ã€ã³å±€ãå©çšããã®ã§ãããã¯æ®éã«ããã°ã¢ããªã±ãŒã·ã§ã³å±€ããã¡ã€ã³å±€ã«äŸåãã圢ã«ãªããŸããããããå€åŽããå åŽãžã®äŸåã«ãªã£ãŠããŸããã
ãã¡ã€ã³å±€ / ã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã®å¢çã«ã€ããŠ
ããŠããã¡ã€ã³å±€ãšã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã§ããããŸããã©ã¡ããå€åŽãã«ãªã£ãŠããããèããŠã¿ãŸããããã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã¯æè¡ç詳现ããã©ãããã©ãŒã äŸåã®ã³ãŒããå«ãŸããããããã¡ã€ã³å±€ããããå€åŽãã§ããã
ã§ã¯ãä»åºŠã¯ã©ã¡ããã©ã¡ããå©çšããã®ããèããŠã¿ãŸãããããã¡ã€ã³å±€ã®ã³ãŒãã¯ãã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã§å®è£ ããããã®ãå©çšããããšã§ãã¡ã€ã³ã§å®çŸãããããšãå®çŸããã®ã§ããããšãªããšããã¡ã€ã³å±€ãã€ã³ãã©ã¹ãã©ã¯ãã£å±€ãå©çšããããšã«ãªããŸãã
ããèãããšãããã¯å°ã£ãããšã§ããïŒã ã£ãŠãããã¡ã€ã³å±€ã¯ã€ã³ãã©ã¹ãã©ã¯ãã£å±€ãå©çšãããã©ãäŸåããŠã¯ãããªãããšããããšã§ããäŸåããŠãªããã®ãã©ããã£ãŠå©çšããã®ã§ãããïŒ
ã§ãããããã«ãæè¡çãªè©³çŽ°ããã©ãããã©ãŒã äŸåã®æ©èœã«äŸåããŠããã³ãŒãã£ãŠãšãŠããã¹ããã«ããã§ããããã¢ããªã±ãŒã·ã§ã³ã®ã³ã¢ãæ ããã¡ã€ã³å±€ããã¹ããã«ããã®ã¯å°ããŸãããªããšãããŠãå©çšã¯ãããã©äŸåã¯ããªãããšããç¶æ³ãäœãåºãããšã¯ã§ããªãã®ã§ããããã
ããã§éèŠã«ãªãæŠå¿µãããäŸåæ§é転ã®æ³å(DIP)ããšãããã€ã§ãã
ãã¡ã€ã³å±€ã¯ãåŠçãå®çŸããããã«ã¯ãã€ã³ãã©ã¹ãã©ã¯ãã£å±€ãå©çšããå¿ èŠããããŸããããããæçŽã«ã€ã³ãã©ã¹ãã©ã¯ãã£å±€ãå©çšããŠããŸããšããã¡ã€ã³ãã€ã³ãã©ã¹ãã©ã¯ãã£ã«äŸåããããšã«ãªããŸããããã§ããã¡ã€ã³å±€ãã€ã³ãã©ã¹ãã©ã¯ãã£å±€ãå©çšãããšãã«ã¯ãããªããDIãçµç±ããŠå©çšããããšã§ãããã®äŸåãæã¡åããŸããããããããšã§ããã¡ã€ã³å±€ãšã€ã³ãã©ã¹ãã©ã¯ãã£å±€ãççµåã«ä¿ã€ããšãã§ããŸãã
DIãããããªãããšãã人ã¯ãã¡ãã£ãšè©±ããããšé·ããªãã®ã§ããããŸãæåå³åã§æçž®ã§ããã以äžã®èšäºãªã©ã§ãã¡ãœããã³ãŒã«ããŠã察象ãžã®äŸåãåŒã£ãºãããŠã"äŸåããŠãªã"å®è£ ã®ã¡ãœãããã³ãŒã«ããããšãã§ãããã£ãŠããšãç解ããŠãã ããã
èŠããã« DI ã£ãŠäœãªã®ãšãã話
ãŸãããã®ãšãããå®è£ ããèãããã®ã§ã¯ãªããããã¡ã€ã³å±€ã¯ã©ãããã€ã³ã¿ãŒãã§ã€ã¹ã§ã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã䜿ãããã®ããããèããã¹ãã§ããããããããšã§ãã¡ãã£ãšãããããèšãæ¹ã«ãªããŸãããæœè±¡ãå®çŸ©ããŠããã¯ãã¡ã€ã³å±€ããã€ã³ãã©ã¹ãã©ã¯ãã£å±€ãããã®æœè±¡ã«äŸåããŠããã®å®è£ ãè¡ãããšãã圢ã«ãªããæ¬åœã®æå³ã§ãã¡ã€ã³å±€ãã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã«äŸåããã«æžãããã«ãªããŸãã
ããã«èšããšãä»åã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãJavaScriptã«ã¯InterfaceãšããæŠå¿µããªãããããšãã«Interfaceãäœã£ãŠããŸããããJavaãªã©ã®Interfaceãããèšèªã§ã¯ããæè¡ç詳现ã«ã€ããŠã¯ç¥ãããã©ã俺ïŒãã¡ã€ã³å±€ïŒã¯ããããAPIã§ããããããšããããããããšããã®ãå®çŸ©ããInterfaceããã¡ã€ã³å±€ã«å®çŸ©ããŠããã°ããããããæäœãå¿ èŠããšãããã¡ã€ã³ã®ç¥èãå®è£ ãªãã®æœè±¡çãªãŸãŸãã¡ã€ã³å±€ã§è¡šçŸã§ããŸãã
ããšãã°ãããã¬ã€ã€ãŒã¯åçç¶æ ã®ãšãé³ã鳎ããããšããã®ã¯ãã¡ã€ã³ã®ç¥èã§ããäžæ¹ããé³ã鳎ããã«ã¯WebAudioãå©çšããããšããã®ã¯ã€ã³ãã©ã¹ãã©ã¯ãã£ã®ç¥èã§ãã
ããã§ããSoundãšããåã¯playãšããã¡ãœãããæã€ããšããããšã ãããã¡ã€ã³å±€ã«æžããŠããplayãå®çŸããããã«WebAudioãå©çšããŠå®è£ ããããšããå 容ã®å®è£ ãã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã«å®è£ ããŠããããšããã¡ã€ã³å±€ã§ååã«ãã¡ã€ã³ãè¡šçŸã§ãããªããã€æè¡ç詳现ãã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã«é èœã§ããããã§ããã
ããŠãä»åã¯JavaScriptãªãã§ãã€ã³ã¿ãŒãã§ã€ã¹ãçšæãããã¢ããªã±ãŒã·ã§ã³å±€ãšãã¡ã€ã³å±€ã®ã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ã«ã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã®ãªããžã§ã¯ããçŽæ¥ã¶ã£ããã§DIãå®çŸããŠããŸãã
// presentation/vue_components/Application.vue
const usecase = new SequencerUsecase(ticker, sounds);
// usecase/SequencerUsecase.js
class {
constructor(ticker, sounds){
this.sequencer = new Sequencer();
this.player = new Player(ticker, this.sequencer, sounds);
}
//snip
}
ããã¡ã¯ããªDIã³ã³ããããããããªèšèªã ã£ããããã§DIã³ã³ããã䜿ããªã©ã®æ¹æ³ãèããããŸããã
ããŠãããããŠããã¡ã€ã³å±€ãšã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã®äŸåé¢ä¿ãé転ããããšããªã«ãå¬ããã§ããããããªã«ãå¬ããããç¥ãããã«ããããããªããšãªã«ããŸããã®ãããšããããšãèããŠã¿ãŸããããããããã¡ã€ã³å±€ãã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã«äŸåããŠããŸã£ãŠãããããã£ãããã¡ã€ã³å±€ããæè¡ç詳现ãå¥ã®ã¬ã€ã€ãŒã«ãŸãšããã®ã«ããã®å±€ããã¹ããããšãã«æè¡ç詳现ã«æ¯ãåãããŠããŸããŸãã
ããšãã°ãå€éšAPIãå©ããããªã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã®ã¯ã©ã¹ã«äŸåããŠãã¯ã©ã¹ã¯ããã®ãŸãŸã§ã¯èªåãã¹ãã§ããŸããããããã¯ãWebAudioãæ±ãã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã®ã¯ã©ã¹ã«äŸåãããŠãã¯ã©ã¹ãèªåãã¹ããããã³ã«é³ã鳎ããŸãã£ãããããããŠããªããŸããã
ããããDIãªã©ãå©çšããŠãã¡ã€ã³å±€ããã€ã³ãã©ã¹ãã©ã¯ãã£å±€ãžã®äŸåãã²ã£ãºãããŠããã°ãã¢ããªã±ãŒã·ã§ã³ã®ã³ã¢ã§ãããã¡ã€ã³å±€ã¯ããã¬ãŒã³ããŒã·ã§ã³ã«ãããŠãŒã¹ã±ãŒã¹ã«ããã€ã³ãã©ã¹ãã©ã¯ãã£ã«ãã©ãã«ãäŸåããªãããã«ã§ããŸãããã®ããããã¡ã€ã³å±€ã¯ãã¡ã€ã³å±€ã®ã¿ã§ãã¹ããããããšãã§ããŸãã
åå±€ã®äŸåé¢ä¿ãæ¹ããŠæŽç
ããŠãDDD-like Layered Architectureã¯ããã©ã®ããã«å±€ãåããã¹ãããã«ã€ããŠèªããŸããããDIPãšMVVMãé§äœ¿ããããšã«ãã£ãŠãåå±€ã®äŸåé¢ä¿ãæŽçã¯ä»¥äžã®ããã«æŽçããããšãã§ããŸããã
- MVVMïŒãšãããObserverãã¿ãŒã³ïŒã«ãã£ãŠæŽçãããäŸåé¢ä¿
- ãã¬ãŒã³ããŒã·ã§ã³å±€ãã¢ããªã±ãŒã·ã§ã³å±€ã«äŸåãã
- ã¢ããªã±ãŒã·ã§ã³å±€ã¯ãã¬ãŒã³ããŒã·ã§ã³å±€ã«äŸåããªã
- èªç¶ã«çãŸããäŸåé¢ä¿
- ã¢ããªã±ãŒã·ã§ã³å±€ããã¡ã€ã³å±€ã«äŸåãã
- ãã¡ã€ã³å±€ã¯ã¢ããªã±ãŒã·ã§ã³å±€ã«äŸåããªã
- DIPã«ãã£ãŠæŽçãããäŸåé¢ä¿
- ã€ã³ãã©ã¹ãã©ã¯ãã£å±€ããã¡ã€ã³å±€ã«äŸåãã
- ãã¡ã€ã³å±€ã¯ã€ã³ãã©ã¹ãã©ã¯ãã£å±€ã«äŸåããªã
å³ã«ãããšãäžå³ã®ããã«ãªããŸãã
ãå€åŽãã®ã³ã³ããŒãã³ãã¯ãå åŽãã«äŸåããŠããŸããããå åŽãã®ã³ã³ããŒãã³ãã¯äžåãå€åŽãã«äŸåããŠããªãç¶æ ã«ãªã£ãŠããŸããClean Architectureã®ã³ã³ã»ããã«äžèŽããŠããŸãã
ãŸãšã
MVVMããLayered ArchitectureããããŠCleanArchitectureã«ã€ããŠãäºããæä»çãªãã®ã§ã¯ãªãããããã¯çžè£çãªé¢ä¿ã«ããããšãèŠãŠããŸããã
ãŸãšãããšã
- PDSã¯ããã¬ãŒã³ããŒã·ã§ã³å±€ãšãã®ä»ãåãããããšããèãæ¹ã§ãã
- MVVMã¯ãã©ããã£ãŠãã¬ãŒã³ããŒã·ã§ã³å±€ãšãã®ä»ãåãããã®å ·äœçãªæéã§ãã
- Layered Architecuterã¯ãããã®ä»ãã®éšåãããããã®å±€ã«åãããããšããèãæ¹ã§ãã
- DDDã®æèã§ã¯ãããããã¬ãŒã³ããŒã·ã§ã³ããã¢ããªã±ãŒã·ã§ã³ãããã¡ã€ã³ããã€ã³ãã©ã¹ãã©ã¯ãã£ããšããåãæ¹ããããããããã®èšäºã§ã¯DDD-like Layered ArchitectureãšäŸ¿å®çã«åŒãã
- Layered Architecuterãæ¡çšããéãObserverãã¿ãŒã³ãDIãªã©ãå©çšããŠããå€åŽãã®ã¬ã€ã€ãŒããå
åŽãã®ã¬ã€ã€ãŒã«äŸåããïŒéã¯é§ç®ïŒãšããã®ããCleanArchitectureã®ã³ã³ã»ããã§ããã
- CleanArchitectureã¯ç¹å®ã®ã¬ã€ã€ãŒã®åãæ¹ãã¬ã€ã€ãŒéã®ã³ãã¥ãã±ãŒã·ã§ã³æ¹æ³ãå®çŸ©ããŠããªã
ãããã«
ããŠãããã§ãããããã®ã¢ãŒããã¯ãã£ã®è§£èª¬ãçµããŸãããæåŸã«ãšãŠãéçšãªããšã念æŒãããŠãããŸãã
æåã«æžããŸãããããã®ãªããžããªã¯ãªãã®ããã«äœãããŠããããèŠããŠããŸããïŒãããMVVMãšCleanArchitectureã®è§£èª¬ã®ããã«æžãããŠããŸãããããã¯ãã®ææžã®äžã§äžåºŠãããã®ã¢ãŒããã¯ãã£ãåžžã«æé©ãªã¢ãŒããã¯ãã£ã§ããããšäž»åŒµããŠããŸããã
ä»åã®ã¢ããªã±ãŒã·ã§ã³ã¯ãããŸããŸããšãŠãã¹ããŒããã«ãªã¢ããªã±ãŒã·ã§ã³ã§ããããªããã€ãç¶æ å士ãé¢ä¿ããŠåãã¢ããªã±ãŒã·ã§ã³ãªã®ã§ããããªãã«è€éãªä»æ§ã§ãããããªãã«è€éãªä»æ§ãªã®ã§ããã£ãããã£ãããšå±€ãäœã£ãŠããããã®è²¬åãæŽçããã»ããèŠéãã®ããã³ãŒãã«ãªãã§ãããããšããå€æãåããŸãã
äžæ¹ããåãªãCRUDã¢ããªã±ãŒã·ã§ã³ãã ã£ããããããã¯ãåã«APIããå€ãåã£ãŠããŠè¡šç€ºããã ãã®ãã¥ãŒã¯ã¢ããªãã ã£ããããã£ãšåçŽãªäœãã«ããã»ããã³ãŒãéãæžããèŠéããè¯ãããã§ãã
ãŸããä»åã¯ããŸããŸVue.jsãšããMVVMãã¿ãŒã³ãæäŸããŠããããã¬ãŒã ã¯ãŒã¯ã«ä¹ã£ãã£ãã®ã§ãPDSã®æ¹æ³ã«MVVMãã¿ãŒã³ãéžæããŸãããããããReactãreduxãå©çšããå Žåãªããæé©ãªPDSã®æ¹æ³ãç°ãªãã§ãããã
ããšãã°ãid:non_117ããã«ããreduxã§ã¢ãã«å±€ããã¡ããšäœãèšäºã§ã¯ãã¢ãã«ãè¿ãå€ãè¿ããŠããŸããã§ããModelå±€ã¯Reactã«äŸåããããã¡ããšPDSãå®çŸãããŠããŸããããã¯ãreduxãèŠè«ãããã¬ãŒã³ããŒã·ã§ã³å±€ã®äœãæ¹ã«åãããŠPDSãèãããšãã®ã²ãšã€ã®è§£ã§ãããã
ãã®ããã«ããã©ã®ãããªã¢ãŒããã¯ãã£ãæé©ã§ããã®ãããšããã®ã¯ããã¢ããªã±ãŒã·ã§ã³ã®ä»æ§ãã©ããããã®ãªã®ããããã©ã®ãããªãã©ãããã©ãŒã ã«ä¹ã£ãŠããã®ãããšãã«ãã£ãŠå€åããŠãããŸããããããããããäŒç€Ÿãã©ã®ãããªããŒã åãã«ãªã£ãŠããã®ãããªã©ã«ãã£ãŠãç°ãªã£ãŠããã§ãããïŒmicroservicesãšãããããã話ã§ãããïŒã
ãããŠããä»åãªãã°ã©ãããã¢ãŒããã¯ãã£ãæé©ã ãããããšããããšãè°è«ããæ·±ããŠããããã«ã¯ããåããã®ãåãååã§åŒã¶ãå¿ èŠããããŸããAãããæã£ãŠããMVVMãšBãããæã£ãŠããMVVMãç°ãªããšãããããã¯Aããã¯ã¯ãªãŒã³ã¢ãŒããã¯ãã£ã®ããšãã³ã³ã»ããã ãšæã£ãŠè©±ããŠããã®ã«Bããã¯ç¹å®ã®ã¢ãŒããã¯ãã£ã ãšæã£ãŠè©±ããŠãããšãããããŸã£ããè°è«ãåã¿åãããè°è«ã®ã¹ã¿ãŒãã©ã€ã³ã«ããç«ãŠãªãã§ãããã
ãšããããã§ããã®ææžã¯ããã§çµããã§ããããããã®ã³ãŒããšæç« ãã¿ãªããã«ãããããã®ãããä»åã®ã¢ããªã±ãŒã·ã§ã³ãšREADMEã®èšèšãåžžã«æ£ããäžèœã®èšèšã ããæ¯åãããšåãèšèšã«ãããïŒïŒïŒãã§ã¯ãªãããä»åã®ã¢ããªã±ãŒã·ã§ã³ãšREADMEã«ãã£ãŠãæ§ã ãªæŠå¿µãæŽçãããïŒããããèªåãã¡ã®ã¢ããªã±ãŒã·ã§ã³ã«æé©ãªèšèšãè°è«ããŠãããïŒïŒïŒããšãªãããã¿ãªããèªèº«ã®åé¡ã解ãããã®äžå©ããšãªããã°ãæå€ã®åã³ã§ãã
ãã®ãªããžããªã§è§ŠããããŠããªã話é¡
ãã€ã¯ã話ã®ã¹ã³ãŒããçµãããã«ããã®ãªããžããªã§ã¯ãããŠãç¶æ 管çãã«ã€ããŠè§ŠããŠããŸããããã®ãªããžããªã§ã¯ãDomainå±€ã®åãªããžã§ã¯ããããããã«ç¶æ ããã£ãŠãããããªèšèšã«ãªã£ãŠããŸãããè¿å¹Žã§ã¯ãããããããžãã¯ãšç¶æ ãçµåããŠããç¶æ ãã¯ããŸã奜ãŸããŸãããããžãã¯ã¯çŽç²é¢æ°ãã€ãã¥ãŒã¿ãã«ãªã¢ãã«ã§èšè¿°ããç¶æ ã¯äžç®æã«éããäžã§ç¶æ å€æŽã®ãçªå£ããšããŒã¿ãããŒãäžæ¬åãããããªææ³ãååšããŸããFluxã¢ãŒããã¯ãã£ããšåŒã°ãããããªãã®ã§ããä»åã®ãã®ãªããžããªãåºçºç¹ã«ããªãããDDD-like Layered ArchitectureãšFluxã¢ãŒããã¯ãã£ãçµ±åããããšãå¯èœã§ãããã²ææŠããŠèŠãŠãã ããã
License
MIT
Copyright
Copyright 2017 Shinpei Maruyama