Thirst for knowledge!

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
SPR_Phantom
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 21
Joined: Mon Oct 03, 2011 10:58 am

Thirst for knowledge!

Post by SPR_Phantom »

Hi.
So, I can program. Not great, but i can do the basics like functions, classes, pointers blah blah blah.
But now I want to be able to program properly, I'm a C++ programmer and my design would make even the sloppy coders a little worried, I want to be able to code without worrying that I'm going to have to go back and redesign everything just because I can't tell what's going on in my own program anymore, don't get me wrong, I don't mind rewriting my code but only if it's for a reason I couldn't foresee from the start.

So what would you guys recommend? are there any specific books, videos, articles and the like on properly using C++ in clean and beautiful ways? or should I just keep hammering at my technique until I eventually get it right?

maybe we could turn this in to a topic specifically directed at learning to use C++ objects etc to their proper and full extent? I know we have an educational topic already, but from my quick skim of it I didn't pick out anything like this :).
Aleios
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 78
Joined: Mon Feb 21, 2011 2:55 am
Current Project: Aleios Engine
Favorite Gaming Platforms: PC, Dreamcast
Programming Language of Choice: C++
Location: Melbourne, Australia

Re: Thirst for knowledge!

Post by Aleios »

This is, in a sense, pretty controversial. There really is no one way to code. Sure there might be some common patterns of which people follow but in the end it's really up to you how you structure things.
More importantly, it's usually based on what you are coding. Are you coding games? if so, what components would you need? (Audio, Graphics, Input, etc;).

I'm creating a framework for cross-platform development (kind of like SDL/SFML) that is based upon "Modules" that can be "mixed and matched" to suit the application. Some might believe that a more centralized approach would be best.

When i code i would generally want to have some sort of base design before hand. i would add to the base design as i went along. There are articles out there that show some design patterns, but it is kind of all up to you in the end. But that's just my opinion.

Also, would you mind sharing an example? i am quite interested to see this code style that you fear :P
Image
SPR_Phantom
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 21
Joined: Mon Oct 03, 2011 10:58 am

Re: Thirst for knowledge!

Post by SPR_Phantom »

Brilliant response and I agree completely, but I would definitely like to see some literature based on the subject :).


I'll show you one of my class declarations:

Code: Select all

class character
{
    private:
    int health;
    int xpos;
    int ypos;
    float exactx;
    float exacty;
    char block;
    entitycell ecp;
    public:
    entitycell inventory[4][7];
        character();
        void readplayerinfo();
        void saveplayerinfo();
        void addtoinventory(entitycell toadd);
        int checkinvfull();
        void saveinv();//writes the inventory to file
        void readinv(); //reads the inventory from the file into the array, pretty nifty stuff.
        int moveup();
        int movedown();
        int moveleft();
        int moveright();
        entitycell checkentity();
        int checkstate();
        void inittargetblock(char targetblock);
        int checkx();
        int checky();
        int checkhp();
};
This class uses "entitycell" which is:

Code: Select all

class entitycell// a variable which holds an entity's information!
{
    public:
    int state; // 0 = nonesolid, 1 = solid
    int ecid;
    char ecsprite;
    int colour;
    bool isitem;
    entitycell();
    void ecellrefresh();
};
I was actually criticized by someone upon showing them these, but they didn't really explain why they despised it! I'm worried I'm not using things to their full potential.
There's also a bad/lazy bit of code in there, which is that my inventory is public because I was too lazy to pass it through a method.
Aleios
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 78
Joined: Mon Feb 21, 2011 2:55 am
Current Project: Aleios Engine
Favorite Gaming Platforms: PC, Dreamcast
Programming Language of Choice: C++
Location: Melbourne, Australia

Re: Thirst for knowledge!

Post by Aleios »

Hmm, i see. Well my first criticism of your character class would be grouping. Its more of an aesthetic thing rather than compiler wise (sort of). For example:

Code: Select all

    int health;
    int xpos;
    int ypos;
    float exactx;
    float exacty;
can be shortened to:

Code: Select all

    int health, xpos, ypos;
    float exactx, exacty;
