Can you recommend any great learning resources on inversify in typescript?
I have looked at http://inversify.io/ and have followed the example but am not grasping how it really works or why I need it.
A great video learning resource would be great or a simple easy beginner example.
Thanks for the help.
The idea of Inversion Of Control, aka dependency injection is that a class hands over control (read: responsibility) for instantiating dependent instances that the class needs to the container that will provide them with these instances instead.
So you would not do something like:
public constructor() {
this._katana = new Katana();
this._shuriken = new Shuriken();
}
I am not going to give a full example, because I would basically be copy-pasting the code that they clearly share on their website in the section 'The Basics'.
They give an example of constructor injection:
public constructor(
#inject(TYPES.Weapon) katana: Weapon,
#inject(TYPES.ThrowableWeapon) shuriken: ThrowableWeapon
) {
this._katana = katana;
this._shuriken = shuriken;
}
This is specifically useful for:
Testing, since the dependent object can be mocked and injected
Injecting dependent objects based on variable parameters.
For example, depending on environment you may want to inject a different configuration object with different values. This is just one example.
Constructor injection is usually preferred over property injection, as the library also seems to support this.
Note that what is injected is an interface, not a concrete class type.
So the class just declares that it needs an object of type Weapon / ThrowableWeapon.
The concrete binding happens in inversify.config.ts:
container.bind<Weapon>(TYPES.Weapon).to(Katana)
So the reason why this is useful is that you have the ability to provide concrete classes at runtime. You don't need to pre-define (hardcode) them in the class.
Related
I have created a class to interact with my database:
class MyDatabase {
connect() { /* ... */ }
}
And the database has two types of modes: admin and client. I would like to have different classes for each mode:
class MyDatabaseAdmin {}
class MyDatabaseClient {}
Both of them will implement the same interface, but with different underline implementations. I would like to know if there is a design pattern to instantiate the parent MyDatabase choosing one over the other. Something like:
const db = new MyDatabase({ mode: 'admin' })
db.connect() // parent calls MyDatabaseAdmin.connect
I don't need a perfect answer, just some direction to what I should search for.
Thanks.
If they have no code in common, then they are really just two separate classes. You probably don't even want the admin code to be present in the browser since it can't be used there anyway.
You could have a single factory function that looks at an admin parameter and instantiates the appropriate database object and returns it, but I don't think I even see why you'd bother with that.
Just have each client instantiate the appropriate DB object. If there's any common code, you can have both implementations inherit from a common base and put the common code in the base class.
Right! I forgot to mention, but there are some common code... the connection and authentication is exactly the same, for example. Do you happen to know any design pattern that would perfect fit for this use case? Should I research about Factories?
I think a common base class with inheritance solves the problem here. It gives you a natural place to put the common code without having to include server-side code in the client implementation. The browser implementation and the server implementation would each be a subclass that are present only on their respective platforms. The common base class would be present and used in both places.
You just have the client instantiate the appropriate leaf class and the shared code lives in the base class. If you want to hide the actual class constructors, you can use a factory function (it's just a simple function that looks at conditions and makes an appropriate object for you and returns it), but I'm not sure there's any compelling reason to use a factory function here. You would only include the appropriate leaf class on the platform for which it is intended so there's no place where you might use one or the other in the same code.
would you consider having only 'users'? then each user could have a 'role' that would be either 'user' or 'admin'. So based on that 'role' you will define the privileges for each user. I find this solution easier for this kind of stuff but let me know if it does not match your case.
I recently watched tutorial of my teacher, and he show us this code:
And he also said products array which is type of any [] IS NOT USING BENEFITS OF STRONGLY TYPE which is feature of TypeScript so it should be defined as INTERFACE, but I'm wondering now, why he did not create a class and that products array might be of that class type??
He said Interfaces purpose is to provide strongly typing and tooling support..
So he wrote this interface:
So I'm wondering why he did not create a class like :
export class Product .. and later he would use products : Product [] ..
So basically I can not figure out why is Interface as dataType better here instead of class?
Sorry for screenshots and not real code, that's because he hosted online video lessons..
Thanks
Check this text writen by James Henry maybe that will clarify you this issue. In short: Unlike classes, interfaces are completely removed during compilation and so they will not add any unnecessary bloat to our final JavaScript code.
Think of interfaces as a blueprint for your object — a brief set of instructions that guarantees that a certain set of fields / methods will be available on objects tagged with that interface. They provide you with a means of taking advantage of strong typing while keeping your code as lightweight as possible. As mentioned, the interface is removed and compile time because it doesn’t actually have any programmatic implications — it’s strictly to make the code less error-prone and easier to work with for you and whoever else.
If you need to specify implementation details, such as getter / setter / constructor logic or methods, that’s when you would use a class. In fact, if the logic for the calculateDiscount() method in your example is expected to remain the same across all Products, it’s possible that a class could make more sense in this case.
Classes can work as interfaces in TypeScript. Interfaces cannot work as classes. One of them can be chosen based on the principle of parsimony.
Things like
class SomeProductClass implements ProductClass {...}
and
const plainProduct: ProductClass = {...};
happen often.
However, when a class is defined, it's expected that it or its descendant will be instantiated. If it won't, this would be misleading, because this is what interfaces are for.
It's common in Angular to define abstract class that won't be instantiated, but that's because abstract classes can be used as both interfaces and dependency injection tokens.
I have a class that extends HTMLElement. From reading this thread
https://github.com/Microsoft/TypeScript/issues/574#issuecomment-231683089
I see that I can't instantiate a custom element with out getting a Illegal constructor. Additionally, the registerElement looked promising as it returned the constructor for the custom element but that is now deprecated for using CustomElementRegistry.define() that 1. exists on the window object and 2. returns void. Any solutions will be greatly appreciated thank you.
for this particular setup I am attempting to use native custom elements as opposed to a web component framework because I only need custom elements. Also, I am using TypeScript and attempting to use Jest to test it.
Depending on what extactly your element is doing you could consider to take the design principles "separation of concern" and "inversion of control" into account.
Separation of concern would be achieved when different things are implemented in different classes. This would also mean that the separated things can be tested without instantiating a concrete HtmlElement.
Inversion of controll comes in handy at this Point because if the dependencies of the separated classes (probably the HtmlElement) are settable from outside of the class, you can easily stub or mock the HtmlElement by giving a stub to the test-instance.
The idea is to design your code in a way that it is independent of things that are not accessible or controllable in unittests.
My experience is with statically typed languages, and I must admit that I feel lost when trying to achieve the same with dynamic languages. One of the things that I would like to avoid, is apply concepts that don't make sense in this context. Please, assume that this class belongs to my project and that we want to test it with Jasmine:
class MyEs6Class {
constructor(
collaborator1 = new MyCollaborator(),
factory = new MyFactory()) {
this.collaborator1 = collaborator1;
this.factory = factory;
}
method() {
// Code
}
}
I'm providing default instances of the objects in the constructor because that allows me to mock them when testing. I'm trying to use inversion of control in the same way that I would use with, let's say C#, but using the dynamic features of the language to avoid a Dependency Injection container. These two dependencies are required by the class, so from the structural point of view, I think is very clear that they must be provided using the constructor.
Also, I'm using the concept of a factory only because while the class is 'alive' can require new objects from the factory several times.
From the point of view of ES6 classes, I know that there is no difference between private and public (https://stackoverflow.com/a/27853642/185027), so I could have the logic handled by the factory in a private method, but depend on him testing seems just wrong. On the other side having something called factory just because I need to fake the objects that returns seems weird, and maybe is screaming my lack of knowledge.
What is the proper way to mock collaborators in this context?.
Is it silly to have the concept of a factory only because I need to mock the object that returns?.
What would be a maintainable and elegant way of isolating the subject under test in Javascript/ES6?. Any interesting public codebase that I can study?.
Coming from a C# background, I used interfaces to base my mock objects off of. I created custom mock objects myself and created the mock implementation off a C# interface.
How do you do something like this in JS or node? Create an interface that you can "mock" off of and also the interface would serve for the real class that would also be able to implement that interface? Does this even make sense in JS or or the Node World?
For example in Java, same deal, define an interface with method stubs and use that as the basis to create real class or mock class off of.
Unfortunately you're not going to find the standard interface as a part of JavaScript. I've never used C#, but I've used Java, and correct me if I'm wrong, but it looks like you're talking about creating interfaces and overriding methods for both mock testing purposes, as well as being able to implement those interfaces in other classes.
Because this isn't a standard JavaScript feature, I think you'll find that there are going to be a lot of very broad answers here. However, to get an idea of how some popular libraries implement this, I might suggest looking at how AngularJS looks at mock testing (there are many resources online, just Google it. As a starting point, look at how they use the ngMock module with Karma and Jasmine.)
Also, because of JavaScript's very flexible nature, you'll find that you can override any sort of "class method" (that is, any function object that is a member of another object, whether that be a new'ed "class" or a plain object) by simply re-implementing it wherever you need to... there's no special syntax for it. To understand where and how you would accomplish this, I'd suggest looking from the ground up at how JavaScript using prototypal/prototypical inheritance. A starting point might be considering an example like this:
function Cat(config) {
if(typeof config !== 'undefined') {
this.meow = config.meow; // where config can possibly implement certain mock methods
}
}
Cat.prototype = {
this.meow = function() {
// the meow that you want to use as part of your "production" code
};
};
var config = {};
config.meow = function() {
// some mock "meow" stuff
};
var testCat = new Cat(config); // this one will use the mock "Cat#meow"
var realCat = new Cat(); // this one will use the prototype "Cat#meow"
In the above example, because of how JavaScript looks up the prototype chain, if it sees an implementation in the class itself, it'll stop there and use that method (thus, you've "overridden" the prototype method). However, in that example, if you don't pass in a config, then it'll look all the way up to the prototype for the Cat#meow method, and use that one.
TL;DR: there's not one good way to implement JavaScript interfaces, especially ones that double as mocks (there's not even a best way to implement dependency injection... that's also a foreign concept to JavaScript itself, even though many libraries do successfully implement it for cetain use-cases.)