From: Vladimir Vassilevsky on


David Brown wrote:


> What I take issue with
> is when people get obsessive about globals and think that it is somehow
> better to have functions called "SetUartTimeout" and "GetUartTimeout",

Yes it is better.

* Perhaps it could be necessary to add flushing the UART before changing
timeouts. You just have to modify one function.

* What if there is a need to have more then one uart? How about
accessing N uarts?

* What if there is a need to access the timeouts from more then one thread?

* What if there is a name conflict due to the use of the global objects?

> doing nothing but accessing a static variable, instead of just using a
> globally visible variable "uartTimeout".

I do require all access to such variables via member functions. I like
an overloaded function UART.Timeout() instead of separate Set.. and
Get.. functions.

> The global must be part of the well-defined interface,

Well defined interfaces exist only in the textbooks.

> not a backdoor into the module's interior, but
> there is absolutely no reason to pretend that having the global variable
> is somehow "riskier" or "unclear", or harder to use or change.

As the project grow large, is gets much harder to maintain the code
which is controlled by the global variables.


Vladimir Vassilevsky
DSP and Mixed Signal Design Consultant
http://www.abvolt.com


From: Arlet on
On Sep 28, 11:39 pm, Vladimir Vassilevsky <nos...(a)nowhere.com> wrote:
> David Brown wrote:
> > What I take issue with
> > is when people get obsessive about globals and think that it is somehow
> > better to have functions called "SetUartTimeout" and "GetUartTimeout",
>
> Yes it is better.
>
> * Perhaps it could be necessary to add flushing the UART before changing
> timeouts. You just have to modify one function.
>
> * What if there is a need to have more then one uart? How about
> accessing N uarts?
>
> * What if there is a need to access the timeouts from more then one thread?
>
> * What if there is a name conflict due to the use of the global objects?
>
> > doing nothing but accessing a static variable, instead of just using a
> > globally visible variable "uartTimeout".
>
> I do require all access to such variables via member functions. I like
> an overloaded function UART.Timeout() instead of separate Set.. and
> Get.. functions.
>
> > The global must be part of the well-defined interface,
>
> Well defined interfaces exist only in the textbooks.
>
> > not a backdoor into the module's interior, but
> > there is absolutely no reason to pretend that having the global variable
> > is somehow "riskier" or "unclear", or harder to use or change.
>
> As the project grow large, is gets much harder to maintain the code
> which is controlled by the global variables.
>
> Vladimir Vassilevsky
> DSP and Mixed Signal Design Consultanthttp://www.abvolt.com

From: Arlet on
On Sep 28, 11:39 pm, Vladimir Vassilevsky <nos...(a)nowhere.com> wrote:

> * Perhaps it could be necessary to add flushing the UART before changing
> timeouts. You just have to modify one function.
>
> * What if there is a need to have more then one uart? How about
> accessing N uarts?
>
> * What if there is a need to access the timeouts from more then one thread?

If a function results in simpler code, they should be used, of course.
But if you know that you're not going to be using threads, there's
only one UART on the device, and the UART doesn't need to be flushed,
using a global may be appropriate. If the circumstances change, the
code can always be modified.

If you know the requirements are fixed, for instance the baud rate
must be 9600, using 8N1, there is also no need to add functions to
change these things.

> * What if there is a name conflict due to the use of the global objects?

Not likely if you start the name with 'uart' or something like that.

> As the project grow large, is gets much harder to maintain the code
> which is controlled by the global variables.

Sure, but many projects never grow large.
From: Jon Kirwan on
On Mon, 28 Sep 2009 22:09:28 +0200, David Brown
<david.brown(a)hesbynett.removethisbit.no> wrote:

