Reputation: 2552
I'm having a very hard time writing modules that are comprised of typically 3-5 smaller modules or classes. The issue arises when these sub components need to be extended, but the main module is already creating and implementing their base versions.
Example
// main module design
class Car {
constructor() {
this.horn = new Horn();
this.horn.on('honk', function() {
console.log('honked');
})
}
}
class Horn {
constructor() {
this.sound = 'hornA.wav'
}
}
// extended module design
class RaceCar extends Car {
constructor() {
super();
this.horn = new RaceHorn();
// event handler is now missing
}
}
class RaceHorn extends Horn {
constructor() {
super();
this.horn = 'hornB.wav'
}
}
This is indeed a very simplified example, while my true issues involve modules with more components and more setup requirements. I do understand that I can put things into another init
or setup
or similar function, but to me it seems like I'm doing something wrong inherently.
Upvotes: 1
Views: 38
Reputation: 2034
I heavily suggest passing the values through parameters, for what concerns this issue. Default parameters can help a lot
// main module design
class Car {
constructor( parametrizedHorn=Horn ) {
this.horn = new parametrizedHorn();
this.horn.on('honk', function() {
console.log('honked');
})
}
}
class Horn {
constructor() {
this.sound = 'hornA.wav'
}
}
// extended module design
class RaceCar extends Car {
constructor() {
super( RaceHorn );
}
}
class RaceHorn extends Horn {
constructor() {
super();
this.sound = 'hornB.wav'
}
}
This can get very messy, so instead you can use initialization methods
// main module design
class Car {
constructor() { ... }
init( hornType=Horn ){
this.initHorn( hornType );
}
initHorn( hornType=Horn ){
this.horn = new Horn();
this.horn.on('honk', function() {
console.log('honked');
})
}
}
class Horn {
constructor() {
this.sound = 'hornA.wav'
}
}
// extended module design
class RaceCar extends Car {
constructor() {
super();
}
init( hornType=RaceHorn ){
this.initHorn( hornType );
}
}
class RaceHorn extends Horn {
constructor() {
super();
this.sound = 'hornB.wav'
}
}
const raceCar = new RaceCar();
raceCar.init();
These are two modular patterns that you can use, and depending on the kind of structure you're already using, you can judge which one is best. The trick in the end is to parametrize the contents of your class, or modularize it even further with methods
Upvotes: 1