also this:

Code: Select all

        int moveup();
        int movedown();
        int moveleft();
        int moveright()
i personally would change it to:

Code: Select all

int move(int direction);

//or i would do
enum DIRECTION { UP, DOWN, LEFT, RIGHT };
int move(DIRECTION direction);
Also, im not sure if checkx, checky, and checkhp are accessors or per update functions. If they are accessors then:

Code: Select all

const int GetX() const;
const int GetY() const;
const int GetHP() const;
where the first "const" says the returned value will be constant, and the last one basically says "i am not allowed to make changes to *this" (basically you cant edit a member variable)

or if they are per update then why not just:

Code: Select all

void Update();
and stick all that crap in there. I try to minimalize as much as possible.

The rest i would not be able to figure out without first hand knowledge. And if someone says it's crap without explaining why, then (since i am prone to raging) i would tell em to shove it up their ass in specific cases.

I can say with certainty that the code you showed is kind of ugly, however, i have seen worse! MUCH WORSE!
Hell, my code even looks like complete shit at times, but what i do is draw out a couple of rectangles, write down the class name (with relevance to its function).
Then i write what methods and member variables i shall expect it to contain. As shown by Gyro, whiteboards are just legendary for these things.

I am in no way an expert, far from it, but the above is just a small example of how i would structure things. I could post a few bits from my current project, some of it makes me scream when i wake up the next morning (or rather afternoon...)
Image
SPR_Phantom
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 21
Joined: Mon Oct 03, 2011 10:58 am

Re: Thirst for knowledge!

Post by SPR_Phantom »

Some interesting points, I'm never too sure when to make things const, simply because it's unclear (to me) in that example why you're using a constant value either side, as surely these values can't be altered by anything else since they are private anyway and our methods to check what they are merely give us some information.

for example, in my code I'm 99.99% sure that I can't go and do:

player1.checkx() = 1;

because that would be trying to edit a return value, or "the sum" of the method?

I agree and understand with the rest of what you've said, very good CC, thanks!

edit: also, I tabbed out of shopping for whiteboards to read this ;)
User avatar
short
ES Beta Backer
ES Beta Backer
Posts: 548
Joined: Thu Apr 30, 2009 2:22 am
Current Project: c++, c
Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
Programming Language of Choice: c, c++
Location: Oregon, US

Re: Thirst for knowledge!

Post by short »

SPR_Phantom wrote:Some interesting points, I'm never too sure when to make things const, simply because it's unclear (to me) in that example why you're using a constant value either side, as surely these values can't be altered by anything else since they are private anyway and our methods to check what they are merely give us some information.
By placing the const keyword, you allow the compiler to make certain optimizations, as well as enforcing semantics with code. For example,

Code: Select all

const int getX() const
The "const int" tells the compiler that this return value cannot be altered as an r-value. It must be converted to an l-value (by assigning it to a variable) then can be altered. It also allows the compiler to do such optimizations such as writing the result into read-only memory, which is oftentimes faster.

The const after getX() tells the compiler, this method will not modify any member variables of the object (allowing other behind the scenes optimizations to take place).

While it is common to use const exactly at is above, the following is a more concrete example:

Code: Select all

void whatevs()
{
    const int RANGE_MAX = 35;
    
    ...

    RANGE_MAX = 37; // compile error
}
The important take home lesson about the const keyword is it allows semantic intent to be enforced by the compiler.
If you don't want a variable to be altered, declare it const.
If you don't want a member function to change any member variables, place the const keyword after the method name (before the curly brace)

Back to the returning a const value. The distinction I made between about disallowing the callee of a function to modify the return value (as an r-value) is pretty complex (imho).

You can never do the following:

Code: Select all

++getX(); // compile error, error C2105: '++' needs l-value
However you can still do something like this:

Code: Select all

int value = getX();
++value;
Again it is all about semantic intent, do you want your return value being fucked with? If not, declare it as const and force them to convert your return value to a l-value.

Disclaimer, I've only learned about what an r-value and l-value are recently, through the new C++0x standard, when I was curious about the move-constructor. If someone sees something incorrect call me out, as I'd love to concertize my knowledge of them.