>ChrisQ wrote:
>> David Brown wrote:
>>
>>> Personally, I think the general idea of "all global data is evil" is
>>> silly, especially for embedded development. But if you've got a
>>> programming method that helps you write better code, then that's far
>>> more important than what other people think!
>>
>> Having had to wade through impenetrable code too many times in the past,
>> where it's hard to tell what's poking what and when, I try not to
>> inflict the same on others. One of the ways to do this is to encapsulate
>> functionality, keep data local as possible and communicate through well
>> defined inband interfaces. The typical embedded design can be split into
>> subsystems - for example, uarts / comms, timers, ports etc. There's no
>> reason why the internal data relating to a subsystem should be public,
>> even though it may need to be visible internally. Avoiding this makes
>> for a more reliable system design, it's easier to make changes, add
>> modules and to keep track of the big picture. Of course, none of this is
>> new, but it does seem to work...
>
>I agree 100% about encapsulation (at least, I agree about it as an ideal
>- sometimes you have to compromise in practice). What I take issue with
>is when people get obsessive about globals and think that it is somehow
>better to have functions called "SetUartTimeout" and "GetUartTimeout",
>doing nothing but accessing a static variable, instead of just using a
>globally visible variable "uartTimeout". The global must be part of the
>well-defined interface, not a backdoor into the module's interior, but
>there is absolutely no reason to pretend that having the global variable
>is somehow "riskier" or "unclear", or harder to use or change.

[First off, I want to make sure no one reading this is conflating the
idea of 'global' with 'static'. A global definition (in c) is always
a static definition. But not all static definitions are global.]

There are few cases where a global static is better than a module-
local static; where a function mediates access rather than allowing
any part of the code in any other module to directly access the global
static. The conceptual region where I imagine you may have a point is
where there is a requirement for frequent access across a wide range
of the total code space and the cost of a function call, both in code
size and execution time, is too high to afford in the application.
While that usually means the code factoring is wrongly arranged, it
doesn't always mean that. And there are ways around this. In
general, the code I can recall doing over the last few decades, even
on smaller PICs, doesn't use global statics. Good factoring seems to
almost always eliminate the need.

An example where I've used global access to a static (for reading) is
the current PID for the active, running process. In this case, access
to reading the current process ID is so widely needed throughout other
modules in an O/S and the memory and execution constraints may be so
tight that it makes some sense. However, this can be carefully
crafted together with the use of #define so that later changes could
be reasonably performed without having to edit all the references.

So you are right that one should be so afraid that they will not
accept it for any use, at all. But be very, very wary of the idea.

An example of how it can be done in c is something like this. The .h
file for a module might include some code like this:

#ifdef SOMECOMPILEOPTION
extern unsigned int GetCurrentPID( void );
#else
extern unsigned int currpid;
#define GetCurrentPID( ) (currpid)
#endif

A function in the .c module can be provided (or selectively provided
depending on a compile option) in the module written like this:

#ifdef SOMECOMPILEOPTION
static unsigned int currpid;
unsigned int (GetCurrentPID)( void ) {
return currpid;
}
#else
unsigned int currpid;
#endif

(You can get trickier.) The reason for wrapping the function name in
parentheses, if this isn't already obvious, is to avoid having the
#define mess with the function definition.

Now you can go either way by changing a compile option.

Jon
From: John Devereux on
Vladimir Vassilevsky <nospam(a)nowhere.com> writes:

> David Brown wrote:
>
>
>> What I take issue with is when people get obsessive about globals
>> and think that it is somehow better to have functions called
>> "SetUartTimeout" and "GetUartTimeout",
>
> Yes it is better.
>
> * Perhaps it could be necessary to add flushing the UART before
> changing timeouts. You just have to modify one function.
>
> * What if there is a need to have more then one uart? How about
> accessing N uarts?
>
> * What if there is a need to access the timeouts from more then one thread?
>
> * What if there is a name conflict due to the use of the global objects?
>
>> doing nothing but accessing a static variable, instead of just using
>> a globally visible variable "uartTimeout".
>
> I do require all access to such variables via member functions. I like
> an overloaded function UART.Timeout() instead of separate Set.. and
> Get.. functions.

How does that work, like:

timeout = UART.Timeout(GET,UART1);

...

UART.Timeout(SET,10000);

?


I seem to end up with a lot of globals at what I would call the
"application" level. By this I mean the code that describes what the
machine does rather than its internal operation.

So you end up with lots of code looking like:

status_t status; /* global */
set_t set; /* global */
....
status.temperature = adc(0);
status.pressure = adc(1);
status.test_number++;

if(set.test_time > SET_TEST_TIME_MAX)
{
status.flags |= STATUS_FLAG_ERROR_TEST_TIME;
}

....

Any part of the application can read and write settings, status
variables etc.

--

John Devereux