Sloppy programming and stupid mistakes you shouldn't make

Diconica

Well-Known Member
Apr 25, 2020
1,100
1,150
As of late I've seen more than one game with this type of issue and it's stupid as shit that it happens.
Developers who do this should be ashamed and hang their heads down. I'll give an example and how to prevent it after.

Developers define a function with X variables then call it with a different number.
Python:
def add(self,a,b):
    return a+b

#later call it with
add(self,a,b,c)
This is easy as hell to prevent.
Write a script go through all the files in the directories and copy all the function definitions.
Have it store a variable count for each of the function definitions.
Then have it go back through all the files in the folders and check for areas the function is called rather than defined.
That's pretty easy to distinguish in python scripts because function calls don't have def in front of them usually.
When it goes through have it at the very least compare the number of variables to the number you have stored for that function.
If it doesn't match save the file name and line to a file or display it.

A lot of people are using python with renpy so there is no excuse why they can't take 10 minutes out to create a script they can run in 1 second that will catch all these errors. With C, C++ this type of issue doesn't really exist because it would be caught at compile time. Python though it shows up when the code is ran.
A good ide can also catch this when you are typing the function calls. It doesn't help much if you however change the function definition after the calls are already written. That's why such a script is handy.

if you want a basic idea how this can be done.
You need an array to store names and variable count
Well use def function(self, v1, v2): we search for def and end with : make sure there is a space after def.
Then remove all white space(new lines, tabs, spaces, carriage return) that will leave you with deffunction(self,v1,v2):
remove def from the front and : from the rear. function(self,v1,v2) Everything up to the first ( will be the function name.
use the commas after that to determine the number of variables. The function above has 3 variables including self thus 2 commas.

Anyway you will need to make 2 passes through the files. The first to collect all the function definitions the second time through to check all the calls against the definitions.

Note: Can't remember if the python rule regarding commas in arrays has been applied to functions also. Arrays you can have a comma following the last variable.
That said I haven't seen it used in any functions if it does apply. Even if it does all you need to do is check if the commas is directly followed by ) and then not count it.

The next part requires a bit more programming skill. It still can be done. Which is why I won't harp to much on this one.
You can make sure the type of variables used to call and expected in the return of are matching the function definition.
 

Frim der Wel

Newbie
Nov 29, 2020
30
413
Well, instead of writing scripts that try to catch such errors I would strongly recommend to use a such as pylint, with integration into your editor or IDE? Also, I am a bit confused why you use the rather questionable looking function call f(self,a) instead of the intended self.f(a)?
 

Diconica

Well-Known Member
Apr 25, 2020
1,100
1,150
Well, instead of writing scripts that try to catch such errors I would strongly recommend to use a such as pylint, with integration into your editor or IDE? Also, I am a bit confused why you use the rather questionable looking function call f(self,a) instead of the intended self.f(a)?
I did mention IDE built in support.
It would also make sense to use an addon if one is available such as atom and flak8. So thanks for bringing it up. I should have brought it up.
Primarily I was targeting the renpy developers.
As for the function style the same reason applies I was targeting the developers of renpy and what I see them most often using.
Technically it didn't matter so much as the format of the function but how they could identify the parts of the function definition and call. The use of the function wasn't what was being demonstrated. I could have made the variables a,b,c and it would much of a difference. The only thing is some of these people seem to get the variable count off not recognizing that self is just that. Which is my guess as to why some of them have these errors. So I figured I would use that in the demo. As for your examples my method to extract the information would have been just as valid on them. So again how to write a function wasn't the point.

The primary point was even if they are using crappy tools such as windows edit. There isn't an excuse for these types of errors. It's easy enough to create your own tool with a little work to catch all those errors.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,384
15,294
Primarily I was targeting the renpy developers.
So, to be clear, your primary target are developers who use a language that validate the number of arguments passed and will throw an explicit TypeError exception anytime there's a mismatch ? An exception that even take count of optional arguments, telling you that the function take "at least X arguments" or "at most X arguments".

Or, said otherwise, developers that will never encounter this problem in production...


As for the function style the same reason applies I was targeting the developers of renpy and what I see them most often using.
If you've seen so many Ren'py games' code that you achieved to found some using method( self, arguments ), you should also have seen that not a single one have the problem you're addressing in this thread. This for the obvious reason explained above.
 
  • Haha
Reactions: gzrtjhgtyhjljk
Apr 24, 2020
192
257
I'm a bit miffed about your easy to implement idea for python overlooks args and kwargs, although that shouldn't be too difficult to add checks for as well.

My biggest issue is how loose the description of the solution is, given the target audience is mainly going to be people with very limited coding experience.
 

Diconica

Well-Known Member
Apr 25, 2020
1,100
1,150
I'm a bit miffed about your easy to implement idea for python overlooks args and kwargs, although that shouldn't be too difficult to add checks for as well.

My biggest issue is how loose the description of the solution is, given the target audience is mainly going to be people with very limited coding experience.
They could use an editor with built in solutions or use an editor with addon linter.
Doesn't take much to google that.

I understand your point. However, I see it from a different perspective. I didn't get to my level of programming by my instructors handing me code and say do this. They gave us projects and said figure out how to do this. Each week did build on the lasts. We were expected to look stuff up use books like PC intern and others to find the missing parts that were not covered in class.
I gave way more of a hint how to do it than my first college prof. Our first week assignment fro the weekend was create a Text based ATM system. Week 3 write a text editor.

The point is they will be better programmers for it. They will remember it a lot better because they came up with the solution on their own rather than me or you handing it to them. Speaking of which if you are so miffed about it and think it is so unfair why didn't you paste the basic solution. You can post the python script on here to do it easy enough.

I have never used self, I don't even understand it : p
Pretty sure you do. But for those who don't ;)

It's similar to the c++ this pointer in that it is used to reference the current instance of the class.
However, you can actually use a different name self is just used because of convention.
There are a number of other differences but you can look those up if you are interested.
 
Apr 24, 2020
192
257
I gave way more of a hint how to do it than my first college prof. Our first week assignment fro the weekend was create a Text based ATM system. Week 3 write a text editor.
My first project was building a crane. Like I've already said, I'm not a computer science guy.

Speaking of which if you are so miffed about it and think it is so unfair why didn't you paste the basic solution.
Because it was your idea and it seems to be a solution to a problem that should already be caught by other checks.
 
Apr 24, 2020
192
257
Don't worry, neither is he. As anne said before, passing the wrong amount of arguments to your function throws an exception in pretty much every language. He hasn't considered something basic like default values either.
Yeah, the only way I can see the issue being described happening, is if the written code was never actually run. Which is a very likely scenario, given the number of hobby programmers among adult game developers on this forum.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,384
15,294
He hasn't considered something basic like default values either.
Nor, since he target Ren'py/Python, the catch up *args and, even more frequent, **kwargs commonly used when you design your classes by inheritance.


For the readers, those two offer you the possibility to not care about the given parameters. You design your own class as needing its own arguments, and everything else will, by example, be catch by **kwargs and can be then sent like this to the ancestor.

If the original class looks like this
Code:
    class WhateverClass( object ):
        def __init__( motherOptional1="this", motherOptional2="that" ):
            [...]
in place of declaring all its arguments in your own class, like that
Code:
    class MyClass( WhateverClass ):
        def __init__( myArg, myOptional=False, motherOptional1="this", motherOptional2="that" ):
            [...]
you can simply declare your class this way
Code:
    class MyClass( WhateverClass ):
        def __init__( myArg, myOptional=False, **kwargs ):
            [...]
And then, if in the future WhateverClass change and get a new motherOptional3 argument, or is given a new default value for an existing argument, your own class is still fully compatible and don't have to be changed.

But obviously, this complicate a lot his method to not make "stupid mistakes".


This being said, it's always a good idea to have a copy of your classes, methods and functions declarations.
Writing a software, whatever an adult game or anything else, is something that need a lot of times. There's always a moment when you don't fully remember the needed arguments or their order. This small personal quick reminder will save you time. In place of searching in which file you put it, then where in this file it's, your just open your "doc.txt" file and you've everything you need.
 
Apr 24, 2020
192
257
This small personal quick reminder will save you time. In place of searching in which file you put it, then where in this file it's, your just open your "doc.txt" file and you've everything you need.
That's not actually a bad idea. It should be fairly easy to program a crawler to generate the document, considering there's a high chance that it needs to be updated fairly regularly.

In my case it's more of a question of which class is responsible for what task. Often functions gets tacked on whichever class makes sense, until there's a large enough group of them that it makes more sense to have them in a class of their own.
 

Frim der Wel

Newbie
Nov 29, 2020
30
413
This being said, it's always a good idea to have a copy of your classes, methods and functions declarations.
I feel kind of weird throwing in best practice tips here, as I am not a programmer at all; but I have written a few ten-thousands lines of python code and I really, really want to recommend to not reinvent the wheel. Seriously: (most important first)
  • Use a linter, such as (if you use any reasonable editor for your python scripts, be it atom, notepad++, vim, emacs,... there will be the possiblility to simply integrate it into the editor). This will take care, among a metric fuckton of other things, of the signature of function calls (and it will understand, of course, kwargs etc; it will also check the signatures of function calls to library methods etc); and it will catch a few other things that usually are typos/mistakes but not syntactically wrong (and accordingly sometimes hard to catch). Seriously, this will save you huge amount of pain.
  • Use docstrings ( ) in a consistent manner to describe your classes/methods (much better than a doc.txt). Less important: If you feel like it, you can then use or whatever to create a (e.g., html) doc from it.
  • Use a revision control system, usually git; make commits very regularly, make sure the commit messages are reasonable, check the differences before you commit (git difftool is your friend). This way you can get a much better overview of what has been going on with the project. And imagine the following, not entirely uncommon situation: you have some brilliant idea to revise your project, start editing several files, and after an hour or two you realize that the change you wanted is stupid and/or much too ambitious. With a CMS you can just revert to the state before with a single command.
  • If you program any nontrivial classes/methods, use integrated testing; the simplest form being trivial doctests. This way you will often find out whether a new change will break some other things that are already done and tested. You will want to use a testrunner, most likely pytest, for this.
All these tools are a pain to set up or get acquainted with at the beginning (git, sphinx and automatic testing more so; but there is really no excuse to not use pylint or docstrings) and it might seem an overkill for the hobby programmer, but all tools are free and well established and have good tutorials, and will save you lot of pain not just in the long run but even for your first small project.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,384
15,294
[...] I really, really want to recommend to not reinvent the wheel.
I totally agree, but I'm not sure that it really fit the amateur level (not said in a belittling way) of most adult games developers. Ren'py already come with its own lint feature and, alas, almost none use it.

The intent of my answer was more to go with the flow of the thread, some kind of "try to do it less badly". Then yours completed it greatly by adding the "and you can even do it more 'goodly'".