0

Have searched for this, but looks like I'm using the wrong terms. Mostly find things about C++, C#, node, PHP classes etc.


Say one have two modules A and B and a script main.

  • A exports farm
  • B exports print and uses A.farm
  • main imports A and B

But B depends on the same state of A.farm as main.


The way I have done this now is:

  1. main imports A
  2. main imports B
  3. B has a initialize function where it get a reference to A.farm from main.

Example:

  • A
let animal = 'donkey';
export const farm = {
    get_animal: () => animal,
    set_animal: a => animal = a
};
  • B
let farm, color;
export const initialize = env => {
    farm = env.farm;
    color = env.COLOR;
};

export const print = () => {
    console.log(
        'The', farm.get_animal(),
        'is going to be painted', color, '.'
    );
};
  • main
import {farm} from 'A';
import {print, initialize as initialize_b} from 'B';

const COLOR = 'red';
initialize_b({farm, COLOR});

farm.set_animal('cat');
print();

The cat is going to be painted red.


Is it the way to do it?

Question is if this is the way to do it? In the real project there is about 5 dependencies in B from main and 3 exports from B to main.

The code of B was initially part of main but as it can be categorized under one theme I found it better to have in a separate module + it keeps main cleaner.

It feels a bit wonky.

Earlier, in no-module-code, I have typically had a PROJECT = {} object that I include first then attach shared functions and other things trough that.

I could have a import-export module, something like:

import_export

import {farm} from 'A';
import {print, initialize as initialize_b} from 'B';

const COLOR = 'red';

initialize_b({farm, COLOR});

export {farm, print, COLOR};

Then import the exports in main. But not sure if that would be any cleaner. The import_export could end up with a lot of exports and main lot of imports.

1
  • 1
    Adding "javascript" your search terms helps in limiting the scope of your search. Commented Jul 11, 2022 at 18:30

3 Answers 3

2

Javascript supports OOP, classes etc., it seems your can use some of OOP methodologies. Instead of exporting ton of functions, you can instantiat a B object and use its methods.

Example:

A.js:

export class Farm {
    constructor(animal='donkey') {
        this.animal = animal;
    }
    get_animal: () => this.animal;
    set_animal: (a) => { this.animal = a }
};

B.js:

export class B {
    constructor(farm,  color) {
        this.farm = farm;
        this.color = color;
    }
    toString() {
        return 'The ' + this.farm.get_animal() + ' is going to be painted ' + this.color + '.'
    );
};

Main.js:

Import {Farm} from "./A.js"
Import {B} from "./B.js"

const someFarm = new Farm("cat")
const b = new B(someFarm, "red")
//invoke any B method like b.someUtil()
console.log(b) // The cat is going to be painted red.
Sign up to request clarification or add additional context in comments.

5 Comments

Yes, in real code I export objects that has functions, but in this case B still needs various data from main. Reason I use a separate initialize function is that module B exports two objects that both use the same properties passed from main.
So from B I export obj1 and obj2 which both has multiple functions and both uses the same objects and variables imported/inherited/begotten from main + some helper functions that I do not attach to the object's / classes as they are 1) private to the module, 2) used by both objects. I simplified the example code a lot.
@Smorfph So create one object in main with the things that you need to pass, and pass it to both new Obj1 and new Obj2 constructors that were imported from B.
@Smorfph And as always, if you need real help, post your real code :-)
Yeah. Thought was to simplify it to make it more generalized for other users. With the real code thought was that it became too specialized + deflect from the core question of “sharing ‘things’ with module one import”
1

Is it the way to do it?

No. But not for the structure of your imports and exports, the number of dependencies, or your modularisation in general, but rather because your modules have global state. Avoid that, or where you cannot avoid it, keep it confined in main.js.

The usual solution here is to use OOP - see @Mercury's answer for a nice implementation. Instead of storing state in global (or module-level) variable, store in objects, and provide ways to create many objects of the same kind and set up its references to other objects.

The alternative, for smaller projects and where you know you're not gonna need it, is to simply have the modules import one another directly. In test most frameworks, you still can usually provide mocks for whole modules, otherwise this would be a real annoyance. Here's a small example:

// A.js
let animal = 'donkey';
export function getAnimal() { return animal; }
export function setAnimal(a) { animal = a; }
// B.js
import { getAnimal } from 'A';
import { color } from 'settings';

export function print() {
    console.log(`The ${getAnimal()} is going to be painted ${color}.`);
}
// settings.js
export const color = 'red';
// main.js
import { setAnimal } from 'A';
import { print } from 'B';

print();
setAnimal('cat');
print();

1 Comment

Yes. I do not like the global state thing. But I really do not like it when main.js becomes too big, hence why I split it out. I can split it out and call the other module functions with more parameters, but try to avoid that as well :P, But sure. I'll have to re-factor this.
-1

import {farm} from 'A';
import {print, initialize as initialize_b} from 'B';

import {farm} from '/A.js';   /* It works by me to put a slash and .js at the end of doc name */
import {print, initialize as initialize_b} from '/B.js';

/*
const COLOR = 'red';

initialize_b({farm, COLOR});

export {farm, print, COLOR};
*/

2 Comments

Yes, I use pat/to/file.js in real code. Have no problem importing.
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.