Basic Programming Knowledge Need Some Advice

Started by
27 comments, last by Oberon_Command 8 years, 8 months ago


My other suggestions would be to keep as little clutter out of your main file as much as possible. It's perfectly ok to move your functions into a separate header file. This example I am going to show you would be something that would probably get you screamed at in the professional enviorment... but for something this small... it'd be overkill to do it the proper way.

Please PLEASE don't put code in a header file. This defeats the whole purpose of a header file. Header files are great for prototyping functions/classes that need to be called from other source files. They are not a place to put code it just so you can "clean up" your main source file.

If you're concerned about cluttering up your main source file, then make multiple source files and include the function prototypes in a header file.

You even said, "This example I am going to show you would be something that would probably get you screamed at in the professional enviorment" so why would you offer this as advice to a beginner who's trying to learn the right way to do things?

And, FWIW, there's nothing wrong with prototyping a function in the same file it is defined, assuming it's only used in that file (and then, it should probably be declared static). I'm not sure why you are so against that.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Advertisement
I actually think xoxos is a bad programmer. When you first learn programming you think of the code as a way to communicate to the computer what to do. After many years of programming I (like many others) realized that humans will end up having to read your code (other humans, or you in a few months, which you can think of as another human), and clarity is the most important metric for your code (even beyond correctness, I think; although that is debatable).

My other suggestions would be to keep as little clutter out of your main file as much as possible. It's perfectly ok to move your functions into a separate header file. This example I am going to show you would be something that would probably get you screamed at in the professional enviorment... but for something this small... it'd be overkill to do it the proper way.


Please PLEASE don't put code in a header file. This defeats the whole purpose of a header file. Header files are great for prototyping functions/classes that need to be called from other source files. They are not a place to put code it just so you can "clean up" your main source file.

If you're concerned about cluttering up your main source file, then make multiple source files and include the function prototypes in a header file.

You even said, "This example I am going to show you would be something that would probably get you screamed at in the professional enviorment" so why would you offer this as advice to a beginner who's trying to learn the right way to do things?

And, FWIW, there's nothing wrong with prototyping a function in the same file it is defined, assuming it's only used in that file (and then, it should probably be declared static). I'm not sure why you are so against that.
I should probably rephrase this then. Move prototypes into headers.

On a side note. It is perfectly reasonable and almost common practice to have accessors defined in the header. Sometimes overrides.

Reason being is easier to edit. And you know exactly what data you are accessing and how.

Oh and FWI if you are going to tell me its ok to prototype and define in the same file, I am sure you can find a tolerance for the same with header files :P

I don't care for prototypes then defs somewhere else in the same file, because it makes reading the code a pain in the ass.
Reason being is easier to edit. And you know exactly what data you are accessing and how.

Oh and FWI if you are going to tell me its ok to prototype and define in the same file, I am sure you can find a tolerance for the same with header files

The counterargument to that, though, is that code in headers tends to cause more widespread recompilation because generally a header file exists to expose the declarations of types to other TUs, which must be recompiled if the header changes. They're not wholly equivalent.

Certainly if you have a small enough project that C++ recompilation isn't a massive performance drain, or if your header exists only for stylistic consistency and is only ever included by on TU, or if you really need certain functions inlined because your compiler can't do whole-program optimization or the like, it's a reasonable option. But it's costs should not be dismissed idly.

My view on single/double-letter variable names is that they are only acceptable in maths-heavy code where those single letters not only match the conventions of the math behind the actual task at hand, but it's very obvious from the context what conventions are being used. I get very grumpy when I see single-letter variable names outside of that context and I would not recommend doing that anywhere else.

For example, I would find the use of a variable called "dx" acceptable, but only in code relating to (eg.) physics or some other integration calculations. In cases like this, I would prefer it if the original equation (and perhaps an explanation thereof) is reproduced in a comment above. In fact, when I do this in my own code, I will often even include a URL (or even MLA citation!) to any reference material I used to derive the equation. My personal experience has been that if you're working from reference material, both citing that material and working as much as possible in the notation used therein that material will help you understand what you were doing a year from now. The less translation of notation you have to do between your own code and the reference material, the easier it will be to follow its meaning.

Note also that "acceptable" is not the same thing as "ideal," and I tend to write out full variable names everywhere else and sometimes even in maths-heavy code. This judgement matches coding conventions I have seen in multiple places.

Also, nobody commented on the fact that OP used "using namespace std" at the start of his translation unit? This is widely considered bad practice.
I completely agree with Alvaro and Oberon_Command. I name identifiers such that other people can glance at them and immediately know what to expect. Usually that means variable names consisting of a few wordsMashedTogether, but if we're dealing with some 3D data, members like "x", "y", and "z" are the obvious naming choice.

