What technique I'm applying to reduce code? - javascript

What kind of programming technique am I applying when I call an Object inside a Object to extend the object?
On my Job, we have a rule that no JS file may have more 50 lines. So when we have an very large Object we separate the code on new child objects but work as single Object:
function ObjetoA(parent){
parent.showMessage() = function () {
console.log('HOLA MUNDO');
}
}
function Objeto(){
new ObjectoA(this); //this one
this.sayHiAgain() = function () {
console.log('HOLA MUNDO OTRA VEZ');
}
}
let Prueba = new Objecto();
Prueba.showMessage();// it works

Let's see what's going on:
When you call Objeto(), the code new ObjetoAA(this) is run.
Now, ObjetoAA(parent) is run, which sets the property showMessage on parent. This property is a function. So now the Objecto has a function property showMessage.
I don't think there's any particular name for this pattern in the way that you've implemented it. It's just... using objects. I will say that it's an inventive way to extend/modify/split/compose a class. It's sort of simulating a mixin.
But it shouldn't be necessary: look at the gymnastics you've had to go through just to meet an arbitrary line count limit. Did it improve your productivity? Did it improve the readability and maintainability of your code? Nope.
Some limit probably makes sense: nobody wants to scan through 30,000 lines of JavaScript in a single file (at least, not the unminified version); but 50 is a very, very small limit. I recommend that you push back on this policy if you can.

Related

Is creating a function to do a small repeated task an anti-pattern?

I am trying to learn best practices for programming and want to keep my code as clean as possible, but also maintainable. For example, I am running a program that waits for each element to be created.
a.waitForElementToAppear(50000);
b.waitForElementToAppear(50000);
c.waitForElementToAppear(50000);
Now, I added a function so I can easily change the 50000 without having to manually edit each one:
function waitForElement(element) {
element.waitForElementToAppear(5000);
}
and have changed the above code to:
waitForElement(a);
waitForElement(b);
waitForElement(c);
Is it an anti-pattern to create a new function to call for a relatively small task? Is there a better approach?
Is it an anti-pattern to create a new function to call for a relatively small task?
No, it is absolutely fine! Although you're right that your function is so small that it hardly gains anything.
Is there a better approach?
To achieve your goal of easily changing the shared argument value, you could alternatively (not necessarily "better") also put it in a variable:
const time = 50000;
a.waitForElementToAppear(time);
b.waitForElementToAppear(time);
c.waitForElementToAppear(time);
Last but not least, that code still is a bit repetitive. Another option would be a loop (although those three items are just about the threshold for a loop being sensible):
for (const element of [a, b, c]) {
element.waitForElementToAppear(5000);
}

Conditional data structure (object) access

