RMMV Why is/Is it bad to add functions to native classes?

Status
Not open for further replies.

bishiba

Adept
Veteran
Joined
Apr 6, 2016
Messages
277
Reaction score
161
First Language
Swedish
Primarily Uses
N/A
Yeah, I asked this on actual JS forum and just got ****... Which is quite sad, because I am relatively thick skinned. But others might not be, so next time they are about to do things that are bad, they won't ask and they'll just make ****ty code :/ Regardless, I've been adding a very small amount to various native objects. Here are the ones I've made:

The Array class.
JavaScript:
Array.prototype.remove = function(n) {
    this.splice(n, 1);
};

Array.prototype.removeEmpty = function() {
    for (var i = 0; i < this.length; i++) {   
        if (!this[i]) {
            this.remove(i);
            i--;
        }
    }
};

The Math class.
JavaScript:
Math.floorRandom = function(x) {
    return Math.floor(Math.random() * x);
}

Math.roundRandom = function(x) {
    return Math.round(Math.random() * x);
}

Math.ceilRandom = function(x) {
    return Math.ceil(Math.random() * x);
}

This is not a native class(I think), but similar concept.
JavaScript:
console.show = function(content) {
    require("nw.gui").Window.get().showDevTools();
    if (content) console.log(content);
};

console.popError = function(content) {
    require("nw.gui").Window.get().showDevTools();
    if (content) console.error(content);
};

I've added these function because they are functions I feel are quite relevant, as I often feel a need for them. But if it is actually bad, then I'd like to know why. Because I honestly don't understand why it would be an issue at all :/
 

Aerosys

Veteran
Veteran
Joined
Apr 23, 2019
Messages
642
Reaction score
620
First Language
german
Primarily Uses
RMMZ
The problem is, if every plugin dev would manipulate class like that, we would get a lot of incompatibilities. What if, someone else creates a "remove" function bit slightly differently? It could work, or it could cause your game to crash. This is why we usually use IIFEs with only one global object as "entrance point". E.g.

MK.removeFromArray(array, obj) { ... }
 

Synrec

Veteran
Veteran
Joined
Nov 6, 2019
Messages
209
Reaction score
135
First Language
English
Primarily Uses
RMMV
Source: https://stackoverflow.com/questions/14034180/why-is-extending-native-objects-a-bad-practice

When you extend an object, you change its behaviour.

Changing the behaviour of an object that will only be used by your own code is fine. But when you change the behaviour of something that is also used by other code there is a risk you will break that other code.

When it comes adding methods to the object and array classes in javascript, the risk of breaking something is very high, due to how javascript works. Long years of experience have taught me that this kind of stuff causes all kinds of terrible bugs in javascript.

If you need custom behaviour, it is far better to define your own class (perhaps a subclass) instead of changing a native one. That way you will not break anything at all.

The ability to change how a class works without subclassing it is an important feature of any good programming language, but it is one that must be used rarely and with caution.
 

bishiba

Adept
Veteran
Joined
Apr 6, 2016
Messages
277
Reaction score
161
First Language
Swedish
Primarily Uses
N/A
The problem is, if every plugin dev would manipulate class like that, we would get a lot of incompatibilities. What if, someone else creates a "remove" function bit slightly differently? It could work, or it could cause your game to crash. This is why we usually use IIFEs with only one global object as "entrance point". E.g.

MK.removeFromArray(array, obj) { ... }
Yeah, that does make a lot of sense. Feels very smooth to add the functions, that honestly feel like they should be there from the start.

And I am very, very rarely doing these things. It's just that it is incredibly common that I want to remove a specific index, or remove all falsy indexes for example. The Math.random functions are a bit excessive since I've added three different variations...

But considering it is specifically this game and such, where I know what functions will possibly exist in regards to these classes. Would it be an issue to add these?
When I've been doing things for online, I haven't ever considered doing something similar. Then all functions go through BISH.

I've anyways, changed the Array classes to be in the BISH class now. Sadly the Math ones are used quite often. So hopefully it won't cause any issues.
 
