From: Vladimir Vassilevsky on 28 Sep 2009 17:39 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 28 Sep 2009 17:42 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 28 Sep 2009 17:59 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 28 Sep 2009 19:55 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 29 Sep 2009 03:27
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 |