edit: I edited the above, but I'm not sure of a concrete example of how returning const int vs int would yield different results, perhaps it would just help the compiler with some optimizations. I'll post back if I discover anything new.
Last edited by short on Sun Oct 09, 2011 1:05 pm, edited 2 times in total.
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
SPR_Phantom
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 21
Joined: Mon Oct 03, 2011 10:58 am

Re: Thirst for knowledge!

Post by SPR_Phantom »

The "concrete" example of const was the one I was familiar with already, however I usually use #define for things like that.

Thanks for explaining it in detail, I can safely know which methods to apply that to and which to not now!

unfortunately I do like to fuck with the return values directly, but isn't that the optimized way of doing things anyway? since if you assigned the return value to a variable first you'd be taking up an extra x bytes of memory?

the const that stops the method itself altering the variable is very nice and I'll add that to all my none side-effect methods! 8-)

so yeah I'd love to know if it's more optimized to fuck with your return value or to put it in a box, then fuck with it ;)!

Again I'd love to know where you guys learn design rules like these in the first place, because I was taught there was such a thing as a class, etc and how they work, but never how they should work in relation to what you're doing with them, if you get me.
User avatar
short
ES Beta Backer
ES Beta Backer
Posts: 548
Joined: Thu Apr 30, 2009 2:22 am
Current Project: c++, c
Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
Programming Language of Choice: c, c++
Location: Oregon, US

Re: Thirst for knowledge!

Post by short »

The return value from the function still needs to be copied out.

It gets "copied out" when you do something like:

Code: Select all

if(getX() > 30)
or

Code: Select all

int x = getX()
It's not like your avoiding a copy either way.
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
User avatar
szdarkhack
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 61
Joined: Fri May 08, 2009 2:31 am

Re: Thirst for knowledge!

Post by szdarkhack »

SPR_Phantom wrote:unfortunately I do like to fuck with the return values directly, but isn't that the optimized way of doing things anyway? since if you assigned the return value to a variable first you'd be taking up an extra x bytes of memory?
Compilers are smart enough to optimize these copies much better than you could ever achieve in C++, so in my opinion, if you can make the code more clear and readable, do so and the compiler will take care of the rest.

Now, regarding your design issues, i would suggest that you check some nice C++ code and try to see how others are doing things. I don't have any links to share off the top of my head, but i'm sure it won't be too hard to find some. But, at the end of the day, the object oriented paradigm is there to serve YOU, not for you to serve IT. So, if you find that it makes things worse, don't do it. Do what you are more comfortable with to minimize your chances of having to recode something because of faulty design.

Also, a way that i *personally* learned better oop, is by coding in strictly oop languages such as Java or C#, nothing big, just test projects. These languages require oop and you will be "forced" to learn how to do it. Again, this worked for *me*, it might not work for you. I'm just putting it out there.

Keep trying, you'll get the hang of it :)
Aleios
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 78
Joined: Mon Feb 21, 2011 2:55 am
Current Project: Aleios Engine
Favorite Gaming Platforms: PC, Dreamcast
Programming Language of Choice: C++
Location: Melbourne, Australia

Re: Thirst for knowledge!

Post by Aleios »

SPR_Phantom wrote: Again I'd love to know where you guys learn design rules like these in the first place, because I was taught there was such a thing as a class, etc and how they work, but never how they should work in relation to what you're doing with them, if you get me.
Well, for classes i guess you could look at them like this. First look around you. What do you see? I would have to bet 100% on a computer or laptop. Maybe you have a couch, bed, desk, chair, etc; around you. Think of what we call them ultimately. They are Objects, these objects have certain functions, a chair is for sitting on, a bed for sleeping (sometimes ;) ). OOP or Object Oriented Programming can be used in such a way as this. So let's make a class named Computer. What functions will computer need to do? Well, one i could think of would be to TogglePower. Now for this function i would want some way to track if the power is on or off, so let's make a boolean value named "power". power will not need to be accessed directly by anything else, so let's make it a private member variable. And let's just make an accessor quickly.

