Related
This is confusing me a great deal. All code examples being namespaceA and namespaceB and the method names being foo() and bar() are not helping, either. The way everyone explains it makes it seem as though namespaces are a relic of pre-OOP times where you could not say 'class car give fuel level' but had to go to this from another approach. But when I now want to do a C++ level, what is the point of using namespaces? Not that headers are confusing enough already, namespaces make absolutely no sense to me, in either how they work or why to use them.
Let's say I have a project built around Traffic, for example. You'd have classes for the Cars and its components, the Drivers and Passengers and the Road.
Now, the Road has Cars and each Car has Persons. What would this look like?
Would you have the namespaces Road, Car, Person? Would the main() use the namespace Road to access the stuff in the header? Would the namespace Road include the namespace Car, and the Car include the namespace Person, and would through this the main() have access to the methods in Person? This is the way most guides explain this, but I don't really see the advantage of this over just importing the header file, wouldn't that have the same effect?
Or would you put multiple headers in the same namespace, such as namespace Traffic with all those classes? Can you nest namespaces?
I know C# and never knew it had namespaces until I looked it up just now, and never needed it, and in Java, Python, and Dart, those also never came up. Since I am trying to teach myself C++, I am kind of stranded here now, asking this question here. So far, I also never used them in C++, but I want to learn it properly.
For small, self-contained projects, there's not much need for namespaces, and you'd never create a namespace for each object or concept in your code.
Larger projects using libraries benefit from being isolated from names introduced by those libraries, as well as some internal organisation to make readability easier.
Similarly, when creating a library, it's a good idea to put its contents into a namespace so as not to cause headaches and conflicts for your users (as you don't know how large their projects will be, and what names they may want to use themselves).
To use an analogy: if you have three books, you don't bother organising them alphabetically. But, once you have a hundred, you might decide to categorise them on your bookshelf for easier reference and mental health.
And, if you now borrow another twenty books from a friend, you'd probably keep those in a separate pile so they're easier to find when you need to give them back.
So, to some degree, this is a case of… you'll know why you need it, when you need it.
If I make a library with a function calculateStuff() in it and you also make a library with a calculateStuff() function, then some other person who wants to use both our libraries at the same time is going to have a bad day. But, if we both used namespaces there's no problem since he/she can then distinguish the functions as myNamespace::calculateStuff() and yourNamespace::calculateStuff() and there's no ambiguity.
For example: std::shared_ptr vs boost::shared_ptr. Without namespaces you wouldn't be able to use both in the same program as the name shared_ptr would be ambiguous.
"[Named] Namespaces" are, as the name perhaps suggests, a way to subdivide the identifier space. In addition to solving literal conflicts ("you have more than one foo ..."), it also makes it considerably easier to find foo in a big, mature program that might well consist of hundreds or even thousands of modules.
The "name" of a variable or routine might(?) suggest what it is, but might not give any clue as to where it is, nor the context (not a technical term) of what it relates to: "it's just one name among many thousands." But, if you now group these into intelligently-chosen namespaces, you're adding a level of helpful organization to them. In a typical "great big program," especially one that is (as is also typical ...) "not entirely familiar to you," this extra level of bread-crumbs is a big bonus.
Simply put, namespaces allow to use the same names for different contexts.
Let's say you want to create two functions that take the same parameters and output text in two different ways, for the sake of simplicity you'd want to call them both print().
Since they both take the same parameters, there is no chance for function overloading here, but if you put each function in a separate namespace and then you call print(), you can simply change what the function will be doing by calling a different namespace each time.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
In C/C++, are global variables as bad as my professor thinks they are?
The problem with global variables is that since every function has access to these, it becomes increasingly hard to figure out which functions actually read and write these variables.
To understand how the application works, you pretty much have to take into account every function which modifies the global state. That can be done, but as the application grows it will get harder to the point of being virtually impossible (or at least a complete waste of time).
If you don't rely on global variables, you can pass state around between different functions as needed. That way you stand a much better chance of understanding what each function does, as you don't need to take the global state into account.
The important thing is to remember the overall goal: clarity
The "no global variables" rule is there because most of the time, global variables make the meaning of code less clear.
However, like many rules, people remember the rule, and not what the rule was intended to do.
I've seen programs that seem to double the size of the code by passing an enormous number of parameters around simply to avoid the evil of global variables. In the end, using globals would have made the program clearer to those reading it. By mindlessly adhering to the word of the rule, the original programmer had failed the intent of the rule.
So, yes, globals are often bad. But if you feel that in the end, the intent of the programmer is made clearer by the use of global variables, then go ahead. However, remember the drop in clarity that automatically ensues when you force someone to access a second piece of code (the globals) to understand how the first piece works.
My professor used to say something like: using global variables are okay if you use them correctly. I don't think I ever got good at using them correctly, so I rarely used them at all.
The problem that global variables create for the programmer is that it expands the inter-component coupling surface between the various components that are using the global variables. What this means is that as the number of components using a global variable increases, the complexity of the interactions can also increase. This increased coupling usually makes defects easier to inject into the system when making changes and also makes defects harder to diagnose and correct. This increase coupling can also reduce the number of available options when making changes and it can increase the effort required for changes as often one must trace through the various modules that are also using the global variable in order to determine the consequences of changes.
The purpose of encapsulation, which is basically the opposite of using global variables, is to decrease coupling in order to make understanding and changing the source easier and safer and more easily tested. It is much easier to use unit testing when global variables are not used.
For example if you have a simple global integer variable that is being used as an enumerated indicator that various components use as a state machine and you then make a change by adding a new state for a new component, you must then trace through all the other components to ensure that the change will not affect them. An example of a possible problem would be if a switch statement to test the value of the enumeration global variable with case statements for each of the current values is being used in various places and it so happens that some of the switch statements do not have a default case to handle an unexpected value for the global all of a sudden you have undefined behavior so far as the application is concerned.
On the other hand the use of a shared data area might be used to contain a set of global parameters which are referenced throughout the application. This approach is often used with embedded applications with small memory footprints.
When using global variables in these sort of applications typically the responsibility for writing to the data area is allocated to a single component and all other components see the area as const and read from it, never writing to it. Taking this approach limits the problems that can develop.
A few problems from global variables which need to be worked around
When the source for a global variable such as a struct is modified, everything using it must be recompiled so that everything using the variable knows its true size and memory template.
If more than one component can modify the global variable you can run into problems with inconsistent data being in the global variable. With a multi-threading application, you will probably need to add some kind of locking or critical region to provide a way so that only one thread at a time can modify the global variable and when a thread is modifying the variable, all changes are complete and committed before other threads can query the variable or modify it.
Debugging a multi-threaded application that uses a global variable can be more difficult. You can run into race conditions that can create defects that are difficult to replicate. With several components communicating through a global variable, especially in a multi-threaded application, being able to know what component is changing the variable when and how it is changing the variable can be very difficult to understand.
Name clash can be a problem with using of global variables. A local variable that has the same name as a global variable can hide the global variable. You also run into the naming convention issue when using the C programming language. A work around is to divide the system up into sub-systems with the global variables for a particular sub-system all beginning with the same first three letters (see this on resolving name space collisions in objective C). C++ provides namespaces and with C you can work around this by creating a globally visible struct whose members are various data items and pointers to data and functions which are provided in a file as static hence with file visibility only so that they can only be referenced through the globally visible struct.
In some cases the original application intent is changed so that global variables that provided the state for a single thread is modified to allow several duplicate threads to run. An example would be a simple application designed for a single user using global variables for state and then a request comes down from management to add a REST interface to allow remote applications to act as virtual users. So now you run into having to duplicate the global variables and their state information so that the single user as well as each of the virtual users from remote applications have their own, unique set of global variables.
Using C++ namespace and the struct Technique for C
For the C++ programming language the namespace directive is a huge help in reducing the chances of a name clash. namespace along with class and the various access keywords (private, protected, and public) provide most of the tools you need to encapsulate variables. However the C programming language doesn't provide this directive. This stackoverflow posting, Namespaces in C , provides some techniques for C.
A useful technique is to have a single memory resident data area that is defined as a struct which has global visibility and within this struct are pointers to the various global variables and functions that are being exposed. The actual definitions of the global variables are given file scope using the static keyword. If you then use the const keyword to indicate which are read only, the compiler can help you to enforce read only access.
Using the struct technique can also encapsulate the global so that it becomes a kind of package or component that happens to be a global. By having a component of this kind it becomes easier to manage changes that affect the global and the functionality using the global.
However while namespace or the struct technique can help manage name clashes, the underlying problems of inter-component coupling which the use of globals introduces especially in a modern multi-threaded application, still exist.
Global variables should only be used when you have no alternative. And yes, that includes Singletons. 90% of the time, global variables are introduced to save the cost of passing around a parameter. And then multithreading/unit testing/maintenance coding happens, and you have a problem.
So yes, in 90% of the situations global variables are bad. The exceptions are not likely to be seen by you in your college years. One exception I can think off the top of my head is dealing with inherently global objects such as interrupt tables. Things like DB connection seem to be global, but ain't.
Global variables are as bad as you make them, no less.
If you are creating a fully encapsulated program, you can use globals. It's a "sin" to use globals, but programming sins are laregly philosophical.
If you check out L.in.oleum, you will see a language whose variables are solely global. It's unscalable because libraries all have no choice but to use globals.
That said, if you have choices, and can ignore programmer philosophy, globals aren't all that bad.
Neither are Gotos, if you use them right.
The big "bad" problem is that, if you use them wrong, people scream, the mars lander crashes, and the world blows up....or something like that.
Yes, but you don't incur the cost of global variables until you stop working in the code that uses global variables and start writing something else that uses the code that uses global variables. But the cost is still there.
In other words, it's a long term indirect cost and as such most people think it's not bad.
If it's possible your code will end up under intensive review during a Supreme Court trial, then you want to make sure to avoid global variables.
See this article:
Buggy breathalyzer code reflects importance of source review
There were some problems with the
style of the code that were identified
by both studies. One of the stylistic
issues that concerned the reviewers
was the extensive use of unprotected
global variables. This is considered
poor form because it increases the
risk that the program state will
become inconsistent or that values
will be inadvertently modified or
overwritten. The researchers also
expressed some concern about the fact
that decimal precision is not
maintained consistently throughout the
code.
Man, I bet those developers are wishing they hadn't used global variables!
The issue is less that they're bad, and more that they're dangerous. They have their own set of pros and cons, and there are situations where they're either the most efficient or only way to achieve a particular task. However, they're very easy to misuse, even if you take steps to always use them properly.
A few pros:
Can be accessed from any function.
Can be accessed from multiple threads.
Will never go out of scope until the program ends.
A few cons:
Can be accessed from any function, without needing to be explicitly dragged in as a parameter and/or documented.
Not thread-safe.
Pollutes the global namespace and potentially causes name collisions, unless measures are taken to prevent this.
Note, if you will, that the first two pros and the first two cons I listed are the exact same thing, just with different wording. This is because the features of a global variable can indeed be useful, but the very features that make them useful are the source of all their problems.
A few potential solutions to some of the problems:
Consider whether they're actually the best or most efficient solution for the problem. If there are any better solutions, use that instead.
Put them in a namespace [C++] or singleton struct [C, C++] with a unique name (a good example would be Globals or GlobalVars), or use a standardised naming convention for global variables (such as global_[name] or g_module_varNameStyle (as mentioned by underscore_d in the comments)). This will both document their use (you can find code that uses global variables by searching for the namespace/struct name), and minimise the impact on the global namespace.
For any function that accesses global variables, explicitly document which variables it reads and which it writes. This will make troubleshooting easier.
Put them in their own source file and declare them extern in the associated header, so their use can be limited to compilation units that need to access them. If your code relies on a lot of global variables, but each compilation unit only needs access to a handful of them, you could consider sorting them into multiple source files, so it's easier to limit each file's access to global variables.
Set up a mechanism to lock and unlock them, and/or design your code so that as few functions as possible need to actually modify global variables. Reading them is a lot safer than writing them, although thread races may still cause problems in multithreaded programs.
Basically, minimise access to them, and maximise name uniqueness. You want to avoid name collisions and have as few functions as possible that can potentially modify any given variable.
Whether they're good or bad depends on how you use them. The majority tend to use them badly, hence the general wariness towards them. If used properly, they can be a major boon; if used poorly, however, they can and will come back to bite you when and how you least expect it.
A good way to look at it is that they themselves aren't bad, but they enable bad design, and can multiply the effects of bad design exponentially.
Even if you don't intend to use them, it is better to know how to use them safely and choose not to, than not to use them because you don't know how to use them safely. If you ever find yourself in a situation where you need to maintain pre-existing code that relies on global variables, you may be in for difficulty if you don't know how to use them properly.
I'd answer this question with another question: Do you use singeltons/ Are singeltons bad?
Because (almost all) singelton usage is a glorified global variable.
As someone said (I'm paraphrasing) in another thread "Rules like this should not be broken, until you fully understand the consequences of doing so."
There are times when global variables are necessary, or at least very helpful (Working with system defined call-backs for example). On the other hand, they're also very dangerous for all of the reasons you've been told.
There are many aspects of programming that should probably be left to the experts. Sometimes you NEED a very sharp knife. But you don't get to use one until you're ready...
Global variables are generally bad, especially if other people are working on the same code and don't want to spend 20mins searching for all the places the variable is referenced. And adding threads that modify the variables brings in a whole new level of headaches.
Global constants in an anonymous namespace used in a single translation unit are fine and ubiquitous in professional apps and libraries. But if the data is mutable, and/or it has to be shared between multiple TUs, you may want to encapsulate it--if not for design's sake, then for the sake of anybody debugging or working with your code.
Using global variables is kind of like sweeping dirt under a rug. It's a quick fix, and a lot easier in the short term than getting a dust-pan or vacuum to clean it up. However, if you ever end up moving the rug later, you're gonna have a big surprise mess underneath.
I think your professor is trying to stop a bad habit before it even starts.
Global variables have their place and like many people said knowing where and when to use them can be complicated. So I think rather than get into the nitty gritty of the why, how, when, and where of global variables your professor decided to just ban. Who knows, he might un-ban them in the future.
Global variables are bad, if they allow you to manipulate aspects of a program that should be only modified locally. In OOP globals often conflict with the encapsulation-idea.
Absolutely not. Misusing them though... that is bad.
Mindlessly removing them for the sake of is just that... mindless. Unless you know the advanatages and disadvantages, it is best to steer clear and do as you have been taught/learned, but there is nothing implicitly wrong with global variables. When you understand the pros and cons better make your own decision.
No they are not bad at all. You need to look at the (machine) code produced by the compiler to make this determination, sometimes it is far far worse to use a local than a global. Also note that putting "static" on a local variable is basically making it a global (and creates other ugly problems that a real global would solve). "local globals" are particularly bad.
Globals give you clean control over your memory usage as well, something far more difficult to do with locals. These days that only matters in embedded environments where memory is quite limited. Something to know before you assume that embedded is the same as other environments and assume the programming rules are the same across the board.
It is good that you question the rules being taught, most of them are not for the reasons you are being told. The most important lesson though is not that this is a rule to carry with you forever, but this is a rule required to honor in order to pass this class and move forward. In life you will find that for company XYZ you will have other programming rules that you in the end will have to honor in order to keep getting a paycheck. In both situations you can argue the rule, but I think you will have far better luck at a job than at school. You are just another of many students, your seat will be replaced soon, the professors wont, at a job you are one of a small team of players that have to see this product to the end and in that environment the rules developed are for the benefit of the team members as well as the product and the company, so if everyone is like minded or if for the particular product there is good engineering reason to violate something you learned in college or some book on generic programming, then sell your idea to the team and write it down as a valid if not the preferred method. Everything is fair game in the real world.
If you follow all of the programming rules taught to you in school or books your programming career will be extremely limited. You can likely survive and have a fruitful career, but the breadth and width of the environments available to you will be extremely limited. If you know how and why the rule is there and can defend it, thats good, if you only reason is "because my teacher said so", well thats not so good.
Note that topics like this are often argued in the workplace and will continue to be, as compilers and processors (and languages) evolve so do these kinds of rules and without defending your position and possibly being taught a lesson by someone with another opinion you wont move forward.
In the mean time, then just do whatever the one that speaks the loudest or carries the biggest stick says (until such a time as you are the one that yells the loudest and carries the biggest stick).
I would like to argue against the point being made throughout this thread that it makes multi-threading harder or impossible per se. Global variables are shared state, but the alternatives to globals (e. g. passing pointers around) might also share state. The problem with multi-threading is how to properly use shared state, not whether that state happens to be shared through a global variable or something else.
Most of the time when you do multi-threading you need to share something. In a producer-consumer pattern for example, you might share some thread-safe queue that contains the work units. And you are allowed to share it because that data structure is thread-safe. Whether that queue is global or not is completely irrelevant when it comes to thread-safety.
The implied hope expressed throughout this thread that transforming a program from single-threaded to multi-threaded will be easier when not using globals is naive. Yes, globals make it easier to shoot yourself in the foot, but there's a lot of ways to shoot yourself.
I'm not advocating globals, as the other points still stand, my point is merely that the number of threads in a program has nothing to do with variable scope.
Yes, because if you let incompetent programmers use them (read 90% especially scientists) you end up with 600+ global variable spread over 20+ files and a project of 12,000 lines where 80% of the functions take void, return void, and operate entirely on global state.
It quickly becomes impossible to understand what is going on at any one point unless you know the entire project.
Global variables are fine in small programs, but horrible if used the same way in large ones.
This means that you can easily get in the habit of using them while learning. This is what your professor is trying to protect you from.
When you are more experienced it will be easier to learn when they are okay.
Global are good when it comes to configuration . When we want our configuration/changes to have a global impact on entire project.
So we can change one configuration and the changes are directed to entire project . But I must warn you would have to be very smart to use globals .
Use of Global variables actually depends on the requirements. Its advantage is that,it reduces the overhead of passing the values repeatedly.
But your professor is right because it raises security issues so use of global variables should be avoided as much as possible. Global variables also create problems which are sometimes difficult to debug.
For example:-
Situations when the variables values is getting modified on runtime. At that moment its difficult to identify which part of code is modifying it and on what conditions.
In the end of the day, your program or app can still work but its a matter of being tidy and having a complete understanding of whats going on. If you share a variable value among all functions, it may become difficult to trace what function is changing the value(if the function does so) and makes debugging a million times harder
Sooner or later you will need to change how that variable is set or what happens when it is accessed, or you just need to hunt down where it is changed.
It is practically always better to not have global variables. Just write the dam get and set methods, and be gland you when you need them a day, week or month later.
I usually use globals for values that are rarely changed like singletons or function pointers to functions in dynamically loaded library. Using mutable globals in multithreaded applications tends to lead to hard to track bug so I try to avoid this as a general rule.
Using a global instead of passing an argument is often faster but if you're writing a multithreaded application, which you often do nowadays, it generally doesn't work very well (you can use thread-statics but then the performance gain is questionable).
In web applications within an enterprize can be used for holding session/window/thread/user specific data on the server for reasons of optimization and to preserve against loss of work where connection are unstable. As mentioned, race conditions need to be handled. We use a single instance of a class for this information and it is carefully managed.
security is less means any one can manipulate the variables if they are declared global , for this one to explain take this example if you have balance as a global variable in your bank program the user function can manipulate this as well as bank officer can also manipulate this so there is a problem .only user should be given the read only and withdraw function but the clerk of the bank can add the amount when the user personally gives the cash in the desk.this is the way it works
In a multi-threaded application, use local variables in place of global variables to avoid a race condition.
A race condition occurs when multiple thread access a shared resource, with at least one thread having a write access to the data. Then, the result of the program is not predictable, and depends on the order of accesses to the data by different threads.
More on this here, https://software.intel.com/en-us/articles/use-intel-parallel-inspector-to-find-race-conditions-in-openmp-based-multithreaded-code
Are there any official C++ recommendations that concern with the amount of information that should be disclosed in a method name? I am asking because I can find plenty of references in Internet but none that really explains this.
I'm working on a C++ class with a method called calculateIBANAndBICAndSaveRecordChainIfChanged, which pretty well explains what the method does. A shorter name would be easier to remember and would need no intellisense or copy & paste to type. It would be less descriptive, true, but functionality is supposed to be documented.
calculateIBANAndBICAndSaveRecordChainIfChanged considered to be a bad function name, it breaks the rule of one-function-does-one-thing.
Reduce complexity
The single most important reason to create a routine is to reduce a program's complexity. Create a routine to hide information so that you won't need to think about it. Sure, you'll need to think about it when you write the routine. But after it's written, you should be able to forget the details and use the routine without any knowledge of its internal workings. Other reasons to create routines—minimizing code size, improving maintainability, and improving correctness—are also good reasons, but without the abstractive power of routines, complex programs would be impossible to manage intellectually.
You could simply break this function into below functions:
CalculateIBAN
CalculateBIC
SaveRecordChain
IsRecordChainChanged
To name a procedure, use a strong verb followed by an object
A procedure with functional cohesion usually performs an operation on an object. The name should reflect what the procedure does, and an operation on an object implies a verb-plus-object name. PrintDocument(), CalcMonthlyRevenues(), CheckOrderlnfo(), and RepaginateDocument() are samples of good procedure names.
Describe everything the routine does
In the routine's name, describe all the outputs and side effects. If a routine computes report totals and opens an output file, ComputeReportTotals() is not an adequate name for the routine. ComputeReportTotalsAndOpen-OutputFile() is an adequate name but is too long and silly. If you have routines with side effects, you'll have many long, silly names. The cure is not to use less-descriptive routine names; the cure is to program so that you cause things to happen directly rather than with side effects.
Avoid meaningless, vague, or wishy-washy verbs
Some verbs are elastic, stretched to cover just about any meaning. Routine names like HandleCalculation(), PerformServices(), OutputUser(), ProcessInput(), and DealWithOutput() don't tell you what the routines do. At the most, these names tell you that the routines have something to do with calculations, services, users, input, and output. The exception would be when the verb "handle" was used in the specific technical sense of handling an event.
Most of above points are referred from Code complete II. Other good books are Clean Code, The Clean Coder from Robert C. Martin
To answer the direct question, I don't think function names need to be memorable. It's nice if they are, but like you say this stuff is supposed to be documented. I can look it up.
calculateIBANAndBICAndSaveRecordChainIfChanged is too long for my taste. Aside from the inconvenience of having to c/p or auto-complete to even use them, my fear with long function names is that I don't read them properly either, so names with similar "shapes" start to look confusingly similar to one another.
So I would advise looking for a shorter name. There must be some reason why these operations (calculating two things, and conditionally saving a record chain) have been grouped together. That reason isn't described in the question, it lies somewhere in the specification or the history of your project. You should identify that reason and look to it for a more succinct function name.
When naming a function you can also consider what reasons[*] the function might change in future. Why are there two things (IBANA and BIC) that are calculated at the same time? What is the relationship between them? Can you identify the reason for doing both at once and then saving?
For example: they are the "acronyms" for this object, it's common to want to recalculate the acronyms all at once, and if you recalculate then naturally the changes need saving. Then call the function refreshAcronyms. Maybe there will be a third acronym in future.
For another example: what callers really want is to save the object if changed, and it's an additional chore that to preserve integrity of the stored data, I must always recalculate the IBANA and the BIC before saving. In that case, all the rest is necessary precursors to saving, so I can call the function saveRecordChain. Users of the public interface just need to know that the save function does what needs to be done. There might be a serializeToFile() function in the private interface that saves if changed without doing the extra stuff.
[*] I say "reasons" plural, but Robert C Martin defines the "single responsibility principle" to be that there is only one possible reason to change a well-designed function.
Ideally one method should do only one thing. And your method name should reflect what it does (that one thing), then only your program become readable.
It''s a matter of personal preference although I would think that calculateIBANAndBICAndSaveRecordChainIfChanged is too long and therefore difficult to read and code with (unless you're using a smart editor that can auto-complete)
Two further points:
The function needs to be broken down into smaller parts, as other
posters have suggested.
There's no law against commenting your headers to give a more
detailed description of the function there so you don't have to
build every aspect of its functionality into the name.
You read and write too many methods over the course of your career to remember their names. Most programmers would need to look up a name of a function from their language's standard library, let alone names of functions that their or their team developed! The most memorable function name would be of no use to someone maintaining your code and seeing the call for the first time. Moreover, good chances are that in six months you wouldn't remember it either!
That is why I recommend going for descriptive names first, and not worrying about the ease of memorization: after all, IDEs with intellisense are not going away any time soon (and they were introduced for a good reason - to address our memory limitations).
For personal interaction that would be enough and useful, but any way after completing the app you have to re-factor every function name to exactly what they intend to do. And if working in a group or in company make it sure that function name reflects what its functionality is.
And in your eg function name i may name it like: saveRecordWithRespctToIBANandBIC()
I am working on a motion control system, and will have at least 5 motors, each with parameters such as "gearbox ratio", "ticks per rev" "Kp", "Ki", "Kd", etc. that will be referenced upon construction of instances of the motors.
My question to StackOverflow is how should I organize these numbers? I know this is likely a preferential thing, but being new to coding I figure I could get some good opinions from you.
The three approaches I immediately see are as follows:
Write in the call to the constructor, either via variables or numbers-- PROS: limited coding, could be implemented in a way that it's easy to change, but possibly harder than #define's
Use #define's to accomplish similar to above -- PROS: least coding, easy to change (assuming you want to look at the source code)
Load a file (possibly named "motorparameters.txt") and load the parameters into an array and populate from that array. If I really wanted to I could add a GUI approach to changing this file rather than manual. -- PROS:easiest to change without diving into source code.
These parameters could change over time, and while there are other coders at the company, I would like to leave it in a way that's easy to configure. Do any of you see a particular benefit of #define vs. variables? I have a "constants.h" file already that I could easily add the #defines to, or I could add variables near the call to the constructor.
There's a principle know as YAGNI (You Ain't Gonna Need It) which says do the simplest thing first, then change it when (if) your requirements expand.
Sounds to me like the thing to do is:
Write a flexible motor class, that can handle any values (within reason), even though there are only 5 different sets of values you currently care about.
Define a component that returns the "right" values for the 5 motors in your system (or that constructs the 5 motors for your system using the "right values")
Initially implement that component to use some hard-coded values out of a header file
Retain the option to replace that component in future with an implementation of the same API, but that reads values out of a resource file, text file, XML file, GUI interaction with the user, off the internet, by making queries to the hardware to find out what motors it thinks it has, whatever.
I say this on the basis that you minimize expected effort by putting in a point of customizability where you suspect you'll want one (to prevent a lot of work when you change it later), but implement using the simplest thing that satisfies your current certain requirements.
Some people might say that it's not actually worth doing the typing (a) to define the component, better just to construct 5 motors in main() (b) to use constants from a header file, better just to type numeric literals in main(). The (b) people are widely despised as peddlers of "magic constants" (which doesn't mean they're necessarily wrong about relative total programming time by implementer and future maintainers, they just probably are) and the (a) people divide opinion. I tend to figure that defining this kind of thing takes a few minutes, so I don't really care whether it's worth it or not. Loading the values out of a file involves specifying a file format that I might regret as soon as I encounter a real reason to customize, so personally I can't be bothered with that until the requirement arises.
The general idea is to separate the portions of your code that will change from those that won't. The more likely something is to change, the more you need to make it easy to change.
If you're building a commercial app where hundreds or thousands of users will use many different motors, it might make sense to code up a UI and store the data in a config file.
If this is development code and these parameters are unlikely to change, then stuffing them into #defines in your constants.h file is probably the way to go.
Number 3 is a great option if you don't have security or IP concerns. Anytime you or someone else touches your code, you introduce the possibility of regressions. By keeping your parameters in a text file, not only are you making life easier on yourself, you're also reducing the scope of possible errors down the road.
I can understand the use for one level of namespaces. But 3 levels of namespaces. Looks insane. Is there any practical use for that? Or is it just a misconception?
Hierarchical namespaces do have a use in that they allow progressively more refined definitions. Certainly a single provider may produce two classes with the same name. Often the first level is occupied by the company name, the second specifies the product, the third (and possibly more) my provide the domain.
There are also other uses of namespace segregation. One popular situation is placing the base classes for a factory pattern in its own namespace and then derived factories in their own namespaces by provider. E.g. System.Data, System.Data.SqlClient and System.Data.OleDbClient.
Obviously it's a matter of opinion. But it really boils down to organization. For example, I have a project which has a plugin api that has functions/objects which look something like this:
plugins::v1::function
When 2.0 is rolled out they will be put into the v2 sub-namespace. I plan to only deprecate but never remove v1 members which should nicely support backwards compatibility in the future. This is just one example of "sane" usage. I imagine some people will differ, but like I said, it's a matter of opinion.
Big codebases will need it. Look at boost for an example. I don't think anyone would call the boost code 'insane'.
If you consider the fact that at any one level of a hierarchy, people can only comprehend somewhere very roughly on the order of 10 items, then two levels only gives you 100 maximum. A sufficiently big project is going to need more, so can easily end up 3 levels deep.
I work on XXX application in my company yyy, and I am writing a GUI subsystem. So I use yyy::xxx::gui as my namespace.
You can easily find yourself in a situation when you need more than one level. For example, your company has a giant namespace for all of its code to separate it from third party code, and you are writing a library which you want to put in its own namespace. Generally, whenever you have a very large and complex system, which is broken down hierarchically, it is reasonable to use several namespace levels.
It depends on your needs and programming style. But one of the benefits of namespace is to help partition name space (hence the name). With a single namespace, as your project is increases in size and complexity, so does the likelihood of name-collision.
If you're writing code that's meant to be shared or reused, this becomes even more important.
I agree for applications. Most people that use multiple levels of namespaces (in my experience) come from a Java or .NET background where the noise is significantly less. I find that good class prefixes can take the place of multiple levels of namespaces.
But I have seen good use of multiple namespace levels in boost (and other libraries). Everything is in the boost namespace, but libraries are allowed (encouraged?) to be in their own namespace. For example - boost::this_thread namespace. It allows things like...
boost::this_thread::get_id()
boost::this_thread::interruption_requested()
"this_thread" is just a namespace for a collection of free functions. You could do the same thing with a class and static functions (i.e. the Java way of defining a free function), but why do something unnatural when the language has a natural way of doing it?
Just look at the .Net base class library to see a namespace hierarchy put to good use. It goes four or five levels deep in a few places, but mostly it's just two or three, and the organization is very nice for finding things.
The bigger the codebase the bigger the need for hierarchical namespaces. As your project gets bigger and bigger you find you need to break it out in ways to make it easier to find stuff.
For instance we currently use a 2 level hierarchy. However some of the bigger portions we are now talking about breaking them out into 3 levels.