Some time ago I learnt a lot of design-patters, specially creational ones.
After some time, I found myself using a patter that I though existed, but when I tried to search about it I didn't found any reference. Basically it is a small modification of a factory which takes advantages of the closures to resolve dependencies of a class. Actually, it is a factory of classes. Let's me illustrate this with a bit of code:
function Factory(depA,depB){
function MyClass(something){
this.something = something;
}
MyClass.prototype.methodA(){ // use depA}
MyClass.prototype.methodB(){ // use depB}
return MyClass
}
Let's assume that depA is a database and depB is a logger. Then you can use the factory like this
var BindedClass = Factory(database,logger);
var instance = new BindedClass(something);
I find this patter very useful for injecting common dependencies, without loosing the control of how the class is actually instantiated.
However, this has some problems. For example, one of the things that made me realize that this is not so common is that JSDoc does not have support at all for this kind of pattern.
Is it a bad pattern? I can't find any disadvantage on it apart from less modularization and non-working documentation tools.
Yes, it's a totally accepted pattern. However we rarely call it a "factory", more common is just "module" - in this case with dependency injection. Many module systems like AMD use this pattern.
You should however ensure that the factory produces a singleton - i.e. Factory should not be called multiple times and create multiple similar classes.
Related
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.
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?.
Hello TypeScript/Angularists!
TL;DR
Can I pass angular dependencies to a TypeScript module/class, so that those dependencies DON'T become attributes of class objects - instead, they are available through scope function parameters?
I know the recommended way of declaring things in angular/typescript is to create a TS class inside a TS module and release it as an angular service, because:
it can't be a factory (see this)
it's good to have modules
a class (comparing to a plain function) might be used to check compile-time types in typescript
An example of such approach is below:
/// <reference path="../../project.d.ts" />
module project.core.services {
export class UiRoutes {
static $inject = ['$state'];
constructor(private $state: angular.ui.IStateService) {
}
public reloadCurrentView(): void {
this.$state.go(this.$state.current.name, this.$state.params, {
reload: true
});
}
}
}
project.core.CoreModule.service('UiRoutes', project.core.services.UiRoutes);
Anyway, there is one great problem with that approach and that is - I'm forced to pass all angular dependencies into class constructor to make them object attributes (available everywhere, not encapsulated - because if the object is accessible then all it's attributes are accessible).
As an alternative, there is Backbone.js + Require.js example:
define(['jquery', 'use!backbone','models/model'], function($, Backbone, Model){
View = Backbone.View.extend({
//...
});
return new View();
});
where, as you can see, jquery, backbone and some internal stuff is available, but it's not saved as an object attribute - it's available through scope. This is purely natural JavaScript way of doing things - passing things through scope function parameters. In this situation, you can encapsulate more things and your code becomes less verbose. And, mainly, it's good to have a choice rather than to be forced to follow the only right rule.
Now I know that backbone is different than angular and, moreover, DI is totally different than require.js, blah blah blah.
What I want is a an example (or just a design) that allow me to specify all angular dependencies and make them accessible for a TypeScript module/class but not to make them attributes of class objects. This is possible with pure AngularJS (without TypeScript) afterall, so it might be possible along with TypeScript.
PS I'll happily provide better description of the problem, if it's not clear (comments, please). Buit I'm not really interested in answers like "it's not what you want, but it works for me, try this" :) if the answer is "no, that's not possible", than I'd appreciate a proof and/or reasons why.
because if the object is accessible then all it's attributes are accessible
This may be true from a runtime perspective, but the runtime perspective is not the only one that matters. If you're using TypeScript and you mark the injected services as private, then no one is accessing these things unless they're being actively malicious. And odds are extremely good that your code is already not resilient to malicious actors inside its own runtime environment (trivially, someone who wanted to screw with your app could inject in any Angular service and overwrite its properties with their own).
So in that regard, the best thing to do is to not care about what things happen to be on a object somewhere versus in a closure somewhere.
Now I know that backbone is different than angular and, moreover, DI is totally different than require.js, blah blah blah.
To expand on "blah blah blah", a relevant difference here is that your requirejs module is effectively a singleton, whereas your Angular classes usually aren't (most of them are probably controllers).
We need to go back to the object vs closure difference to understand why that matters. If you're going to have closure privacy over your injected services (because compile-time privacy wasn't good enough for whatever reason), it follows that every instance of your object is going to need its own set of subclosures to be able to access those closed-over values.
Duplicating your function closures for every single instance of an object incurs a large performance penalty when there are many instances of the object. It's more allocations, more memory pressure, more time spent cleaning up things in the GC, more time spent marking or sweeping or refcounting in the GC, less locality of reference, less efficient JIT, and so on. This is why TypeScript and other languages don't give you ready-made footguns for making closure-based classes.
Now you're saying "But my service is a singleton!" and you're right. Singletons can be written as a closure like this:
module project.core.services {
export function UiRoutes($state: angular.ui.IStateService) {
function go() {
$state.go(/* etc*/);
}
function other() { }
function foo() { }
return {
go,
other,
foo
}
}
}
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.)
Using the Google closure compiler and library for inheritance I found two different calls of super constructor in a lot of closure based libraries (forgot where I found it). Not sure if I got it wrong at all.
What is the difference and what is the correct one to use?
// Xhrio extends EventTarget
goog.events.EventTarget.call(this);
goog.net.XhrIo.base(this, 'constructor');
Either one is fine. I suppose you might say the second one is slightly better because if you later changed XhrIo to extend something other than EventTarget you might not have to change that line.
You can also use goog.base(this, 'constructor') but that is incompatible with strict mode.