Computer.hpp

Code: Select all

#ifndef COMPUTER_H
#define COMPUTER_H
class Computer
{
public:
   Computer();
   void TogglePower();
   const bool GetPowerState() const;
private:
   bool power;
};
#endif

Computer.cpp

Code: Select all

#include "Computer.hpp"

Computer::Computer()
   : power(false)
{
}

void Computer::TogglePower()
{
   power = !power;
}

const bool Computer::GetPowerState() const
{
   return power;
}
main.cpp

Code: Select all

#include "Computer.hpp"
#include <iostream>

int main(int argc, char* argv[])
{
  // Don't really need to dynamically allocate in this instance, but meh...
  Computer *computer = new Computer();
  
  std::cout << "The current state is: " << computer->GetPowerState() << "\nSetting new State...\n";
  
  computer->TogglePower();
  
  std::cout << "The new state is: " << computer->GetPowerState() << "\n";
  
  delete computer;

  // May need, keeps vc++ console up.
  std::cin.get();
  return 0;
}
Also, as stated above by the brilliant peoples, the compiler should be smart enough to do const optimization. It's really just a habit of mine as i do a lot of cross compiling and i have little faith in the compiler at times.
Image
SPR_Phantom
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 21
Joined: Mon Oct 03, 2011 10:58 am

Re: Thirst for knowledge!

Post by SPR_Phantom »

Some good examples there, thanks :)!

I never thought of using ! before a variable's name to invert it like that, very appropriate!

I'm having a crack at making my program look nice internally before I bind it with lua, if I can get the internals very clear it should be much easier ( I hope ) to implement lua, so here goes :D
Obscurity
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 16
Joined: Mon Oct 10, 2011 9:33 pm

Re: Thirst for knowledge!

Post by Obscurity »

SPR_Phantom wrote:I was actually criticized by someone upon showing them these, but they didn't really explain why they despised it! I'm worried I'm not using things to their full potential.
What is this non-sense you've decided to spew, youngster? You claim to be in college at the tender age of 17... Act your age!

[quote="YouTube message TO "SPR_Phantom" - 10/06/'11"]Hello, MaxRavelle.

First off, it looks like you've copied & pasted code you've found off of MSDN (the examples), and have made no attempt to learn them, or apply them in any reasonable sense.

Second off, I'm not sure how you managed to implement that frame limiter (I'll assume you copied someone elses code, or simply their idea), but it is very impressive to me. There are alternatives methods to creating a frame limiter with the console, but that, is a pretty universal approach. I like it. :)

Third off, you aren't using wrapper functions, which makes reading some of this stuff very difficult. You are using the 'raw' Win32 API, which is fine... But I prefer to create wrapper functions for readability purposes. If nothing else, use a #define macro like you did for the 'W' key (you named it: "Wk").

Fourth off, aside from the fact you have INDEED created a monolithic main.cpp file, the class organization (as you stated before) is horrendous! I do not like it AT all! I do not like how you named things either (that's of no consequence, personal preference).

I found it to be EXTREMELY difficult! To locate and follow stuff. I also noticed soon on that you used a "float" type when you're assigning it "double" values; I simply changed those float's to double's and it worked fine; That may be a difference between the GCC/VS compilers though.

The fact that you have it CONSTANTLY writing to the harddrive is BAD. You do NOT need to do that! It not only will wear out the harddrive faster, but wastes system resources (not that they are really necessary for a project of this magnitude (lack thereof)). Bad habits die hard though.

Fifth off, you are using GetAsyncKeyState instead of using the console's internal buffer to manipulate key input. With how you have this set up, I do not even need the window's focus to play the game!! Select the foreground, like your browser. Let the console over-lap on top of the browser. Press the "W, A, S, D" keys, and see your character move... Disastrous, no?

This is just a basis of ideas (criticism). If you'd like to see some source code, I'd be more than happy to provide some soon. However, I am going to bed soon. I work today from 16:00 to 18:00.

Talk to you later! :)"[/quote]

