å ç¢ã§ä¿å®æ§ã®é«ãã¢ããªã±ãŒã·ã§ã³ã®ããã«ãJavaScriptã¢ãžã¥ãŒã«èšèšã«ããããªã¹ã³ãã®çœ®æååïŒLSPïŒãæ¢æ±ããŸããæ¯ãèãã®äºææ§ãç¶æ¿ãããªã¢ãŒãã£ãºã ã«ã€ããŠåŠã³ãŸãã
JavaScriptã¢ãžã¥ãŒã«ã«ããããªã¹ã³ãã®çœ®æååïŒæ¯ãèãã®äºææ§
ãªã¹ã³ãã®çœ®æååïŒLSPïŒã¯ããªããžã§ã¯ãæåããã°ã©ãã³ã°ã®5ã€ã®SOLIDååã®1ã€ã§ããããã¯ããµãã¿ã€ãã¯ãããã°ã©ã ã®æ£ç¢ºæ§ã倿Žããããšãªãããã®åºæ¬åãšçœ®æå¯èœã§ãªããã°ãªããªããšè¿°ã¹ãŠããŸããJavaScriptã¢ãžã¥ãŒã«ã®ã³ã³ããã¹ãã§ã¯ãã¢ãžã¥ãŒã«ãç¹å®ã®ã€ã³ã¿ãŒãã§ãŒã¹ãŸãã¯åºæ¬ã¢ãžã¥ãŒã«ã«äŸåããŠããå Žåããã®ã€ã³ã¿ãŒãã§ãŒã¹ãå®è£ ãŸãã¯ãã®åºæ¬ã¢ãžã¥ãŒã«ããç¶æ¿ããã¢ãžã¥ãŒã«ã¯ãäºæããªãåäœãåŒãèµ·ããããšãªãããã®å Žæã«å©çšã§ããå¿ èŠããããŸããLSPãéµå®ããããšã¯ãããä¿å®æ§ãé«ããå ç¢ã§ããã¹ãå¯èœãªã³ãŒãããŒã¹ã«ã€ãªãããŸãã
ãªã¹ã³ãã®çœ®æååïŒLSPïŒã®çè§£
LSPã¯ã1987幎ã®åºèª¿è¬æŒãããŒã¿æœè±¡åãšéå±€ãã§ãã®æŠå¿µã玹ä»ããããŒãã©ã»ãªã¹ã³ãã«ã¡ãªãã§åä»ããããŸãããå ã ã¯ãªããžã§ã¯ãæåã¯ã©ã¹éå±€ã®ã³ã³ããã¹ãã§å®åŒåãããŸãããããã®ååã¯JavaScriptã®ã¢ãžã¥ãŒã«èšèšãç¹ã«ã¢ãžã¥ãŒã«ã®æ§æãšäŸåæ§æ³šå ¥ãèæ ®ããå Žåã«ãåæ§ã«é¢é£æ§ããããŸãã
LSPã®æ ¹åºã«ããæ žå¿ã¯ãæ¯ãèãã®äºææ§ã§ãããµãã¿ã€ãïŒãŸãã¯ä»£æ¿ã¢ãžã¥ãŒã«ïŒã¯ããã®åºæ¬åïŒãŸãã¯å ã®ã¢ãžã¥ãŒã«ïŒãšåãã¡ãœãããŸãã¯ããããã£ãåã«å®è£ ããã ãã§ãªããåºæ¬åã®æåŸ ãšäžèŽããæ¹æ³ã§æ¯ãèãå¿ èŠããããŸããããã¯ãã¯ã©ã€ã¢ã³ãã³ãŒãã«ãã£ãŠèªèããã代æ¿ã¢ãžã¥ãŒã«ã®æ¯ãèãããåºæ¬åã«ãã£ãŠç¢ºç«ãããå¥çŽã«éåããŠã¯ãªããªãããšãæå³ããŸãã
æ£åŒãªå®çŸ©
æ£åŒã«ã¯ãLSPã¯æ¬¡ã®ããã«è¿°ã¹ãããšãã§ããŸãã
Tåã®ãªããžã§ã¯ãxã«ã€ããŠèšŒæå¯èœãªããããã£Ï(x)ããããšããŸããæ¬¡ã«ãÏ(y)ã¯ãSãTã®ãµãã¿ã€ãã§ããSåã®ãªããžã§ã¯ãyã«å¯ŸããŠçã§ããã¹ãã§ãã
ç°¡åã«èšããšãåºæ¬åã®æ¯ãèãã«ã€ããŠäž»åŒµã§ããå Žåããããã®äž»åŒµã¯ããã®ãµãã¿ã€ãã®ãããã«å¯ŸããŠãäŸç¶ãšããŠæå¹ã§ããã¯ãã§ãã
JavaScriptã¢ãžã¥ãŒã«ã«ãããLSP
JavaScriptã®ã¢ãžã¥ãŒã«ã·ã¹ãã ãç¹ã«ESã¢ãžã¥ãŒã«ïŒESMïŒã¯ãLSPååãé©çšããããã®åªããåºç€ãæäŸããŸããã¢ãžã¥ãŒã«ã¯ã€ã³ã¿ãŒãã§ãŒã¹ãŸãã¯æœè±¡çãªæ¯ãèãããšã¯ã¹ããŒãããä»ã®ã¢ãžã¥ãŒã«ã¯ãããã®ã€ã³ã¿ãŒãã§ãŒã¹ãã€ã³ããŒãããŠå©çšã§ããŸããããã¢ãžã¥ãŒã«ãå¥ã®ã¢ãžã¥ãŒã«ã«çœ®ãæããå Žåãæ¯ãèãã®äºææ§ã確ä¿ããããšãéèŠã§ãã
äŸïŒéç¥ã¢ãžã¥ãŒã«
ç°¡åãªäŸãšããŠãéç¥ã¢ãžã¥ãŒã«ãèããŠã¿ãŸãããããŸãã¯ãåºæ¬ã®`Notifier`ã¢ãžã¥ãŒã«ããå§ããŸãã
// notifier.js
export class Notifier {
constructor(config) {
this.config = config;
}
sendNotification(message, recipient) {
throw new Error("sendNotification must be implemented in a subclass");
}
}
次ã«ã2ã€ã®ãµãã¿ã€ãã`EmailNotifier`ãš`SMSNotifier`ãäœæããŸãããã
// email-notifier.js
import { Notifier } from './notifier.js';
export class EmailNotifier extends Notifier {
constructor(config) {
super(config);
if (!config.smtpServer || !config.emailFrom) {
throw new Error("EmailNotifier requires smtpServer and emailFrom in config");
}
}
sendNotification(message, recipient) {
// Send email logic here
console.log(`Sending email to ${recipient}: ${message}`);
return `Email sent to ${recipient}`; // Simulate success
}
}
// sms-notifier.js
import { Notifier } from './notifier.js';
export class SMSNotifier extends Notifier {
constructor(config) {
super(config);
if (!config.twilioAccountSid || !config.twilioAuthToken || !config.twilioPhoneNumber) {
throw new Error("SMSNotifier requires twilioAccountSid, twilioAuthToken, and twilioPhoneNumber in config");
}
}
sendNotification(message, recipient) {
// Send SMS logic here
console.log(`Sending SMS to ${recipient}: ${message}`);
return `SMS sent to ${recipient}`; // Simulate success
}
}
æåŸã«ã`Notifier`ã䜿çšããã¢ãžã¥ãŒã«ã§ãã
// notification-service.js
import { Notifier } from './notifier.js';
export class NotificationService {
constructor(notifier) {
if (!(notifier instanceof Notifier)) {
throw new Error("Notifier must be an instance of Notifier");
}
this.notifier = notifier;
}
send(message, recipient) {
return this.notifier.sendNotification(message, recipient);
}
}
ãã®äŸã§ã¯ã`EmailNotifier`ãš`SMSNotifier`ã¯`Notifier`ãšçœ®ãæãå¯èœã§ãã`NotificationService`ã¯`Notifier`ã€ã³ã¹ã¿ã³ã¹ãæåŸ ãããã®`sendNotification`ã¡ãœãããåŒã³åºããŸãã`EmailNotifier`ãš`SMSNotifier`ã®äž¡æ¹ããã®ã¡ãœãããå®è£ ããŠããããã®å®è£ ã¯ç°ãªããŸãããéç¥ãéä¿¡ãããšããå¥çŽãæºãããŠããŸããæåã瀺ãæååãè¿ããŸããéèŠãªã®ã¯ãéç¥ã*éä¿¡ããªã*ããŸãã¯äºæããªããšã©ãŒãã¹ããŒãã`sendNotification`ã¡ãœããã远å ããå ŽåãLSPã«éåããããšã«ãªããšããããšã§ãã
LSPãžã®éå
æ¬ é¥ã®ãã`SilentNotifier`ãå°å ¥ããå ŽåãèããŠã¿ãŸãããã
// silent-notifier.js
import { Notifier } from './notifier.js';
export class SilentNotifier extends Notifier {
sendNotification(message, recipient) {
// Does nothing! Intentionally silent.
console.log("Notification suppressed.");
return null; // Or maybe even throws an error!
}
}
`NotificationService`ã®`Notifier`ã`SilentNotifier`ã«çœ®ãæãããšãã¢ããªã±ãŒã·ã§ã³ã®åäœãäºæããªãæ¹æ³ã§å€åããŸãããŠãŒã¶ãŒã¯éç¥ãéä¿¡ãããããšãæåŸ ãããããããŸããããäœãèµ·ãããŸãããããã«ã`null`ã®æ»ãå€ã¯ãåŒã³åºãå ã®ã³ãŒããæååãæåŸ ããŠããå Žåã«åé¡ãåŒãèµ·ããå¯èœæ§ããããŸããããã¯ããµãã¿ã€ããåºæ¬åãšäžè²«ããåäœãããªããããLSPã«éåããŠããŸãã`NotificationService`ã¯ã`SilentNotifier`ã䜿çšãããšå£ããŸãã
LSPãéµå®ããããšã®å©ç¹
- ã³ãŒãã®åå©çšæ§ã®åäžïŒ LSPã¯ãåå©çšå¯èœãªã¢ãžã¥ãŒã«ã®äœæãä¿é²ããŸãããµãã¿ã€ãã¯åºæ¬åãšçœ®ãæãå¯èœã§ãããããæ¢åã®ã³ãŒãã倿ŽããããšãªããããŸããŸãªã³ã³ããã¹ãã§äœ¿çšã§ããŸãã
- ä¿å®æ§ã®åäžïŒ ãµãã¿ã€ããLSPãéµå®ããå Žåããµãã¿ã€ããžã®å€æŽããã¢ããªã±ãŒã·ã§ã³ã®ä»ã®éšåã«ãã°ãäºæããªãåäœãå°å ¥ããå¯èœæ§ã¯äœããªããŸããããã«ãããã³ãŒãã¯ããç°¡åã«ä¿å®ããã³é²åãããããšãã§ããŸãã
- ãã¹ãæ§ã®åäžïŒ LSPã¯ããµãã¿ã€ããåºæ¬åãšã¯å¥ã«ãã¹ãã§ããããããã¹ããç°¡çŽ åããŸããåºæ¬åã®åäœãæ€èšŒãããã®ãã¹ãããµãã¿ã€ãã«åå©çšãããã¹ããäœæã§ããŸãã
- çµåã®åæžïŒ LSPã¯ãã¢ãžã¥ãŒã«ãå ·è±¡å®è£ ã§ã¯ãªãæœè±¡ã€ã³ã¿ãŒãã§ãŒã¹ãä»ããŠçžäºäœçšã§ããããã«ããããšã«ãããã¢ãžã¥ãŒã«éã®çµåãåæžããŸããããã«ãããã³ãŒãã¯ããæè»ã«ãªãã倿Žã容æã«ãªããŸãã
JavaScriptã¢ãžã¥ãŒã«ã§LSPãé©çšããããã®å®çšçãªã¬ã€ãã©ã€ã³
- å¥çŽã«ããèšèšïŒ ã¢ãžã¥ãŒã«ã®äºæãããåäœãæå®ããæç¢ºãªå¥çŽïŒã€ã³ã¿ãŒãã§ãŒã¹ãŸãã¯æœè±¡ã¯ã©ã¹ïŒãå®çŸ©ããŸãããµãã¿ã€ãã¯ããããã®å¥çŽãå³å¯ã«éµå®ããå¿ èŠããããŸããTypeScriptãªã©ã®ããŒã«ã䜿çšããŠãã³ã³ãã€ã«æã«ãããã®å¥çŽã匷å¶ããŸãã
- åææ¡ä»¶ã®åŒ·åã®åé¿ïŒ ãµãã¿ã€ãã¯ããã®åºæ¬åãããå³ããåææ¡ä»¶ãå¿ èŠãšãã¹ãã§ã¯ãããŸãããåºæ¬åãç¹å®ã®ç¯å²ã®å ¥åãåãå ¥ããå Žåããµãã¿ã€ãã¯åãç¯å²ãŸãã¯ããåºãç¯å²ãåãå ¥ããå¿ èŠããããŸãã
- äºåŸæ¡ä»¶ã®åŒ±äœåã®åé¿ïŒ ãµãã¿ã€ãã¯ããã®åºæ¬åããã匱ãäºåŸæ¡ä»¶ãä¿èšŒãã¹ãã§ã¯ãããŸãããåºæ¬åãç¹å®ã®çµæãä¿èšŒããå Žåããµãã¿ã€ãã¯åãçµæãŸãã¯ãã匷ãçµæãä¿èšŒããå¿ èŠããããŸãã
- äºæããªãäŸå€ã®ã¹ããŒã®åé¿ïŒ ãµãã¿ã€ãã¯ãåºæ¬åãã¹ããŒããªãäŸå€ãã¹ããŒãã¹ãã§ã¯ãããŸããïŒãããã®äŸå€ãåºæ¬åã«ãã£ãŠã¹ããŒãããäŸå€ã®ãµãã¿ã€ãã§ãªãéãïŒã
- ç¶æ¿ã®è³¢æãªäœ¿çšïŒ JavaScriptã§ã¯ãç¶æ¿ã¯ãããã¿ã€ãç¶æ¿ãŸãã¯ã¯ã©ã¹ããŒã¹ã®ç¶æ¿ã«ãã£ãŠå®çŸã§ããŸããç¶æ¿ã®æœåšçãªèœãšã穎ïŒå¯çµåãè匱ãªåºæ¬ã¯ã©ã¹ã®åé¡ãªã©ïŒã«æ³šæããŠãã ãããé©åãªå Žåã¯ãç¶æ¿ãããæ§æãæ€èšããŠãã ããã
- ã€ã³ã¿ãŒãã§ãŒã¹ã®äœ¿çšïŒTypeScriptïŒïŒ TypeScriptã€ã³ã¿ãŒãã§ãŒã¹ã䜿çšããŠããªããžã§ã¯ãã®åœ¢ç¶ãå®çŸ©ãããµãã¿ã€ããå¿ é ã®ã¡ãœãããšããããã£ãå®è£ ããŠããããšã匷å¶ã§ããŸããããã¯ããµãã¿ã€ããåºæ¬åãšçœ®ãæãå¯èœã§ããããšã確èªããã®ã«åœ¹ç«ã¡ãŸãã
é«åºŠãªèæ ®äºé
ããªã¢ã³ã¹
ããªã¢ã³ã¹ãšã¯ã颿°ã®ãã©ã¡ãŒã¿ãŒãšæ»ãå€ã®åãããã®çœ®æå¯èœæ§ã«ã©ã®ããã«åœ±é¿ããããæããŸããããªã¢ã³ã¹ã«ã¯3ã€ã®ã¿ã€ãããããŸãã
- å ±å€æ§ïŒ ãµãã¿ã€ãããåºæ¬åãããå ·äœçãªåãè¿ãããšãèš±å¯ããŸãã
- å倿§ïŒ ãµãã¿ã€ãããåºæ¬åãããäžè¬çãªåããã©ã¡ãŒã¿ãŒãšããŠåãå ¥ããããšãèš±å¯ããŸãã
- äžå€æ§ïŒ ãµãã¿ã€ãããåºæ¬åãšåããã©ã¡ãŒã¿ãŒãšæ»ãå€ã®åãæã€ããšãå¿ èŠãšããŸãã
JavaScriptã®åçåä»ãã«ãããããªã¢ã³ã¹ã«ãŒã«ãå³å¯ã«é©çšããããšã¯å°é£ã§ãããã ããTypeScriptã¯ãããå¶åŸ¡ãããæ¹æ³ã§ããªã¢ã³ã¹ã管çããã®ã«åœ¹ç«ã€æ©èœãæäŸããŸããéèŠãªã®ã¯ãåã®ç¹æ®åæã§ãã颿°ã·ã°ããã£ãäºææ§ãç¶æããããšã§ãã
ã¢ãžã¥ãŒã«ã®æ§æãšäŸåé¢ä¿ã®æ³šå ¥
LSPã¯ãã¢ãžã¥ãŒã«ã®æ§æãšäŸåé¢ä¿ã®æ³šå ¥ã«å¯æ¥ã«é¢é£ããŠããŸããã¢ãžã¥ãŒã«ãæ§æããå Žåãã¢ãžã¥ãŒã«ãççµåã§ãããæœè±¡ã€ã³ã¿ãŒãã§ãŒã¹ãä»ããŠçžäºäœçšããããã«ããããšãéèŠã§ããäŸåé¢ä¿ã®æ³šå ¥ã«ãããå®è¡æã«ã€ã³ã¿ãŒãã§ãŒã¹ã®ããŸããŸãªå®è£ ãæ³šå ¥ã§ããŸããããã¯ããã¹ããšæ§æã«åœ¹ç«ã¡ãŸããLSPã®ååã¯ããããã®çœ®æãå®å šã§ãããäºæããªãåäœãå°å ¥ããªãããã«ããã®ã«åœ¹ç«ã¡ãŸãã
å®éã®äŸïŒããŒã¿ã¢ã¯ã»ã¹å±€
ããŸããŸãªããŒã¿ãœãŒã¹ãžã®ã¢ã¯ã»ã¹ãæäŸããããŒã¿ã¢ã¯ã»ã¹å±€ïŒDALïŒãèããŠã¿ãŸãããã`MySQLDataAccess`ã`PostgreSQLDataAccess`ã`MongoDBDataAccess`ãªã©ã®ãµãã¿ã€ããæã€åºæ¬ã®`DataAccess`ã¢ãžã¥ãŒã«ãããå ŽåããããŸããåãµãã¿ã€ãã¯åãã¡ãœããïŒããšãã°ã`getData`ã`insertData`ã`updateData`ã`deleteData`ïŒãå®è£ ããŸãããå¥ã®ããŒã¿ããŒã¹ã«æ¥ç¶ããŸããLSPãéµå®ããå Žåããããã䜿çšããã³ãŒãã倿Žããããšãªãããããã®ããŒã¿ã¢ã¯ã»ã¹ã¢ãžã¥ãŒã«ãåãæ¿ããããšãã§ããŸããã¯ã©ã€ã¢ã³ãã³ãŒãã¯ã`DataAccess`ã¢ãžã¥ãŒã«ã«ãã£ãŠæäŸãããæœè±¡ã€ã³ã¿ãŒãã§ãŒã¹ã«ã®ã¿äŸåããŸãã
ãã ããMongoDBã®æ§è³ªã«ããã`MongoDBDataAccess`ã¢ãžã¥ãŒã«ããã©ã³ã¶ã¯ã·ã§ã³ããµããŒãããã`beginTransaction`ãåŒã³åºããããšãã«ãšã©ãŒãã¹ããŒããä»ã®ããŒã¿ã¢ã¯ã»ã¹ã¢ãžã¥ãŒã«ããã©ã³ã¶ã¯ã·ã§ã³ããµããŒãããŠãããšããŸããããã¯ã`MongoDBDataAccess`ãå®å šã«çœ®ãæãå¯èœã§ã¯ãªããããLSPã«éåããŸããæœåšçãªè§£æ±ºçã¯ã`MongoDBDataAccess`ã«å¯ŸããŠäœãããªã`NoOpTransaction`ãæäŸããæäœèªäœãno-opã§ãã£ãŠãã€ã³ã¿ãŒãã§ãŒã¹ãç¶æããããšã§ãã
çµè«
ãªã¹ã³ãã®çœ®æååã¯ãJavaScriptã¢ãžã¥ãŒã«èšèšã«éåžžã«é¢é£æ§ã®é«ãããªããžã§ã¯ãæåããã°ã©ãã³ã°ã®åºæ¬çãªååã§ããLSPãéµå®ããããšã«ãããåå©çšæ§ãé«ããä¿å®æ§ãé«ãããã¹ãå¯èœãªã¢ãžã¥ãŒã«ãäœæã§ããŸããããã«ãããæéã®çµéãšãšãã«é²åãããããããå ç¢ã§æè»ãªã³ãŒãããŒã¹ãåŸãããŸãã
éèŠãªã®ã¯ãæ¯ãèãã®äºææ§ã§ãããµãã¿ã€ãã¯ãåºæ¬åã®æåŸ ãšäžèŽããæ¹æ³ã§æ¯ãèãå¿ èŠããããŸããã¢ãžã¥ãŒã«ãæ³šææ·±ãèšèšãã眮æã®å¯èœæ§ãèæ ®ããããšã«ãããLSPã®ã¡ãªããã享åããJavaScriptã¢ããªã±ãŒã·ã§ã³ã®ãã匷åºãªåºç€ãç¯ãããšãã§ããŸãã
ãªã¹ã³ãã®çœ®æååãçè§£ããé©çšããããšã«ãããäžçäžã®éçºè ã¯ãçŸä»£ã®ãœãããŠã§ã¢éçºã®èª²é¡ã«å¯Ÿå¿ãããããä¿¡é Œæ§ãé«ããé©å¿æ§ã®é«ãJavaScriptã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸããã·ã³ã°ã«ããŒãžã¢ããªã±ãŒã·ã§ã³ããè€éãªãµãŒããŒãµã€ãã·ã¹ãã ãŸã§ãLSPã¯ãä¿å®æ§ãšå ç¢ãªã³ãŒããäœæããããã®è²ŽéãªããŒã«ã§ãã