8

This question already has an answer here:

I'm a newbie coder. I find it troublesome to declare a variable in 1 function and not be able to access it in other functions. I have to make many of my variables global just to get my code to work. But a lot of people say that the global state is evil. I don't understand the purpose of having limited scope, anyway.

Scope seems to encourage developers to declare same-name variables in different places.

def func1():
    string = 'hello world'
    ...
def func2():
    string = 'hello universe'
    ...

Without the need to distinguish variables in different functions, developers name their variables vague and less-meaningful names. Wouldn't it be better to have more specific variable names?

def func1():
    world_string = 'hello world'
    ...
def func2():
    universe_string = 'hello universe'
    ...

Why is limiting access to variables outside of the block that it's defined in, i.e. scope, a good thing to have in programming languages? As a newbie, I find it convenient to make every variable a global variable. Why is that bad in bigger projects?

marked as duplicate by Robert Harvey, Telastyn, Doc Brown, Andres F., Greg Burghardt Jul 13 '18 at 21:23

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 3
    In the limited code context you've provided, it doesn't make sense. – Robert Harvey Jul 13 '18 at 18:01
  • 7
    You quickly run out of unique, meaningful names. – Caleth Jul 13 '18 at 18:04
  • 8
    Possible duplicate of Why is Global State so Evil?. Also related – Delioth Jul 13 '18 at 18:06
  • 7
    Local variables let you think locally. You can reason about a function in isolation, with no fear that some other external function is going to tamper with your state. Plus, why repeat yourself? It's clear to see that a is in either func1, or func2, so why do we have to label it further? – Alexander Jul 13 '18 at 18:09
  • 6
    What if every single different collection type had to have a different name for "Length", wouldn't that get rather obnoxious? – whatsisname Jul 13 '18 at 18:14
25

Engineering is, abstractly, managing complexity.

Software Engineering is, abstractly, managing complexity in software!

Scope is a tool to help manage complexity, like any tool it can be used or abused, and sometimes can be overkill.

Without scope, you would have to track the entire state of the program at all times when writing or modifying it.

Without tools to manage complexity, the complexity will rise to the point of becoming overwhelming. N.b. scope is only one tool in the aresanel.

As a newbie, I find it convenient to make every variable a global variable. Why is that bad in bigger projects?

As the size of the project increases it will become harder and harder to keep all the state, names, etc. straight; you will make more errors.

  • 1
    +1 I don't understand how this answer can have downvotes. Scope is about managing complexity. – Andres F. Jul 13 '18 at 20:12
  • 1
    ... and software abstraction is all about suppressing the details into ideally a single and self contained unit of code with a name to represent the abstract idea. – ThisClark Jul 14 '18 at 22:18
11

Minimizing your use of global variables means that you don't have to think about how these variables are interacting with your functions.

How many different places in your code are writing to that global variable? Your global variable is the center of a spider web; every place it touches is adding unnecessary complexity and coupling.

Eliminate the variable, and the complexity disappears, because you can reason about each function in isolation. Unit testing becomes easier, maintenance becomes easier, everything becomes easier.

  • 4
    To add: minimizing scope can also allow for optimizations. For example, the escape analysis feature of hotspot which can identify that an object's scope never leaves the stack allowing the state to be extracted to the stack and it's methods inlined. – JimmyJames Jul 13 '18 at 18:19
5

You mention you're a newbie coder, so I'm guessing you're working on fairly small programs right now - small enough that you can keep most of it in your head at once. But a typical mobile app is about 400k lines of code. Photoshop is about 5 million.

How can you keep that much code in your head at once? You can't. Nobody can. Hence, encapsulation. You build a sealed box that does one thing. Then once you verify that the box works, you can stop thinking about the contents of the box. A dozen lines of code turns into one unit. Then you do that again, and again, using the boxes to make larger boxes, so that at any given layer you have a small enough number of elements to keep them all in your head at once (ideally; in practice there are various ways for nicely decoupled systems to become a confusing mess).

That's why you want to keep the scope of your variables as small as possible. Because then you can stop thinking about them sooner.

3

There are a couple of schools of programming methodology, but nearly everyone agrees that functions should have well defined and narrow responsibility. For one, it makes testing much easier, for another, it makes the code more modular.

It's likely that in a large application you'll want to get a count of something more than once. If you didn't have scope, you would overwrite the count variable, possibly before you were done using it in another context.

You might respond by saying, "that's not really a problem, I'm a good programmer, I only use very descriptive variable names". However, consider a situation where you are working on a team to build software. What guarantee do you have that no one else has used your variable before? You could search the whole project for any instances, but what happens when you find an occurrence. Instead of naming your variable PostCount you might end up naming it PostCountInBlogController. We're getting further away from readable code.

2

Beyond the observation that global state is bad, what you're looking for, if you want to share variables between several methods, is the notion of the class and object instantiation!

A class lets us group state and methods that work together.

Further, instantiation (creating an object instance of a class) allows us to

  • manage the lifetime of state, so it's not necessarily global,
  • support multiple concurrent separate instantiations,
  • manage access to the state, so one instance doesn't interfere with another

The class & instance mechanism delivers what you're looking for, plus more, and, avoids many of the pitfalls of global variables.

  • 2
    Do note that scope as a concept is orthogonal to classes and object instantiation, and indeed scope is used in languages without classes, objects or methods. – Andres F. Jul 13 '18 at 20:13
  • And in languages like ECMAScript or Scheme, scope is used to implement objects! – Jörg W Mittag Jul 13 '18 at 21:44
1

If you feel the need to access a variable declared in another function, your function may have too many responsibilities.

Rather than focus on the number of lines, try to think of a function as a processor that does one thing. If it yields a result, you may return the result and pass it on to the next function as an input argument. That is another way of sharing data, but without one function having to know about the other function.

Now everything in one function will be independent from other functions. You can change and move around stuff in one function without impacting (having to change as well) other functions. That is a good thing, it makes the code easier to maintain.

It is like building something from components. The components are self contained, they can exist and be updated disregarding the full system.

1

Most functions have some variables which they use during execution, but that nothing in the universe will have reason to care about once they return. While it might be possible for an implementation to hold onto such variables forever, or at least until the next time the function is called, doing so with variables nobody will ever care about would represent a waste of storage. Limiting the scope of variables makes it possible to discard them when a function exits, allowing any space they'd occupied to be used for other purposes.

While it would be possible to tag the names of variables with a prefix indicating the function where they're used, that wouldn't make much sense for variables that are used only within the function where they are created. The fact that a declaration for x appears within a function foo() indicates that any use of the identifier x within that function will refer to foo's own private variable of that name. There's no need to mark the name with the name foo because the variable couldn't possibly belong to any other function.

Not the answer you're looking for? Browse other questions tagged or ask your own question.