I have a set of JavaScript functions that handle certain objects. All these objects have the following flexibility:
Fields can be accessed like this: data[prop][sub-prop][etc.], OR
Like this (with a type sub-structure): data[TYPE][prop][sub-prop][etc.].
The object is accessed in many places, and the condition (let's call it is_mixed) is relevant everywhere.
I thought of the following alternatives:
Always access data like this: (is_mixed ? data[TYPE] : data)[prop][sub-prop][etc.]
Have a function called getData and always access data like this: getData()[prop][sub-prop][etc.].
The function code would be:
function getData() { return is_mixed ? data[TYPE] : data; }
Run the following on every new input: if (is_mixed) { data = data[TYPE]; }
It seems to me that options 2 and 3 might be copying the object data (which might be big) and performance is important here (I didn't find the literature to support this guess), but option 1 will make the code big and ugly.
Is there a better option? What's the best way to acheive this in terms of performance, code quality and basically best practices?
It seems to me that options 2 and 3 might be copying the JSON content
No, they won't. They both just copy an object reference, which is quick and cheap (like copying a boolean). #2 is of course slightly slower, since it's a function call, but if it's used a lot, any decent JavaScript engine will inline the function anyway, giving you the benefit of modularity at the source level. (It can take thousands of calls to the function in a shortish period of time to make that kick in, though; e.g., a modern engine only bothers with optimization when it looks likely to matter.)

Scenarios for Re-using Variables within the Same JavaScript Function: Always a No No?

I've just finished writing a script for parsing csv data. Having recently installed JShint, it's been badgering me about the re-use of variables. I've been using JS a fair bit lately, but I come from a python background where it's normal to reuse variables. I'm wondering what issues there are with reusing variables in the following two examples:
Loop with a Switch
The following loop steps through the rows on a csv file, and when it passes a certain value in a row, it switches variable "currentSwitch" from false to true. After currentSwitch is tripped, the loop starts to push stuff to an array.
for (f=0; f < data.length; f++){
if (data[f][0] === code){
if (currentSwitch === true){
dataListByCode.push(data[f]);
}
}
else if ((data[f][0]).slice(0,4) === "UNIN"){
var currentSwitch = true;
}
}
Processing Data with Broken Out Functions
I've got a few functions for processing data that it makes sense to keep separate. In the following code, I process with one function, then I process with another.
var dataListByCode = addDivideData(dataListByCode);
var dataListByCode = addBeforeEntriesArray(dataListByCode, invNumber, matterNumber, client, workType);
Can anyone tell me if this is not in line with best practice? Is there anything that could go wrong with either of these (or scenarios like them)?
You don't need to redeclare currentSwtich
var currentSwitch = true;
In fact it really doesn't make any sense to redeclare this variable in the middle of the loop and in most cases it's almost certainly not what you actually want.
Just initialize/declare it once at the beginning of your loop
var currentSwtich;
// or
var currentSwitch = false;
and drop the var when you set it to true:
currentSwitch = true;
Basically what you are doing is creating a brand new variable with the same name as the old one, and throwing away the old one. This isn't really what you want normally.
There is no analogous concept in python because python doesn't require you to declare variables.
The major problem with reusing variables is that:
a.) in bigger code blocks it can get very confusing, especially if you added/removed code ~20 times, and kept reusing same ~5 variables for multiple things
b.) any programmer that knows nothing about code(read: you after couple months/years) will have a much more difficult time grasping the code.
The lower function snippet can be expressed as:
var dataListByCode = addBeforeEntriesArray(addDivideData(dataListByCode), invNumber, matterNumber, client, workType);
which is not that problematic. The breaking up of functions is useless in this case, and if you have many inline function chains that is usually sign that you need to rethink the object/function design.

OOP - Is it better to call functions from within other functions, or to have one big controller?

I'm re-writing a fairly complex script that I created a few weeks ago. After showing it to a few people, they all agreed that I should break it up into smaller pieces (classes) that have a specific purpose, and SOLID object-oriented programming principles
As a self-taught programmer these concepts are pretty new to me, and I'm a little confused about how to best transfer data from one function/class to another. For instance, here is a simplified structure of what I'm building:
MY QUESTION IS:
Should I have a "controller" script that calls all of these functions/classes and passes the data around wherever necessary? Is this where I would put the for loop from the diagram above, even though it would work just as well as part of Function 1 which could then call Function 2?
Without a controller/service script you'll not be able to meet single responsibility principle in fact. Here's a high level design I'd implement if I were you.
FileRepository
Should expose a method to get a file. Let's name it GetFileById.
MongoDBRepository
Methods for CRUD operations. Such as SelectById, SelectByQuery, Update, Create, Delete.
Object creation logic
If your createNewObj logic is simple it would be enough to move it to your object contructor so that your code looks like that: var newObj = new MyObj(json[i]);
But if it's relatively complex maybe because you use some third party frameforks for validation or whatever you'd better create a factory. Then you could would look this way: var newObj = MyObjFactory.Create(json[i]);
Service/controller
Finally you'll need to implement controller/service object. Let's name it WorkService with a method DoWork which should handle all interactions between the repositories and other objects discribed above. Here's approximately DoWork should look like:
function DoWork(fileId){
var json = fileRepository.SelectById(fileId);
for(var i=0;i<json.length;i++){
var newObj = new MyObj(json[i]); // or calling factory method
var dbRecord = MongoDBRepository.SelectByQuery(newObj.name, newObj.date);
if(dbRecord){
MongoDBRepository.Update(newObj);
}
else{
MongoDBRepository.Create(newObj);
}
}
}
Please note it's just a javascript syntax pseudo-code. Your actual code might look absolutley different but it gives your a feeling of what kind of design your should have. Also I exmplicitly didn't create a repository objects inside DoWork method, think of the way to inject them so you meet Dependency inversion principle.
Hope it helps!

