Javascript - Refactor a class splitting it by concepts - javascript

I am trying to refactor (splitting by concepts) the following class:
import myService from "./myService"
...
export default function MyService() {
if (!isInstantiated) {
myService.configurate(configuration);
// Initialize Auth and Database
this.auth = myService.auth(); // myService.auth() has to be performed after myService.configurate()
this.database = myService.database(); // myService.database() has to be performed after myService.configurate()
isInstantiated = true;
}
}
MyService.prototype.methodAssociatedWithAuthConcept = function () {
...
};
... more mothods associated with the "Auth" concept
MyService.prototype.methodAssociatedWithDatabaseConcept = function (email, password) {
...
};
... more mothods associated with the "Database" concept
In a future, this class will be really big, so splitting it into other classes "Auth" and "Database" is my best option, but... myService.auth() and myService.database() has to be performed when myService.configurate(configuration) is done in the MyService constructor's singleton.
And, also, I have to be able to access Auth class and Database class from MyService class, instantiating them in the MyService singleton, in order to do:
const myServiceObj = new MyService();
myServiceObj.database.someMethodAssociatedWithDatabaseConcept();
Any ideas?

That sound like you need a factory.
Outsource your database and auth. Then write a factory that implements both of them on demand. Your factory can create a new constructor for every usecase. constructors are in fact just normal functions that call Object.create() and do some prototyping for you. Then they return the object created with Object.create(). But you can handle that totally by your own. So adding diffent calls in your constructor is easy.
Give your factory standard methods for accessing auth and database.
import your database and auth on demand
export an new generated class with all functions you need for your database and/or auth

Related

Registering service with constructor arguments using tsyringe

