January 26, 2022

On Tuesday, 25 January 2022 at 09:53:25 UTC, rempas wrote:

>

It is known that people dislike global variables and the reason is that they make the code harder to debug. In my experience tho, it is the exact opposite. When I have a variable that I must pass down to 5-6 functions, I find it much easier to make it global rather than having it been passed in all the functions that need it. This practice also makes my function signatures looking much cleaner. Yeah, one variable will not make a difference but in my project, I have about 2-3 variables that need to be passed down to a lot of functions so I only think that it makes sense to use them as globals. Another problem is the case that I'll introduce a new variable that needs to also be passed in most of my functions. What happens then? Let's say I will have 20 functions at the time. I have to change both the function signature and all the other places in code that call this function. The latter can be easily done with a quick "search and replace" in my text editor but still, it's a tedious thing to do.

So can someone make examples about how global variables can mess me up. I know that probably everyone here has more personal experience than me so I really want to learn why global variables are considered so harmful.

Some examples of global variables that are frequently used:

  1. C has an implicit global variable in all programs - errno.
  2. If you are writing asm blocks (in C or D), then the processor's flags and registers are obviously global variables that can affect the function's behavior. At least in D the compiler will complain if a function is marked pure but has an inner asm block; the block has to be annotated explicitly with pure.
  3. The language runtime might also be considered as one giant global variable. As an example, a function may return successfully on one invocation and fail on another despite being pure and being invoked with the same parameters, just because a memory allocation has failed. Potentially, you could even catch and handle OurOfMemoryErrors (something which you aren't supposed to do, I think) and change function behavior based on that. However, if I'm not mistaken, any issues related to memory allocation aren't typically considered a part of the function's "contract"; otherwise, pure would only be possible if @nogc is also present.
January 26, 2022

On Wednesday, 26 January 2022 at 08:07:10 UTC, rempas wrote:

>

[snip]

Thank you! The thing is that this will not work on me as I want global variables that I will actually be able to mutate.

I have the same worries about global mutables as others...

January 26, 2022

On Wednesday, 26 January 2022 at 09:27:28 UTC, rempas wrote:

>

I started getting interested in programing in 2020 (even tho I had some prior experience with Python in school but this doesn't count) so I didn't had the joy to work with any version of FORTRAN. Fun fact: I thought that FORTRAN (do we really need to write it in capital letters?) is an ancient language but I made a research and found out that it is still updated!!!

The numbers behind the name are roughly the year of the standard. FORTRAN 66 and FORTRAN 77 used all caps. Fortran 90 and later dropped the all caps thing.

Modern Fortran isn't bad if you're working in the domain for which it was written. I wouldn't hesitate to take it over C, C++, or Rust for that type of work.

January 26, 2022

On Wednesday, 26 January 2022 at 08:02:33 UTC, rempas wrote:

>

On Tuesday, 25 January 2022 at 12:56:00 UTC, max haughton wrote:

>

What I mean by outline (where global is the thing you don't like passing around) :

```d
int foo(ref int global)
{
    bar(global);
}
int bar(ref int global);
```
the "outline" (a reduced call graph if you will) would be something like

```
foo(ref int global)
  bar(global);
```
if the code is small enough just post the code, I want to illuminate that if you have a bunch of parameters everywhere you might want to make it a member function instead.

Oh, thanks for the explanation! No, the code is not small, it is a bunch of functions that access them actually. What do you mean with "member function". In a class?

If a class is reasonable, use a class, however if it's just some mutable state then use a struct since you don't need OOP

January 26, 2022
On Wed, Jan 26, 2022 at 08:46:04AM +0000, rempas via Digitalmars-d wrote:
> On Tuesday, 25 January 2022 at 14:28:24 UTC, H. S. Teoh wrote:
[...]
> > Either group your parameters in a single struct, or make your functions members of the struct. Then all you have to do is add another field to your struct and you're done. No tedium.
> 
> Actually, I was wondering something. Maybe I should read the whole reference first but I'll just ask in case you know. Is there a way to just declare a struct/class method and define it outside the struct/class like in C++? It will be very annoying to have all my functions be in the same file. The first method seems better to me.
[...]

Thanks to UFCS, you don't need to define every function that operates on the struct/class as a method. Free functions work just fine.

I.e., instead of this:

	struct MyData {
		int x;
		void method() {
			x++;
		}
	}

	MyData data;
	data.method();

you could also write this:

	struct MyData {
		int x;
	}

	void method(ref MyData mydata) {
		mydata.x++;
	}

	MyData data;
	data.method();


T

-- 
Debian GNU/Linux: Cray on your desktop.
January 26, 2022

On Tuesday, 25 January 2022 at 09:53:25 UTC, rempas wrote:

>

It is known that people dislike global variables and the reason is that they make the code harder to debug. In my experience tho, it is the exact opposite. When I have a variable that I must pass down to 5-6 functions, I find it much easier to make it global rather than having it been passed in all the functions that need it. This practice also makes my function signatures looking much cleaner. Yeah, one variable will not make a difference but in my project, I have about 2-3 variables that need to be passed down to a lot of functions so I only think that it makes sense to use them as globals. Another problem is the case that I'll introduce a new variable that needs to also be passed in most of my functions. What happens then? Let's say I will have 20 functions at the time. I have to change both the function signature and all the other places in code that call this function. The latter can be easily done with a quick "search and replace" in my text editor but still, it's a tedious thing to do.

So can someone make examples about how global variables can mess me up. I know that probably everyone here has more personal experience than me so I really want to learn why global variables are considered so harmful.

I once worked on a system (written in Java) that was a huge commercial success. The company has a revenue of about €100 million from it. What later turned out should always have been passed on to methods as a parameter was always a global function. Now many person years have been spent on development and countless lines have been written and there is absolutely no way to fix this as the effort in time and money is way to large. For some little programs you might get away with some globals, but not in case of lage systems.

January 26, 2022

On 1/26/22 4:10 AM, rempas wrote:

> >

In some cases, they make sense, and in those cases, I'd recommend at least guarding the direct access to the variable through properties so you can control how it's used.

What do you mean "properties"? I suppose not struct/class properties right?

A property is a functional setter/getter (or only one of those) that prevents incorrect usage.

For example, if you have a global int, and it really should only be in the range of 1 to 1000, you can guard the setting of the int to make sure that value was correct.

Or if you have a class reference stored globally, you may want to prevent someone from reassigning the class reference to another object. Then you can restrict access to getting only, and not allow setting.

You can implement a property in D at global level, e.g.:

private Resource _resource;

public Resource resource() { return _resource; } // only can access via this property

-Steve

January 26, 2022

On Wednesday, 26 January 2022 at 11:38:51 UTC, forkit wrote:

>

oh. what is actually going on in foo is irrelevant of course.

foo does nothing of any relevance.

the point I was making, was about having a global variable with the same name as as a local variable, could 'potentially' slip you up.

What you describe here is actually not specific to globals.
The same can happen with aggregate members

struct S
{
    int e;
    function f() {int e;}
}

but also inheritance. This is more a problem of name hijacking, except that this is officially not recognized as such, since there is a way to distinguish (either using the global access operator or the explicit ThisExp.

Here is an example for the inheritance taken from DMD codebase and that was encountered, for real, 2 years ago while doing a refactoring

class A
{
     bool isscope;
}

class B : A
{
    bool isscope(); // not even related to A.isscope
}

now remember that getters can be called without parens. Now imagine you want to rename one of the isscope.

January 26, 2022

On Tuesday, 25 January 2022 at 09:53:25 UTC, rempas wrote:

>

It is known that people dislike global variables and the reason is that they make the code harder to debug. In my experience tho, it is the exact opposite. When I have a variable that I must pass down to 5-6 functions, I find it much easier to make it global rather than having it been passed in all the functions that need it. This practice also makes my function signatures looking much cleaner. Yeah, one variable will not make a difference but in my project, I have about 2-3 variables that need to be passed down to a lot of functions so I only think that it makes sense to use them as globals. Another problem is the case that I'll introduce a new variable that needs to also be passed in most of my functions. What happens then? Let's say I will have 20 functions at the time. I have to change both the function signature and all the other places in code that call this function. The latter can be easily done with a quick "search and replace" in my text editor but still, it's a tedious thing to do.

So can someone make examples about how global variables can mess me up. I know that probably everyone here has more personal experience than me so I really want to learn why global variables are considered so harmful.

when you create a global variable anything can modify it, meaning that if someone else writes code, or another thread changes the variable, it can cause side affects, and it can be difficult to follow especially because you may not know what or where the bug is, also when you pass it into a function then you are effectively documenting the code, this means in the future it will be much easier to debug because you know where it is going, especially when working in a team environment. however this is yes good practice but I still use global variables when it is convenient for a smaller project where the code fits on one screen, or the name of the variable describes its location. but I work for myself and I am the only one who sees my code.
a lot of code practices people recommend such as not using macros is because of team environments' because many convenient code practices can easily cause confusion for your peers. but I still dont understand why people see it as a sin of coding to use global variables, it depends on the code base and the project.

In some of my code there is only global variables because one of the languages I use only uses global variables so if something is broken it takes a hot minute, I dont know what function is causing the error, just have to go through them all.

January 26, 2022
On Wed, Jan 26, 2022 at 11:13:56PM +0000, MrJay via Digitalmars-d wrote: [...]
> a lot of code practices people recommend such as not using macros is because of team environments' because many convenient code practices can easily cause confusion for your peers. but I still dont understand why people see it as a sin of coding to use global variables, it depends on the code base and the project.
[...]

I don't consider it a "sin" to use global variables, I've done that myself in the past (and still do it occasionally for one-off scripts, because let's face it, it's darned convenient).  Only thing is, in pretty much every non-trivial project where I've used globals, I ended up regretting it later because of the myriad of problems associated with using global variables. Such as not being able to create new instances without rewriting a ton of code (e.g., the database connection example in my other post), being confusing to debug (some global changed between the call to f() and the call to g(), but it's totally non-obvious from reading the code and left me scratching my head as to why g() is suddenly behaving funny).

This applies not only in team environments -- in single-person projects the "confused team member" could very well be yourself after 3 months ("WHAT I was thinking when I wrote this?!"). Or, in my case, 5 years ("WHAT was I trying to do when I wrote this crock?!").

After many experiences of this, I've come to the conclusion that the convenience of using globals is usually not worth the trouble they cause down the road. I rather "waste" a bit more time writing things the "right" way now, than to waste a LOT of time (and frustration) later trying to debug code riddled with global state.


T

-- 
It said to install Windows 2000 or better, so I installed Linux instead.