ãDIï¼ä¾åæ§æ³¨å ¥ï¼ããã©ãã¸è¡ããã ãã®1ãã«ããã¦ï¼
DIï¼ä¾åæ§æ³¨å ¥ï¼ã«ã¤ãã¦ã¯ãéèªãæ¸ç±ã§éåç´¹ä»ããã¦ããã®ã§ãããããã®ãè¦ã¦ãã ããã
ãããªãã¨[注ï¼DIå]ãã¦ä½ããããããã£ã¦ï¼ ããã¯ããã¡ã¦ã©ã¼å çã¨ããã®ä»ã¨ã©ã¤äººã¨ãã¨ã©ã¯ãªã人ã¨ãã«èãã¦ãã ããã
ã¨æ¸ãã¾ããããDIï¼Dependency Injection; ä¾åæ§æ³¨å ¥ï¼ãã®ãã®ã«ã¤ãã¦ã説æã試ã¿ã¦ã¿ã¾ããããå ·ä½çãªãµã³ãã«ã使ããã¨ã«ãã¾ãããã®ããããµã³ãã«ã®èª¬æãé·ããªã£ã¦ãã¾ãã®ãå°ã£ããã¨ã§ãããã¾ã¼ãåãªãè½æ¸ãããã¯ãµã³ãã«ããã£ãã»ããããã§ããã
å 容ï¼
- ãµã³ãã«ã¯ãã³ãã¬ã¼ãå¦çç³»
- ã¬ã¯ãµã¼ï¼åå¥å¦çç³»ï¼
- ã¬ã¯ãµã¼ãã¤ã³ã¿ã¼ãã§ã¼ã¹çµç±ã§ä½¿ã
- ãµã¼ãã¹ã»ãã±ã¼ã¿ã¼
- ä¾åæ§ãæ¶ãã¦ãªãï¼
- DIï¼ä¾åæ§æ³¨å ¥ï¼ç»å ´
- DIãããã¤ã¦IoCï¼å¶å¾¡ã®é転ï¼ã¨å¼ã°ãã¦ããçç±
âãµã³ãã«ã¯ãã³ãã¬ã¼ãå¦çç³»
ã¾ãXionå¦çç³»ï¼http://www.chimaira.org/tmp/Xion-0.1.tgzï¼ãä¾ã«ããããã¨ãæã£ãã®ã§ããããµã³ãã«ã«ã¯å°ã大ããæ°ãããã®ã§ãå¥ãªï¼ãããããä¼¼ãï¼ä¾ãã§ã£ã¡ä¸ãã¾ãã
ãããç°¡åãªãã³ãã¬ã¼ãï¼Very Simple Templates; VSTï¼å¦çç³»ã«ãã¾ãããã次ããã³ãã¬ã¼ãã®ä¾ã
ãã³ãã¬ã¼ãå¦çç³»ã«ããã{ã客æ§å}ã¨{æ¥åºæ¥}ã®é¨åãé©åãªæååã«ç½®æããããã¨ã«ãªãã¾ãã
{ã客æ§å}æ§ãããã«ã¡ã¯ã{æ¥åºæ¥}ã«ã¯ãæ¥åºããã ãã
ã¾ãã¨ã«ãããã¨ããããã¾ãã
æ¬æ¥ã¯{ã客æ§å}æ§ã«æ°ååããç´¹ä»ãããã¾ãã
â¦
ãã³ãã¬ã¼ãå¦çã¯ã次ã®2ã¤ã®é¨åã«åãã¦èãã¾ãã
- ãã³ãã¬ã¼ãã»ããã¹ãããã¼ããã¦ã¡ã¢ãªå ã«æ±ãããããã¼ã¿æ§é ãä½ãã
- å®éã®ç½®æå¦çããã¦çµæãåºåããã
ãã¼ãå¦çãè¡ãã®ã¯VSTãã¼ã¶ã¼ã§ããããã®ãã¼ã¶ã¼ã¯SAXï¼Simple API for XMLï¼ãçä¼¼ã¦ããæ§æè¦ç´ ãã¨ã«å¦çã¡ã½ããï¼ãã³ãã©ï¼ãã³ã¼ã«ããã¯ããæ¹å¼ãã¨ãã¾ãããã¼ã¶ã¼ï¼ããããä½ã£ã¦ãªã(è¦ç¬)ï¼ã®ã½ã¼ã¹ã³ã¼ãã¯ä»¥ä¸ã®ã¨ããï¼ããã±ã¼ã¸ã¯ä½¿ã£ã¦ãªãããåä¸ãã¡ã¤ã«ã«è¤æ°ã¯ã©ã¹ãè©°ãè¾¼ãã§ãããããã£ã¦quick-and-dirtyã§ãããå¦çã®æ¹éã¯èªã¿åããã§ãããã
âã¬ã¯ãµã¼ï¼åå¥å¦çç³»ï¼
ãµã³ãã«ã«ããã¦ããã¼ã¶ã¼ï¼VSTParserï¼ã¯ã¬ã¯ãµã¼ï¼VSTLexerï¼ãä¸è«ãã«ä½¿ãã¾ããã¬ã¯ãµã¼ã¯ãå ¥åããã¹ããã'{'ï¼å·¦æ³¢æ¬å¼§ï¼left braceï¼ã'}'ï¼å³æ³¢æ¬å¼§ï¼right braceï¼ããã®ä»ã®ããã¹ãé¨åã«åãåãããã¡ã¤ã«ã®æå¾ã§ã¯EOFï¼end-of-fileï¼ãç¥ããã¾ããã¬ã¯ãµã¼ã®ä¸»è¦ã¡ã½ããnextTokenã®æ»ãå¤ã¯æ¬¡ã®VSTTokenåã§ãã
/* ãã¼ã¯ã³ã»ãã¼ã¿ */
class VSTToken {
enum Kind {L_BRACE, R_BRACE, TEXT, EOF}
final Kind kind;
final String value;
VSTToken(Kind kind, String value) {
this.kind = kind;
this.value = value;
}
}
ä»åã®è©±é¡ï¼æèããã¯è足ã§ããã次ã®ç¹ã注æãã¦ããã¾ãï¼
- ç¹æ®è¨å·'{'ã'}'ãï¼é©å½ãªæ¹å¼ã§ï¼ã¨ã¹ã±ã¼ãããã¦ããã°ãããã¯ããã¹ãã¨ãã¦è¿ãã
- ãã®ä»ã®æåãã¨ã¹ã±ã¼ãããã¦ããã¨ãããã¨ã¹ã±ã¼ããã»ã©ãã¦ï¼unescapeãã¦ï¼è¿ãã
- ã¬ã¯ãµã¼ã¯ã'{'ã'}'ã®å é¨ã¨å¤é¨ãåºå¥ããå¿ è¦ã¯ãªãã
- ã²ã¨ããã¾ãã®ããã¹ãããä½åãã®ããã¹ãã»ãã¼ã¯ã³ã«åãã¦è¿ãã¦ãããã
- ãã¼ã¯ã³ã®valueãnullã§ãã£ã¦ã¯ãããªããã""ã§ãã£ã¦ãããã
ãªãããµã³ãã«ã»ã³ã¼ãã§ã¯ã'{'ã®ã¨ã¹ã±ã¼ãã«ã¯'{{'ï¼æ³¢æ¬å¼§ã2åç¶ããï¼ã使ã£ã¦ãã¾ãã
âã¬ã¯ãµã¼ãã¤ã³ã¿ã¼ãã§ã¼ã¹çµç±ã§ä½¿ã
ãã¼ã¶ã¼ã¯ã¬ã¯ãµã¼ãå¿ è¦ã¨ãã¾ãããµã³ãã«ã§ã¯ããã¼ã¶ã¼ã®ä¸»è¦ã¡ã½ããparseå ã§ã次ã«ããã«ãã¦ã¬ã¯ãµã¼ãå ¥æãã¦ãã¾ãã
public void parse(Reader input) throws IOException, VSTParseException {
VSTLexer lexer = new VSTLexer(input);
// ...
}
ããã ã¨ããã¼ã¶ã¼ï¼VSTParserï¼ã¯ãã¬ã¯ãµã¼ã®å ·ä½çå®è£ ã¯ã©ã¹ã§ããVSTLexerã«ç´æ¥ã«ä¾åããã®ã§å¥½ã¾ãããªããã¨ããã¾ã -- ãã®å»ºåã®çå½ã¯è©®ç´¢ããªãã§ç´ ç´ã«å¾ããã¨ã«ãã¾ããããã§ãVSTLexerãã¤ã³ã¿ã¼ãã§ã¼ã¹ã«ãã¾ããã¬ã¯ãµã¼ã»ãªãã¸ã§ã¯ããçæããå¾ã§ãinputã渡ããã»ãã便å©ã§ããããsetInputã¨ããã»ãã¿ã¼ãã¤ã³ã¿ã¼ãã§ã¼ã¹ã«å ãã¾ãã*1ã
import java.io.*;interface VSTLexer {
public void setInput(Reader reader);
public VSTToken nextToken() throws IOException;
}
ãã¨ã®VSTLexerå®è£ ã¯ã©ã¹ã¯ãVSTLexerStdImplã¨ã§ãæ¹åãã¦ããã¾ãããã
ãã¦ãã¤ã³ã¿ã¼ãã§ã¼ã¹ã ãã§ã¯çæï¼newï¼ãã§ããªãã®ã§ç´°å·¥ãå¿ è¦ã§ãããã¡ã¯ããªã¼ã使ãã®ãã²ã¨ã¤ã®æ¹æ³ã§ããã
public void parse(Reader input) throws IOException, VSTParseException {
VSTLexerFactory factory = new VSTLexerFactory("some parameter");
VSTLexer lexer = factory.create(input);
// ...
}
setInputãããã®ã§ã次ã®ããã«ãã§ãã¾ãã
// ã¬ã¯ãµã¼ã®çæã¯ããã¼ã¶ã¼ã®ã³ã³ã¹ãã©ã¯ã¿å ã§ããã
VSTLexerFactory factory = new VSTLexerFactory("some parameter");
VSTLexer lexer = factory.create();
// å¾ããinputãã»ããã§ããããã
lexer.setInput(input);
âãµã¼ãã¹ã»ãã±ã¼ã¿ã¼
ã¬ã¯ãµã¼ã»ãã¡ã¯ããªã¼ãããã£ã¨ä¸è¬çãªæ¹æ³ãèãã¾ããã¤ã³ã¿ã¼ãã§ã¼ã¹ãäºåã«å®ç¾©ãããååã渡ãã¨ãé©å½ãªãªãã¸ã§ã¯ããè¿ããããªæé 師ãèãã¾ãããã®ãããªæé 師ããµã¼ãã¹ã»ãã±ã¼ã¿ã¼ï¼service locatorï¼ã¨å¼ã¶ããã§ãã
public void parse(Reader input) throws IOException, VSTParseException {
VSTLexer lexer = null;
MyServiceLocator locator = MyServiceLocator.getInstance();
try {
lexer = (VSTLexer)locator.getService(VSTLexer.class);
} catch (Exception e) {
// ã¨ã©ã¼å¦ç
}
lexer.setInput(input);
// ...
}
â»ãããç´æ£ãªãµã¼ãã¹ã»ãã±ã¼ã¿ã¼ã«ãªã£ã¦ãããã©ããã¯ç¥ããªãã
âä¾åæ§ãæ¶ãã¦ãªãï¼
ãã¡ã¯ããªã¼ããµã¼ãã¹ã»ãã±ã¼ã¿ã¼ã使ãã¨ããã¼ã¶ã¼ã®ã³ã¼ãããã¬ã¯ãµã¼å®è£ ã¯ã©ã¹ã¸ã®åç §ããªããªãã®ã§ããã¬ã¯ãµã¼å®è£ ã¯ã©ã¹ã¸ã®ç´æ¥çãªä¾åæ§ãã¯ç¢ºãã«è§£æ¶ããã¾ããããããã®ä»£ãããVSTLexerFactoryãMyServiceLocatorã«ä¾åãã¦ãã¾ãã¾ãã
ãã¼ã¶ã¼ãæ¸ãããã°ã©ãã¯ãVSTLexerFactoryãMyServiceLocatorã®åå¨ãç¥ã£ã¦ããªããã°ãªããªããããã®ä½¿ãæ¹ã®ç¥èãå¿ è¦ã§ãããããããã¯ãããã¼ã¶ã¼ã®å¦çãæ¸ããã¨ããæ¬æ¥ã®ç®çããããã°ä½è¨ãªãã¨ãè¦ãã¬è² æ ãå¼·ãã¦ãã¾ãã
ããã«æªããã¨ã«ã¯ãVSTLexerFactoryãMyServiceLocatorã使ã£ããã¼ã¶ã¼ã¯ãå½ç¶ãªãããVSTLexerFactoryãMyServiceLocatorããªãç°å¢ã§ã¯ã³ã³ãã¤ã«ãå®è¡ãã§ãã¾ããããã¼ã¶ã¼ãã»ãã¨ã«å¿ è¦ã¨ããã®ã¯ãé©åãªã¬ã¯ãµã¼å®è£ ã§ãããç£å©å½¹ãæé 師ã§ããVSTLexerFactoryãMyServiceLocatorãããªãã§ããããªããæ¬æ«è»¢åã ããªã
âDIï¼ä¾åæ§æ³¨å ¥ï¼ç»å ´
- ãã¼ã¶ã¼ã¯ã¬ã¯ãµã¼å®è£ ã¯ã©ã¹ã«ä¾åããããªããã¬ã¯ãµã¼å®è£ ã¯ã©ã¹ãç´æ¥ã«ç¥ã£ã¦ã¯ãããªãã
- ãã¼ã¶ã¼ãã»ãã¨ã«å¿ è¦ã¨ãã¦ããã®ã¯ã¬ã¯ãµã¼å®è£ ãªãã¸ã§ã¯ãã§ãããä½è¨ãªä»²ä»äººãªãã¦ãå¼ã³ã§ãªãã
ãã®ä¸è¦ã¸ã¬ã³ãã®ç¶æ³ã解決ããæ段ã¯ãã¬ã¯ãµã¼å®è£ ãå ¥æãã仲ä»äººããè¦ç¥ãã¬å¤é¨ã®åå¨ãã¨è¦ãªããã¨ã§ãã誰ã ãç¥ããªãããã¨ã«ãã親åãªãã¬ã«ãµã³ãã¬ã¯ãµã¼å®è£ ãæé ãã¦æ¸¡ãã¦ãããã®ã§ããã®åãå£ã ãæºåãã¾ãã
ãã£ã¨ãåç´ãªåãå£ã¯ãã¬ã¯ãµã¼ãã»ããããå¤æ°ï¼ãã£ã¼ã«ãï¼ã§ãã次ã®ãããªãªãã¸ãã¤ãæ¸ãã¦ããã ãã
class VSTParser {
public VSTLexer lexer; // ããã«ãã¬ã«ãµã³ãã»ãããã¦ããã
// ....
}
ãããã¯ãåãå£ï¼å¤ããè¦ãã¨æ³¨å ¥å£ï¼ãã»ãã¿ã¼ã»ã¡ã½ããã«ãã¦ï¼
class VSTParser {
private VSTLexer lexer;
// ãã®ã¡ã½ããããã¬ã«ãµã³ãå¼ãã§ããã
public void setLexer(VSTLexer lexer) {
this.lexer = lexer;
}
// ....
}
ãã®ããã«ããã°ããã¼ã¶ã¼ã³ã¼ãã¯ç´ç²ã«ãã¼ã¸ã³ã°å¦çãè¨è¿°ãã¦ããã ãã§ããåãå£ï¼æ³¨å ¥å£ï¼ã«é¢ããããããç´æãã¨ï¼ã³ã³ãã³ã·ã§ã³ï¼ã«ã¯å¾ãã¾ããã仲ä»äººã®åå¨ãæèãããã¬ã¯ãµã¼å®è£ ãç´æ¥åç §ãããã¨ããªããã¬ã¼ã³ï¼ã¯ãªã¼ã³ãªã³ã¼ãã«ãªãã¾ããã
âDIãããã¤ã¦IoCï¼å¶å¾¡ã®é転ï¼ã¨å¼ã°ãã¦ããçç±
ãInversion of Control コンテナと Dependency Injection パターンãã«ããã°ãDIã¯ãã¤ã¦ãIoCï¼Inversion of Control; å¶å¾¡ã®é転ï¼ã¨å¼ã°ãã¦ããããã§ãããå¶å¾¡ã®é転ããããªãã®ãã¨ã ãåãããªãããããä¾åæ§æ³¨å ¥ãã«ããã¨ã®ãã¨ï¼ããã§ããªãã ãåãããªãã¨æããï¼ã
確ãã«ãä½ããé転ãã¦ããå°è±¡ãããã®ã ãã©ãã©ãããå¶å¾¡ããããªããããªâ¦ ããããã責åï¼responsibilityï¼ã®é転ãã§IoRã®ãããªæ°ããããã§ãé転ãã責åã¯ä½ã«é¢ãã責åãã¨ããã°ï¼
- èªåã«å¿ è¦ãªã¢ãä¸å¼ãå ¥æãã責å
å®è£ ã¯ã©ã¹ã®é¸æããªãã¸ã§ã¯ãã®çæã¨åæåããã¡ã¯ããªã¼ããµã¼ãã¹ã»ãã±ã¼ã¿ã¼ã«ä»»ãã¦ããçµå±ããã¡ã¯ããªã¼ããµã¼ãã¹ã»ãã±ã¼ã¿ã¼ãå©ç¨ãã¦å¿ è¦ãªãªãã¸ã§ã¯ããæããã³ã¼ããæ®ã£ã¦ãã¾ããã
VSTLexer lexer = factory.create();
lexer = (VSTLexer)locator.getService(VSTLexer.class);
ã¤ã¾ãããèªåã«å¿ è¦ãªã¢ãã¯ï¼ä»²ä»äººã®æãåããã«ãã¦ãï¼èªåèªèº«ã§å ¥æãããã ã£ããã§ããã
ãããããå¿ è¦ãªã¢ãã®å ¥æã¯ã親åãªãã¬ã«ãµã³ãå ¨é¨ãã£ã¦ãããããä»»ãã¦ãããèªåã§ãããªãã¦ãããã«å¤ãã£ãã®ã§ããå¿ è¦ãªã¢ãã®å ¥æãã®è²¬åãâä¸ããå¤ã¸ç§»ã£ã¦ããâãã¾ã¼é転ãã¦ãã¾ãããã
ã¨ãããããèãæ¹ã¨ãã¦ã®ãä¾åæ§æ³¨å ¥ï¼è²¬åã®é転ãã¯ãããªãã¨ãããªãã§ãããããå ·ä½çææ³ã¨ãæ¯æ´ç°å¢ã¨ãã¯ãã¾ãè²ã ã¨ããã§ããããã
*1:ãã¼ããã¼ã¹ã»ã³ã³ããã³ãã®çºæ³ã§ã¯ãsetInputã¯ã¬ã¯ãµã¼æ©è½ã表ãã¤ã³ã¿ã¼ãã§ã¼ã¹ã®ä¸é¨ã¨ãããããããããã¼ãéã®ã¯ã¤ã¤ãªã³ã°æ©æ§ã ã¨èãã¾ãã