Measuring pollution of global namespace

Background
I'm trying to refactor some long, ugly Javascript (shamefully, it's my own). I started the project when I started learning Javascript; it was a great learning experience, but there is some total garbage in my code and I employ some rather bad practices, chief among them being heavy pollution of the global namespace / object (in my case, the window object). In my effort to mitigate said pollution, I think it would be helpful to measure it.
Approach
My gut instinct was to simply count the number of objects attached to the window object prior to loading any code, again after loading third-party libraries and lastly after my code has been executed. Then, as I refactor, I would try to reduce the increase that corresponds to loading my code). To do this, I'm using:
console.log(Object.keys(window).length)
at various places in my code. This seems to work alright and I see the number grow, in particular after my own code is loaded. But...
Problem
Just from looking at the contents of the window object in the Chrome Developer console, I can see that its not counting everything attached to the object. I suspect it's not including some more fundamental properties or object types, whether they belong to the browser, a library or my own code. Either way though, can anyone think of a better and more accurate way to measure global namespace pollution that would help in refactoring?
Thanks in advance!
So after some of the comments left by Felix Kling and Lèse majesté, I have found a solution that works well. Prior to loading any libraries or my own code, I create the dashboard global object (my only intentional one) and store a list of objects attached to window via:
var dashboard = {
cache: {
load: Object.getOwnPropertyNames(window)
}
};
Then, after I load all of the libraries but prior to loading any of my own code, I modify the dashboard object, adding the pollution method (within a new debug namespace):
dashboard.debug = {
pollution: (function() {
var pollution,
base = cache.load, // window at load
filter = function(a,b) { // difference of two arrays
return a.filter(function(i) {
return !(b.indexOf(i) > -1);
});
},
library = filter(Object.getOwnPropertyNames(window), base),
custom = function() {
return filter(Object.getOwnPropertyNames(window),
base.concat(library));
};
delete cache.load;
pollution = function() {
console.log('Global namespace polluted with:\n ' +
custom().length + ' custom objects \n ' +
library.length + ' library objects');
return {custom: custom().sort(), library: library.sort()};
};
return pollution;
}())
};
At any point, I can call this method from the console and see
Global namespace polluted with:
53 custom objects
44 library objects
as well as two arrays listing the keys associated with those objects. The base and library snapshots are static, while the current custom measurement (via custom) is dynamic such that if I were to load any custom javascript via AJAX, then I could remeasure and see any new custom "pollution".
The general pattern you've selected works OK from experience. However, there are two things you might need to consider (as additions or alternatives):
Use JsLint.com or JSHint.com with your existing code and look at the errors produced. It should help you spot most if not all of the global variable usage quickly and easily (you'll see errors of 'undefined' variables for example). This is a great simple approach. So, the measurement in this case will be just looking at the total number of issues.
We've found that Chrome can make doing detection of leaking resources on the window object tricky (as things are added during the course of running the page). We've needed to check for example to see if certain properties returned are native by using RegExs: /\s*function \w*\(\) {\s*\[native code\]\s*}\s*/ to spot native code. In some code "leak detection" code we've written, we also try to (in a try catch) obtain the value of a property to verify it's set to a value (and not just undefined). But, that shouldn't be necessary in your case.

Categories

Resources