Last edited:

Synrec

Veteran
Veteran
Joined
Nov 6, 2019
Messages
209
Reaction score
135
First Language
English
Primarily Uses
RMMV
If it's just you, I don't think there's any rules.

Ultimately, what you want is the result.

Why do you care about the best practice if the code is only for you?
 

zzmmorgan

I've used punchcards
Veteran
Joined
Jul 10, 2020
Messages
168
Reaction score
278
First Language
English
Primarily Uses
RMMZ
If it's just for your project I don't see that it matters since if you screw it up you can always drop in the original .js files and start fresh. IF you decide to write plugins though it can make a BIG difference.....
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
4,206
Reaction score
3,477
First Language
English
Primarily Uses
RMMZ
As others have said, the issue with doing this is when your work is going to be used alongside another developer's, whose functions and code you don't know. If you add a particular function to the Array class, it's entirely possible someone else also added a function with the same name, and if someone puts their plugin after yours, their version will take precedence, and then any of your code that relies on that function might end up working differently to how you intended.

If you're only working on your own project, writing your own code, and know everything that's going into it, there's no harm in this.

I take a best of both worlds approach: if I'm adding functions to native classes in plugins that I might be making available to others, I preface their names with an acronym it's unlikely anyone else will use (usually TLB for my Trilobytes brand)
 

Arthran

Veteran
Veteran
Joined
Jun 25, 2021
Messages
123
Reaction score
90
First Language
English
Primarily Uses
RMMZ
In addition to what other people have already said, I kinda want to point out that, in your examples, there's not an actual reason to be extending Math or console.

In your Array example, there is a tangible benefit to doing what you're doing, because it will allow you to call those methods off of any instantiated arrays. What I mean is that if you've got an array named butts, you can invoke your remove method using butts.remove(x) at any time. This could save some typing, increase the readability of your code, and allow you to use it in a chain of methods (i.e. butts.reverse.remove(x)). But you don't get that benefit in your Math and console examples.

Math is static, so you're not going to have instantiated objects of it. So what benefit do you get from adding those methods to the Math class, instead of to your own utility class or something? Math.roundRandom(10) isn't any easier to type than Bish.roundRandom(10). Sticking those methods in the existing Math class is entirely superfluous, and yields no benefit outside of satisfying your own arbitrary organizational desires.

Since there's no actual benefit to doing it, yet there are potential risks, it's better to just not do it. Putting it in your own class also has a benefit to anyone else who's reading your code, because then they can immediately recognize it as a user-defined method.

The same goes for your console extensions. There's not a real reason for them to be tacked onto the console object. There's no benefit to doing it the way you did it, compared to simply using Bish.showConsole(x) or something. In fact, in this particular case, I would say that what you're doing is a bad thing to do for a different reason than what has already been stated: Both of your methods are calling the require function, which is *not* a standard JavaScript function--it's a Node.js function. To me, since the standard JavaScript classes are all platform independent, it seems kinda dirty to extend them with methods that are platform specific. It seems like a potential can of worms that should be avoided.
 
Last edited:

bishiba

Adept
Veteran
Joined
Apr 6, 2016
Messages
277
Reaction score
161
First Language
Swedish
Primarily Uses
N/A
If it's just you, I don't think there's any rules.

Ultimately, what you want is the result.

Why do you care about the best practice if the code is only for you?
Well other answers I got was that it messes with the engine and that it makes it unstable when modifying native code. But I also think it is good to go with good practice, I don't know, if I make a nice stable plugin, I'll prolly release it :)

As others have said, the issue with doing this is when your work is going to be used alongside another developer's, whose functions and code you don't know. If you add a particular function to the Array class, it's entirely possible someone else also added a function with the same name, and if someone puts their plugin after yours, their version will take precedence, and then any of your code that relies on that function might end up working differently to how you intended.

If you're only working on your own project, writing your own code, and know everything that's going into it, there's no harm in this.