... Here is a partial copy of his reply shortly after (I can check my e-mail and post exact time/dates if anyone's interested):
[quote="YouTube message TO "SPR_Phantom" - 10/06/'11"]Thank you for your tips/criticisms, I have not yet had the chance to pick up good habits as this has been my first C++ project this side of 2011 and while I did have to read up again on how to do some of it I in no way stole any of my code or simply copy/pasted.[/quote]

Yet here it is, the same day I offered more explanation, and offered more help, and awaited an eagerness on his behalf or simply interest in the project idea altogether! More lies stacked upon lies! Why must you do so? I do not understand. It is absolutely unnecessary and unreasonable! It is ludicrous, SPR_Phantom. Please don't...
SPR_Phantom wrote:I was actually criticized by someone upon showing them these, but they didn't really explain why they despised it! I'm worried I'm not using things to their full potential.
If I have failed to explain myself in depth, then tell me so! So I may try again from another approach, one that you might understand better. Do not thank me for something you do not understand, SPR_Phantom. That only wastes BOTH our time, and creates frustration (as shown). I am fully well aware you have declined any further help, due to some estranged belief that I have attacked you on a personal basis, but I will offer my hand one last time...

Normally I would send this over YouTube, but that's irrelevant to me at this point, as I believe everyone should see this, as everyone who reads it will benefit from it in a positive way, hopefully. I will again explain more and more as to why I disliked the way you went about things in your simple game:
  • Monolithic main.cpp
    This is a MAJOR design flaw! It is hard to locate specifically what you need. Modifying the existing code-base becomes extremely frustrating, and difficult
  • Your syntax ("style of writing")
    I disagree with how everything was written, at random seeming, pieced together from different sources.
    - The macro at the beginning
    - The "cls()" function at the end
    - The irregular white spacing altogether
  • The naming of variables, classes, and functions
    "entitycell," "ecellrefresh," "ecid" are all hard for me to read
  • General DESIGN paradigm
    This seems to be lacking altogether! I see three monolithic classes: entitycell, area, and character
  • Reinventing the wheel
    You chose to create an ENTIRE class wrapper ("entitycell") dedicated to the console cells (color, position, etc) instead of using what's already there!
  • Reinventing the wheel x2 (the console IS an array ALREADY!!!)
    You implement an ENTIRE (duplicate) array to 'reference' the console within the "area" class
  • CONSTANT harddrive file writes
    There is NO point in continually updating the file every program iteration; This wears down the harddrive more than it needs to be. This also constantly OPENS and CLOSES the file, just asking for a corrupted save file when something malfunctions (power-outage just to name one)
  • Direct Win32 API calls - UGLY!
    Another personal preference, as stated in a YouTube PM once before: Wrapper functions do not only provide an 'easier' and 'more clear' way of calling library functions, but may provide MORE functionality, without constantly repeating code (see: C++ overloaded functions, C++ overloaded operators).
  • main() function
    Disgusting, cluster of unreadable crap! The error checking was fine. The lack of whitespace? NO! The awkward system of arbitrary seeming loops? Disgusting!!! That could've been done so, so!!! Much better!
There are more intricate aspects of your program I could criticize in larger amounts of detail, with more potential solutions (of my own), but that's not up to me. I would spend a lot more time than the half hour I've already spent creating, and formatting this reply if I did! I am simply here to say: I have attempted to help you COUNTLESS times before you joined this forum. This is the last try. I hope you heed my word, SPR_Phantom! :(

There were some potential solutions you'd mentioned you could do, over YouTube, such as keeping the GetAsyncKeyState() functions and simply 'working around' them to keep the wretched design that you have set up already (which leads me to believe you know of NO other way to, and are HIDING that fact!). I insisted you learn something new, such as the ReadConsoleInput() API call (among others). It's a SMALL amount of work for the LARGE SCALE amount of benefits you'd reap! There was other stuff, but I'll leave that to YOU to discuss and bring up. :)

Sorry about all the crap over IRC; I have not been feeling well lately, and honestly, the conversation regarding English was VERY stimulating to me. I should've taken it to a PM, but equally, you (whomever complained) could have squelched me just as easily. ;)
Post Reply