I have a service to handle some data-fetching and I am trying to use tsyringe with it, the function to create the service gets called multiple times (i cant really do anything about that), so it is creating many instances of the service. I tried to wrap it in "container.isRegistered" checks, but when I do that it doesn't register the service at all.
What I have so far is:
#singleton()
#injectable()
export class Service implements IService {
constructor(#inject('arg1') arg1: string, #inject('arg2') arg2: string) {
}
Then I am registering it here in another file:
if (!container.isRegistered('arg1', true)) {
container.register('arg1', {useValue: this.arg1});
}
if (!container.isRegistered('arg2', true)) {
container.register('arg2', {useValue: this.arg2});
}
if (!container.isRegistered('IService', true)) {
container.register('IService', {useClass: Service});
}
In another file I resolve it like so:
this.service = container.resolve('IService');
Trying to check if it is registered stops the Service from being registered at all, but if I don't I have multiple instances running. The service mainly handles data-fetching, it's only supposed to fetch some data once on startup but I am seeing many calls that do so. I put some logs in the service constructor and I can see it being created many times.
Thanks for your help!
When you are creating new registry in IoC using method register, in fact you create another link on service that doesn't related to your decorator #singlton inside of class. You need set additional parameter in the register method. It will describe lifecycle of injectable object. Because be default it doesn't use Singleton. You should do this like that:
import { container, autoInjectable, Lifecycle } from 'tsyringe';
...
container.register<UsersService>('IService', {useClass: UsersService}, { lifecycle: Lifecycle.Singleton } );
More info here and types here

What is the difference if use Subject over a Get Service method in Angular?

I have a service and I have 2 solutions from this kind of problem and I want to know what is best and when to use the Subject solution above the Service solution.
I have a UserModel that all my components see with my service, the approach that I want is when I change the UserModel from service, changes it for all my application
1 FIRST SERVICE
export class UserService {
private userModel: UserModel = new UserModel();
public userSubject$ = new Subject<any>();
private timeOut = 20000;
private mainConfig: MainConfig;
constructor(private http: HttpClient) {
this.mainConfig = new MainConfig();
}
getUserModel() {
return this.userModel;
}
setUserModel(user) {
this.userModel = user
}
}
And is just to make this call in my HTML from all my components and will work
this.userService.getUserModel().name
The second approach
2 SECOND SERVICE
#Injectable()
export class UserService {
private userModel: UserModel = new UserModel();
public userSubject$ = new Subject<any>();
private timeOut = 20000;
private mainConfig: MainConfig;
constructor(private http: HttpClient) {
this.mainConfig = new MainConfig();
}
getUserModel() {
return this.userModel;
}
setUserModel(user) {
this.userSubject$.next(this.userModel = user);
}
}
And in my HTML file, I just use
{{ userModel.name }}
And I must make this new line on my example-component.ts
ngOnInit
this.subTemp = this.userService.userSubject$.subscribe(
user => this.userModel = user
);
ngOnDestroy
this.subTemp.unsubscribed();
What is the advantage to make the Subject from direct from Service? Because I need to make much more work
If I could paraphrase your question(s), I'm guessing it'd go something like:
Why should I use Angular Services instead of just making async/http calls directly from the component?/Why should I write Service logic in a separate file as a dependency?
and
Why should I use lifecycle methods like ngOnInit and ngOnDestroy in conjunction with Services or async/http calls?
When it comes to questions like these, the Angular framework is more opinionated than other SPA technologies like React, Vue, etc. So while you're not technically forced to follow either of the approaches you listed, you should know of the downsides and problems that emerge if you follow the first approach rather than the traditional injectable Service approach(number 2).
Generally speaking, the Angular team recommends following a unidirectional data flow pattern in your app implemented with Services. This means that data flow should generally come from Services which distribute the data to components and then to view templates.
Within this pattern, there's also an implication of separation of concerns which is a good practice to follow within any app. Services should handle fetching and handling data, components should handle view logic, and templates should be as clean and declarative as possible. Components and their templates should consume data that's been processed already. Relatedly, you should try to keep your components as pure as possible - meaning they produce as few side effects as possible. This is because components are dynamically mounted and unmounted in the course of a user session. Have a look at this article for more information on pure components.
Aside from the above architectural discussion of Services there are some other, more concrete consequences to be aware of:
Failure to unsubscribe from observables can lead to memory leaks in your application. With the first scenario you've outlined above, a component may be loaded 10-20 times in a user session and each time you're setting up a new subscription without tearing it down again. This can have a very real performance impact on your app.
The Angular compiler is optimized to add and remove dependencies dynamically, resulting in better app performance. If you keep all your Service code right in your component, they'll be larger and slower. From a UX perspective, components should be as light and nimble as possible so they can load quickly for the user.
If you register a service as a provider, the Angular compiler will treat it as a singleton meaning there can be only one instance of it. This is as opposed to the many instances of a Service class generated with each component if you were to use the first approach you listed. This is another performance benefit of using injectable Services.
The Angular compiler is optimized to work with the DI framework so your next step may be to learn more about it and the implications of going with one approach or the other. There's a long talk about creating your own Angular Compiler that's a couple years old now that might be helpful.
What you wish to know is the difference between pull based method vs push based method of retrieving data.
Method 1: pull based
As the name suggests the pull based method is traditional method where you for eg. call a function and it returns the value once. If you need the value again, the function should be called again. And you exactly when the data will arrive.
export class UserService {
private userModel: UserModel = new UserModel();
getUserModel() {
return this.userModel;
}
setUserModel(user) {
this.userModel = user
}
}
some.component.ts
export class SomeComponent implements OnInit {
userModel: UserModel;
constructor(private _userService: UserService) { }
ngOnInit() {
// It's a one time call and you control when you get (or `pull`) the data
this.userModel = this._userService.getUserModel();
}
}
Method 2: push based
Here the observable decides when you receive the data. This is the basic of reactive/asynchronous data flow. You subscribe to the data source and wait till it pushes the data. You have no knowledge when the result might arrive.
#Injectable()
export class UserService {
public userSubject$ = new Subject<any>();
getUserModel() {
return this.userSubject$.asObservable();
}
setUserModel(user) {
this.userSubject$.next(this.userModel = user);
}
}
some.component.ts
export class SomeComponent implements OnInit, OnDestroy {
userModel: UserModel;
closed$ = new Subject<any>();
constructor(private _userService: UserService) { }
ngOnInit() {
// The stream is open until closed and the service/observable decide when it sends (or `pushes`) the data
this._userService.getUserModel().pipe(
takeUntil(this.closed$) // <-- close the `getUserModel()` subscription when `this.closed$` is complete
).subscribe(
userModel => { this.userModel = userModel }
);
}
ngOnDestroy() {
this.closed$.next();
this.closed$.complete();
}
}
Angular uses observables extensively due to the nature of data flow in a typical web-application and the flexibility it provides.
For eg. the HTTP client returns an observable that you can latch on to and wait till the server returns any information. And the RxJS provides numerous operators and functions to refine and adjust the data flow.

Javascript/Express - Exports all methods vs exporting class containing methods

I am confused while encountering this over-looked question like how they are different ?
Module.exports = {
search_companies(req, res) {
//some ops
},
get_details(req, res) {
//some ops
}
};
vs
class MainContrller {
search_companies(req, res) {
//some ops
},
get_details(req, res) {
//some ops
}
}
module.exports.MainController = MainController;
The first one exports an object with the function search_companies and get_details. So you can call these to function on the object that is exported.
The second one exports a class MainController with the functions search_companies and get_details. Here you have to create an instance of MainController to be able to call those two functions on the instance.
You use the first syntax if you only need one instance of that object through the whole project. It's like a singleton or like static, but without the need to define an actual class for it.
And you use the second one if you need multiple different instances of MainController.
A module is supposed to be used like:
const { search_companies } = require('...');
A class is supposed to be used like:
const { MainController } = require('...');
const { search_companies } = new MainController();
MainController in this case is a bad practice because it mimics the usage of classes in other languages without taking the specifics of JavaScript into account.
MainController doesn't benefit from being a class if this instance is ignored and doesn't lose in functionality when a class is refactored to separate functions.
Classes aren't glorified namespaces in JavaScript; there are modules that already serve this purpose. If there's a need for a namespace and no need for class instance, a module can be used as a rule of thumb.

Using ES6 classes OR Object Literals in controllers for an Express + NodeJS app

There are 2 things that I'm very confused about.
What is the advantage of using any of ES6 class or Object literals.
And where should I use any of them?
Some of the examples that I'm trying out are mentioned below. Please let me know when to use particular way of implementation and when not to.
Class Example 1:
// auth.js
class Auth {
login(req, res) {...}
signup(req, res) {...}
}
module.exports = new Auth();
// index.js
const auth = require('auth');
Class Example 2:
// auth.js
class Auth {
login(req, res) {...}
signup(req, res) {...}
}
module.exports = Auth;
// index.js
const Auth = require('auth');
const auth = new Auth();
Object Literal Example:
// auth.js
module.exports = {
login: (req, res) => {...},
signup: (req, res) => {...}
};
// index.js
const auth = require('auth');
What I think from reading about them is that:
Class Example 1:
You can not create more than 1 object. Because a module is only executed once. So, on every import you will get the same object. Something similar to singleton. (Correct me here if I misunderstood it)
You will not be able to access the static methods of the class because you are only exporting the object of the class.
Class Example 2:
If you have a class that contains nothing but helper methods and the object does not have any state, It makes no sense creating object of this class all the time. So, in case of helper classes, this should not be used.
Object Literal Example:
You can not do inheritance.
Same object will be passed around on every require. (Correct me if I'm wrong here as well)
Please help me understand these concepts, what I'm missing out, what I've misunderstood and what should be used when and where. I'll be very grateful for your help.
Feel free to edit the question, if you think I made a mistake somewhere.
Class Example 1: You can not create more than 1 object. Because a module is only executed once. So, on every import you will get the same object. Something similar to singleton.
Correct. This is an antipattern therefore. Do not use it. class syntax is no replacement for object literals.
You will not be able to access the static methods of the class because you are only exporting the object of the class.
Theoretically you can do auth.constructor.… but that's no good.
Class Example 2: If you have a class that contains nothing but helper methods and the object does not have any state, It makes no sense creating object of this class all the time. So, in case of helper classes, this should not be used.
Correct. Use a simple object literal instead, or even better: multiple named exports instead of "utility objects".
Object Literal Example: You can not do inheritance.
You still can use Object.create to do inheritance, or parasitic inheritance, or really anything.
Same object will be passed around on every require.
Correct, but that's not a disadvantage. If your object contains state, you should've used a class instead.
If your class has got a constructor, you can build several objects from this class threw :
var Panier= require('./panier');
var panier1 = new Panier(13, 12, 25);
var panier2 = new Panier(1, 32, 569);
Of course your Panier would be defined in the file Panier.js located in the same directory :
module.exports = class Panier
{
constructor(code, qte, prix)
{
this.codeArticle = code;
this.qteArticle = qte;
this.prixArticle = prix;
}
getCode()
{
return this.codeArticle;
}
getQte()
{
return this.qteArticle;
}
getPrix()
{
return this.prixArticle;
}
}

Export objects vs functions NodeJs

Export Objects {} vs Export function
I'm developing an exercise application, I came across to the question When do I need to exports an object {} instead of a function class?
Scenario example:
I'm building a simple authentication module using the object style.
// file auth.js
module.exports = {
login: function() {
// code login
},
logout: function() {
// code logout
},
register: function() {
// code register
}
}
Here I'm using the anonymous function style
module.exports = function() {
return {
login: function() {
// code login
},
logout: function() {
// code logout
},
register: function() {
// code register
}
}
}
Requiring
When I want to require this module I just do:
var auth = require('auth');
auth.login(); // trigger login function via object
auth().login() // trigger login function via function
It will work with both the approaches, but I'm confused to choose which fit better and why.
Questions
How do you understand in your design of a module, when is appropriate to exports, an object, anonymous function, named function to Instantiate?
Which are the difference and how the require method behave, when requiring these functions or Objects ?
How do you understand in your design of a module, when is appropriate to exports, an object, anonymous function, named function to Instantiate?
true minimalists aim to export a single function if that will suffice. This is based on the scope of your module and assumes a small and focused purpose.
Export an object of related functions when you need a set of functions to have a meaningful set of functionality. For example, a tempConversion module might have both cToF and fToC functions.
If you are doing OO, exporting the constructor function is fine.
a closure function that returns the real payload (which can be an object or a function) is useful for configuration options. For example var tip = require('computeTip')(18); could store 18 in closure and return a function that would calculate 18% tip when called with a number.
Here's a rule of thumb: if you export only one named function a la require('average').average(listOfNumbers), it's redundant, so just export the average function directly to make it more concise. If you have more than one function you want to expose, use an object whose properties are the functions.
Which are the difference and how the require method behave, when requiring these functions or Objects ?
There are no differences. require has a single behavior that accommodates each of these techniques.
In both your examples you actually return an object and not a function class. In the second case you get the object by executing the function. In order to use the function as a class you should return a function which acts as the constructor, and then instantiate with the new operator.
That being said, I would prefer an object over a class if I consider my module as a singleton, something that would be common to every file that would include it. An example would be a module that implements a common access layer to my database.
A class makes more sense if you intent to instantiate it multiple times. An example would be a specific model class for your database schema, like a User class.

Categories