I even tend to give longer names to math-related variables just because I'm not as math-knowledgeable as many people are -- I'll forget what the variables mean if I don't name them something I can understand instantly.

Reason being is easier to edit. And you know exactly what data you are accessing and how.

Oh and FWI if you are going to tell me its ok to prototype and define in the same file, I am sure you can find a tolerance for the same with header files

The counterargument to that, though, is that code in headers tends to cause more widespread recompilation because generally a header file exists to expose the declarations of types to other TUs, which must be recompiled if the header changes. They're not wholly equivalent.

Certainly if you have a small enough project that C++ recompilation isn't a massive performance drain, or if your header exists only for stylistic consistency and is only ever included by on TU, or if you really need certain functions inlined because your compiler can't do whole-program optimization or the like, it's a reasonable option. But it's costs should not be dismissed idly.

I don't know about all of that.

Header Guards and Pragma's can reduce the majority of your issues. Your accessors and overloads won't be overly complicated that it will effect your performance by much. These are functions that are typically expected to be inlined anyways so it won't matter much. What does matter is how that code is actually compiled, in which you need to crack open it's Assembly. Accessing a pointer from another class... for instance will HORRIFICALLY BLOAT your code. But accessing a local data type is really only two or three instructions.

And your complier, while it may have an optimizing heuristic, only optimizes by heuristics that humans have programmed in. So... essentially you need to write in such a manner that the compiler can optimize your code, because it matches heuristics. Kinda like how your compiler won't automatically make an AoS a SoA when it really matters. Or change your multidimensional array's accessing in such a way that it's at it's optimal.

See this link here.

http://www.gdcvault.com/play/1021866/Code-Clinic-2015-How-to

EDIT:

At this point I am starting to notice, and suspect it's the same person who's quick on the down vote. Even after I provided credited information, legitimate advice and criticism. So consider this my formal resignation from this thread.

Header Guards and Pragma's can reduce the majority of your issues

Header guards do not prevent recompilation of TUs including a header that changes.

Your accessors and overloads won't be overly complicated that it will effect your performance by much.

These are functions that are typically expected to be inlined anyways so it won't matter much.

Very true, but not related to my point, which had nothing to do with runtime performance.

Accessing a pointer from another class... for instance will HORRIFICALLY BLOAT your code. But accessing a local data type is really only two or three instructions.

This depends far more on the context of the access than accessing a "pointer from another class" versus a "local data type" (by which I presume you mean a field of the type of which a given function is a member, as opposed to a local structure definition, which itself is purely a language construct). Both are cheap in some cases, more expensive in others; fundamentally they're addressing a fixed offset from a given location (the "pointer from another class" versus the "this" pointer). Neither case is likely to "bloat" the generated assembly significantly more than the other, and neither case is affected by the placement of the code in a header versus a source file, because the compiler only sees the single TU. It's all the same to it.

Even after I provided credited information, legitimate advice and criticism. So consider this my formal resignation from this thread.

Some of your information is incorrect or inaccurate, unfortunately, and I have a very low tolerance for incorrect information in the For Beginners forum. Especially when it is accompanied by the hostile attitude you're presenting with this "resigning from the thread" business. It suggests you care more about the prestige you expected your commentary to offer than actually helping the beginning in question, and that's not an attitude that is welcome in FB.
Also, nobody commented on the fact that OP used "using namespace std" at the start of his translation unit? This is widely considered bad practice.

Definitely worth mentioning, although it's made less egregious an offense by being scoped to a given source file instead of a header, where it becomes a true pollutant.

Also, nobody commented on the fact that OP used "using namespace std" at the start of his translation unit? This is widely considered bad practice.


Definitely worth mentioning, although it's made less egregious an offense by being scoped to a given source file instead of a header, where it becomes a true pollutant.


This is true, but I feel it would be even less egregious were it used in an even narrower scope - say, the functions wherein the std:: prefix could be shown to contribute to the unreadablility of the code. The whole point of namespaces is to name things - to hide the namespace across an entire translation unit rather dilutes their meaning, in my view.

Another critique I have of the original code snippet is that the functions are declared, then defined unnecessarily. In my own code, I generally prefer to only have a declaration of a function when it's absolutely needed. If I can get away with defining a function before the functions that call it, I will. This is particularly true if I have a function which is not intended to be referenced outside of its translation unit, whereupon I might also put it in an anonymous namespace to signify this intent. I think Tangletail already mentioned this objection.

This topic is closed to new replies.

Advertisement