I take a best of both worlds approach: if I'm adding functions to native classes in plugins that I might be making available to others, I preface their names with an acronym it's unlikely anyone else will use (usually TLB for my Trilobytes brand)
Well, since two people in the javascript forum claimed it messes with the internal engines and can create issues from there it feels like there might be some harm. I don't think any sources were sent, and I am doubtful about the claims. But still.

At the end, I assume you mean then Array.prototype.BISHremove(index), for example?

In addition to what other people have already said, I kinda want to point out that, in your examples, there's not an actual reason to be extending Math or console.

In your Array example, there is a tangible benefit to doing what you're doing, because it will allow you to call those methods off of any instantiated arrays. What I mean is that if you've got an array named butts, you can invoke your remove method using butts.remove(x) at any time. This could save some typing, increase the readability of your code, and allow you to use it in a chain of methods (i.e. butts.reverse.remove(x)). But you don't get that benefit in your Math and console examples.

Math is static, so you're not going to have instantiated objects of it. So what benefit do you get from adding those methods to the Math class, instead of to your own utility class or something? Math.roundRandom(10) isn't any easier to type than Bish.roundRandom(10). Sticking those methods in the existing Math class is entirely superfluous, and yields no benefit outside of satisfying your own arbitrary organizational desires.

Since there's no actual benefit to doing it, yet there are potential risks, it's better to just not do it. Putting it in your own class also has a benefit to anyone else who's reading your code, because then they can immediately recognize it as a user-defined method.

The same goes for your console extensions. There's not a real reason for them to be tacked onto the console object. There's no benefit to doing it the way you did it, compared to simply using Bish.showConsole(x) or something. In fact, in this particular case, I would say that what you're doing is a bad thing to do for a different reason than what has already been stated: Both of your methods are calling the require function, which is *not* a standard JavaScript function--it's a Node.js function. To me, since the standard JavaScript classes are all platform independent, it seems kinda dirty to extend them with methods that are platform specific. It seems like a potential can of worms that should be avoided.
Truth be told, I didn't consider the reason for why I did it before posting this. I think you hit the nail straight down, I remember that when I made the Math class I thought to myself that it was neat and tidy. So basically satisfying my "organizational desire"... Busted...o_O
Then again, I did create the console commands like yesterday with the same reasoning :D
But you are right and I shall work on removing them, satisfying arbitrary things like that for no reason is just begging to get bugs.

I did not consider that the require feature was just in Node, nor did I know it was Node specific. I remember thinking something along the lines of "I wonder if that is a general thing or just something for the RPG maker engine".

Either way, I've removed them at this point and I placed them in the BISH class instead. Except for the Math additions as I've used them in several places. But I will remove them when I get the chance.
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
4,206
Reaction score
3,477
First Language
English
Primarily Uses
RMMZ
Your example is what I meant, yes. :)
 

Shaz

Global Moderators
Global Mod
Joined
Mar 2, 2012
Messages
44,647
Reaction score
15,742
First Language
English
Primarily Uses
RMMV

This thread is being closed, due to being solved. If for some reason you would like this thread re-opened, please report this post and leave a message why. Thank you.

 
Status
Not open for further replies.

Latest Threads

Latest Posts

Latest Profile Posts

SF_Enemy1_6 added!
index.php

Just thought I'd share how my battlers are looking for my 4 main characters. From left to right... Ashlyn the brave fighter, Lizzabelle the peaceful mage, Suki the thief, Saedra the not-so-peaceful mage.

pLZHVLI.png
Power to the Game Make!
ok by this weekend I WILL finally need alpha testers for Backstage: murdered sleep because it's got enough content at this point I want to get it on Steam Early Access ASAP (2/22/2022 would be a cool release date if I can make it).

By all means volunteer here, sure, but where else should I be looking?
1643337839651.png
Randomly trying to make some butcher shop tiles for MZ :3

Forum statistics

Threads
118,776
Messages
1,118,633
Members
155,943
Latest member
fooooox
Top