Better program design?

J

JoeC

I am a self taught programmer and I have figured out most syntax but
desigining my programs is a challenge. I realize that there are many
ways to design a program but what are some good rules to follow for
creating a program?

I am writing a map game program. I created several objects: board
object that is an array of integers each number 0-5 is a kind of
terrain, a terrain object that is an array of terrain types and each
number of the map coresponds to a kind terrain on the map. Finally I
have a unit object:

#include "graphic.h"
#include "libs.h"
#include "board.h"

#ifndef UNIT_H
#define UNIT_H

class unit : public graphic{

std::map<char, coord> keys; //movement engine
coord n; //directions
coord s;
coord e;
coord w;

int xloc; //x location
int yloc; //ylocation
int r, g, b; //color
int attack; //attack factor
int defence; //defence facor
int move; //movemnt factor
int moved; //the number of factors used
void make();

public:
unit();
void SetGr(int, int, int, BYTE c[]); //sets graphic info
void SetData(int, int, int);//sets ofensive defensive and move facors
void Place(int, int); //puts on the map
void moveUD(int, int); //handled up down movment
//direction, cost to enter next space.
void moveLR(int, int);
void newMove(char, board *,terrain trn[]);
void show(HWND); //displays the unit
void reset(); //restes movemnt
int red(){return r;} //returns colors for display
int grn(){return g;}
int blu(){return b;}
int getXloc()const {return xloc;} //returns location
int getYloc()const {return yloc;}
bool canMove(); //still has movement factors left.


};


void unit::newMove(char ch, board * b, terrain trn[]){

int n, mv;
int tempX = xloc + keys[ch].x;
int tempY = yloc + keys[ch].y;

mv = trn[b->GetSpace(tempY, tempX)].move();
if(moved > 0 && mv != 0){
moved -= mv;
xloc = tempX;
yloc = tempY;
}
}

case VK_UP:

if(red){rteam[t1m].newMove('n',b,trn);}
else{ yteam[t2m].newMove('n',b,trn);}

This all works and my units move around the map but is it good design
to send up the board and terrain objects to the function? I am
planning to have a fight function and that may involve even ore
objects, that is units from both sides the map and the kind of terrain.


Are there some rules or guides I can go by to write better programs?
For example I was instructed to tell on ask objects to do things.
 
P

Phlip

JoeC said:
I am a self taught programmer and I have figured out most syntax but
desigining my programs is a challenge. I realize that there are many
ways to design a program but what are some good rules to follow for
creating a program?

Use a unit test rig, such as UnitTest++, and write test cases before you
write the code to pass the tests.

That simple step prevents many hours of debugging.
int xloc; //x location
int yloc; //ylocation

Next, after the code works, you should "refactor" to remove duplication. In
this case, you have a latent object called Point, with members x and y. Then
you can write Point loc; here, and you can re-use the Point everywhere that
you have x and y now.
int red(){return r;} //returns colors for display
int grn(){return g;}
int blu(){return b;}

Similary, a single accessor, here, would return a Color object.
int getXloc()const {return xloc;} //returns location
int getYloc()const {return yloc;}

And these
bool canMove(); //still has movement factors left.

Next, OO design is about replacing conditional statements (if and switch)
with polymorphism. If that were simply a method called virtual maybeMove(),
you could derive a MobileUnit from your Unit. Then Unit::maybeMove() would
do nothing, and MobileUnit::maybeMove() would move.

OO is about putting the behaviors inside the objects - not about stuffing
objects full of data and putting the behaviors outside them.
This all works and my units move around the map but is it good design
to send up the board and terrain objects to the function? I am
planning to have a fight function and that may involve even ore
objects, that is units from both sides the map and the kind of terrain.

Maybe or maybe not. The items shouldn't be global. If your design is
otherwise clean then this might be the best way.

More importantly, my other guidelines attempt to make a program's original
design less important than its tests. If you can upgrade the design after
the program works, you can use the program itself to learn what the best
design will be.
Are there some rules or guides I can go by to write better programs?
For example I was instructed to tell on ask objects to do things.

Google for these, with quotes:

"test driven development"
"refactoring"
"hollywood principle"
"dependency inversion principle"
 
J

JoeC

Phlip said:
Use a unit test rig, such as UnitTest++, and write test cases before you
write the code to pass the tests.

That simple step prevents many hours of debugging.


Next, after the code works, you should "refactor" to remove duplication. In
this case, you have a latent object called Point, with members x and y. Then
you can write Point loc; here, and you can re-use the Point everywhere that
you have x and y now.


Similary, a single accessor, here, would return a Color object.

Does that realy matter? It would be a structure much like a coord
struct. paint(obj.gcolor().r, obj.gcolor().b
paint(obj,r(),obj.b()...


And these


Next, OO design is about replacing conditional statements (if and switch)
with polymorphism. If that were simply a method called virtual maybeMove(),
you could derive a MobileUnit from your Unit. Then Unit::maybeMove() would
do nothing, and MobileUnit::maybeMove() would move.

I was trying to figure out how I could keep the move concept a seperate
object. I was able to derrive my unit class and terrain from my
graphic class. It may be a good idea to do the same with a color
class.

I try to avoid dynamic binding. The only thing I find it useful for is
putting simmilliar objects in the same container. The terrain and the
units are in different containers and are different objects.
OO is about putting the behaviors inside the objects - not about stuffing
objects full of data and putting the behaviors outside them.

I tried to put the behavior in the objects. I tell the objects what to
do. Can move is internal to the object. If you tell an object to move
when it dosn't have any movement points, it does nothing.
Maybe or maybe not. The items shouldn't be global. If your design is
otherwise clean then this might be the best way.

No my objects are not global. They are to enxtent so that they can be
created in the create part of the program and then are visible to
winproc part of the program. I am using win32 for graphics support.
More importantly, my other guidelines attempt to make a program's original
design less important than its tests. If you can upgrade the design after
the program works, you can use the program itself to learn what the best
design will be.

I have done some upgrade since I first wrote the program. Mostly I put
the workings of the move function in the object instead of outside of
it. But the problem is that I have several objects that influence each
other and I am worried that my functions will be too cumbersom and my
compiler will start to complain at times.
 
D

Daniel T.

"JoeC said:
I am a self taught programmer and I have figured out most syntax but
desigining my programs is a challenge. I realize that there are many
ways to design a program but what are some good rules to follow for
creating a program?

I am writing a map game program. I created several objects: board
object that is an array of integers each number 0-5 is a kind of
terrain, a terrain object that is an array of terrain types and each
number of the map coresponds to a kind terrain on the map. Finally I
have a unit object:

#include "graphic.h"
#include "libs.h"
#include "board.h"

#ifndef UNIT_H
#define UNIT_H

class unit : public graphic{

std::map<char, coord> keys; //movement engine
coord n; //directions
coord s;
coord e;
coord w;

int xloc; //x location
int yloc; //ylocation
int r, g, b; //color
int attack; //attack factor
int defence; //defence facor
int move; //movemnt factor
int moved; //the number of factors used

That's an awful lot of variables. I notice that 'newMove' only uses
keys, xloc, yloc, and moved. You may have more than one concept buried
in this class.

One idea that I found useful in the past... Get some graph paper (or use
a spreadsheet program.) List the member-variables in the first column,
and the member-functions in the first row. Then go through and put an X
in the cell of each member-function that uses that particular
member-variable. You may find that several of the variables are only
used in a proper subset of the functions, and they are only used in that
subset. If so, it would be a good idea to group them in a class.
void make();

public:
unit();
void SetGr(int, int, int, BYTE c[]); //sets graphic info
void SetData(int, int, int);//sets ofensive defensive and move facors
void Place(int, int); //puts on the map
void moveUD(int, int); //handled up down movment
//direction, cost to enter next space.
void moveLR(int, int);
void newMove(char, board *,terrain trn[]);
void show(HWND); //displays the unit
void reset(); //restes movemnt
int red(){return r;} //returns colors for display
int grn(){return g;}
int blu(){return b;}
int getXloc()const {return xloc;} //returns location
int getYloc()const {return yloc;}
bool canMove(); //still has movement factors left.


};


void unit::newMove(char ch, board * b, terrain trn[]){

int n, mv;
int tempX = xloc + keys[ch].x;
int tempY = yloc + keys[ch].y;

mv = trn[b->GetSpace(tempY, tempX)].move();
if(moved > 0 && mv != 0){
moved -= mv;
xloc = tempX;
yloc = tempY;
}
}

case VK_UP:

if(red){rteam[t1m].newMove('n',b,trn);}
else{ yteam[t2m].newMove('n',b,trn);}

This all works and my units move around the map but is it good design
to send up the board and terrain objects to the function?

I would limit the function to only the data it needs. I would be
inclined to, for example, only send the one cell from trn that the
function actually uses, or maybe limit it to just the int returned by
..move(). Doing so would remove the need to send the board to newMove at
all.
Are there some rules or guides I can go by to write better programs?
For example I was instructed to tell on ask objects to do things.

There are many heuristics. The book "Object-Oriented Design Heuristics"
by Riel has a bunch, "C++ Coding Standards" by Sutter and Alexandrescu
has a bunch, "Enough Rope to Shoot Youreelf in the Foot" by Holub has a
bunch, "Large Scale C++ Design" by Lakos has a bunch, the "Effective
C++" series by Meyers, the list goes on and on. Many of these books have
heuristics that conflict with heuristics from a different book. A few
even have heuristics that conflict within the same book! You have to
read the heuristics understand the motivation for them and decide for
yourself which is more relevant to your particular situation.

One book I think should be on every programmer's shelf and read at least
every other year... "The Pragmatic Programmer" by Hunt and Thomas.
 
J

JoeC

One idea that I found useful in the past... Get some graph paper (or use
a spreadsheet program.) List the member-variables in the first column,
and the member-functions in the first row. Then go through and put an X
in the cell of each member-function that uses that particular
member-variable. You may find that several of the variables are only
used in a proper subset of the functions, and they are only used in that
subset. If so, it would be a good idea to group them in a class.

I took that advice and did, it was redundant code from my terrain
class.

class color{
protected:
int r, g, b; //color red, green, blue

public:
color() : : r(0), g(0), b(0){}
int red(){return r;} //returns colors for display
int grn(){return g;}
int blu(){return b;}


class unit : public graphic
: public color{
I would limit the function to only the data it needs. I would be
inclined to, for example, only send the one cell from trn that the
function actually uses, or maybe limit it to just the int returned by
.move(). Doing so would remove the need to send the board to newMove at
all.

I did that and with all the directions I had lots of redundant code.

if(red){
n = b->GetSpace((rteam[t1m].getYloc()-1),
rteam[t1m].getXloc());
mv = trn[n].move(); //gets movemnt cost
rteam[t1m].moveUD(-1,mv); //moves
} else {
n = b->GetSpace((yteam[t2m].getYloc()-1),
yteam[t2m].getXloc());
mv = trn[n].move();
yteam[t2m].moveUD(-1,mv);
}

to:

case VK_UP:

if(red){rteam[t1m].newMove('n',b,trn);}
else{ yteam[t2m].newMove('n',b,trn);}
break;
There are many heuristics. The book "Object-Oriented Design Heuristics"
by Riel has a bunch, "C++ Coding Standards" by Sutter and Alexandrescu
has a bunch, "Enough Rope to Shoot Youreelf in the Foot" by Holub has a
bunch, "Large Scale C++ Design" by Lakos has a bunch, the "Effective
C++" series by Meyers, the list goes on and on. Many of these books have
heuristics that conflict with heuristics from a different book. A few
even have heuristics that conflict within the same book! You have to
read the heuristics understand the motivation for them and decide for
yourself which is more relevant to your particular situation.

One book I think should be on every programmer's shelf and read at least
every other year... "The Pragmatic Programmer" by Hunt and Thomas.

OK, I have been looking into getting a design book but not sure which
ones are worth it. I have been looking into the mythical man of the
month.

I realy appreciate this advice. I do take it and try to create better
programs.
 
P

Phlip

JoeC said:
Does that realy matter? It would be a structure much like a coord
struct. paint(obj.gcolor().r, obj.gcolor().b
paint(obj,r(),obj.b()...

Why does your Color object have accessors? It's just a data bucket.

Either way, what matters is replacing duplication with structure. Maybe a
higher-level paint() method can take a Color object. Or maybe a lower-level
one needs raw values.

We don't have enough evidence to tell, but we both know the present
situation - getting and setting everything - will lead to sloppy code.
I was trying to figure out how I could keep the move concept a seperate
object. I was able to derrive my unit class and terrain from my
graphic class. It may be a good idea to do the same with a color
class.

I try to avoid dynamic binding.

You may want to read /Design Patterns/, to see good examples of OO designs.
You should use dynamic binding when it makes the code simpler, and there are
many ways to do that.
 
J

JoeC

Phlip said:
Why does your Color object have accessors? It's just a data bucket.

Either way, what matters is replacing duplication with structure. Maybe a
higher-level paint() method can take a Color object. Or maybe a lower-level
one needs raw values.
I took some advice and did:

class unit : public graphic, public color{

class color{
protected:
int r, g, b; //color red, green, blue

public:
color() : r(0), g(0), b(0){}
int red(){return r;} //returns colors for display
int grn(){return g;}
int blu(){return b;}
};

It eliminates redundant code in both the unit and terrain objects. It
is basically a data bucket that holds color data. Used like:

for(int y = 0; y != b->GetSizeY(); y++){
for(int x = 0; x != b->GetSizeX(); x++){
if(b->GetSpace(y,x)){
num = b->GetSpace(y,x);
SetTextColor(hdc,RGB(trn[num].red(), trn[num].grn(),
trn[num].blu()));
trn[num].display(hwnd,convert(y),convert(x));
}
}
}
 
P

Phlip

JoeC said:
class color{
protected:
int r, g, b; //color red, green, blue

Why aren't these public?

There are two kinds of objects out there - class objects and structures.

Class objects store behavior, and structures store data. Of course either
might have a little of the other. But if your color object has no behavior,
then it has no reason to defend its data members. We can't cause a bug, for
example, by tweaking the red!

(We might max it out; that's a different topic...)

If you simply must make r,g,b private, then make the entire color class
private to the classes that use it.
SetTextColor(hdc,RGB(trn[num].red(), trn[num].grn(),
trn[num].blu()));

Always seek duplication to replace with structure. The above line duplicates
trn[num].

If you want to allow your color object to keep r,g,b private, and if the
above line is the only place where you access them, then you can remove
duplication simply by turning the line inside out:

trn[num].setTexColor(hdc);

All the RGB() stuff went inside a method of color.
 
J

Jerry Coffin

[ ... ]
I took some advice and did:

class unit : public graphic, public color{

I don't know whose advice you're taking here, but IMO, it's not very
good advice at all. Looking back at your original code, it doesn't seem
to me that a unit is substitutable for a color under all possible
circumstances. Quite the contrary, a Unit is not a color -- it's a thing
that has a color, so it should contain a color object, but should not be
derived from color (more on this below).
class color{
protected:
int r, g, b; //color red, green, blue

public:
color() : r(0), g(0), b(0){}
int red(){return r;} //returns colors for display
int grn(){return g;}
int blu(){return b;}
};

To the extent possible, a class should attempt to act as a coherent
whole, NOT simply a collection of pieces. Right now, you build a color
out of components, but the only way to use it seems to be to break it
back into the components. It's better for it to remain a whole thing
instead.
It eliminates redundant code in both the unit and terrain objects. It
is basically a data bucket that holds color data. Used like:

for(int y = 0; y != b->GetSizeY(); y++){
for(int x = 0; x != b->GetSizeX(); x++){
if(b->GetSpace(y,x)){
num = b->GetSpace(y,x);
SetTextColor(hdc,RGB(trn[num].red(), trn[num].grn(),
trn[num].blu()));
trn[num].display(hwnd,convert(y),convert(x));
}
}
}

In line with the above, I'd add something that allows most of the code
to deal with a color as a whole. You've got a couple of choices in that
direction. From the looks of things, you're programming for Windows,
which expects a color to be encapsulated in a DWORD. You could add a
cast to your color class to support that:

class color {
// ...
operator DWORD() { return RGB(r, g, b); }
// ...
};

Or you can add a function like:

SetTextColor(HDC hdc, color const &c) {
SetTextColor(hdc, RGB(c.red(), c.grn(), c.blu());
}

Either way, your code comes out something like:

SetTextColor(hdc, trn[num].c);

where 'c' is a member of type 'color'. Of the two, the cast operator is
less work, but also easier to misuse (often by accident) -- it makes it
easy to use a color anywhere a DWORD is expected, inlcuding places a
color doesn't make sense at all.

I've looked at the rest of the code in your posts, but you've left out
far too much detail to be able to provide much in the way of meaningful
comments on it. Just for some obvious examples:

void SetGr(int, int, int, BYTE c[]); //sets graphic info
void SetData(int, int, int);//sets ofensive defensive and move facors

With no description of what the parameters are/mean, we can't really
provide meaningful advice about whether what you have is close to
optimal, and/or how it could be improved. With that said, my immediate
guess is that the existence and description of SetGr indicates that you
probably have some subset of functionality related to graphics that
should be in a class of its own, and most of what's in SetGr should
probably be in a ctor for that class (with Unit containing an instance
of such an object).

Lacking the information to comment more directly on your code, I'm going
to make some more general observations. I would try to break things down
into a larger number of smaller pieces, each of which has a more
specific purpose. You've started in that direction with the color class,
but my immediate reaction would be that there's probably a lot more to
do in that direction.

Unit deriving from color is almost certainly a poor idea -- a reasonable
derivative of color would be something that represents only a more
speicific version of the same concept -- for example, reasonable
derivatives of "color" would be classes that represent the colors
available in specific color spaces (AdobeRGB, ProPhotoRGB, sRGB, etc.)
Having Unit derive from color is almost certainly a poor and problematic
design.

My immediate reaction would be that it's _probably_ better to make
movement into an algorithm that's applied to something rather than being
part of the Unit itself -- though that's something of a judgement call.
If Unit is the base class of anything and everything that can be moved,
it might make some sense to keep it as a member -- but IMO, such a base
class is probably a poor idea to stat with.

Code that deals specifically with individual key-strokes (e.g. VK_UP)
should definitely be moved into a class that deals only with input from
the user, and translates it to a logical signal. The remainder of the
program should be 100% oblivious if you decide to change it to use input
from a joystick or mouse instead of the keyboard, for example.

Commenting a bit on some other advice you've received: I'd take the
advice about test-driven programming with a grain of salt. While it's
useful, at least IMO, it's often over-sold (including this case). While
the technique itself has uses, I've yet to see good evidence that any of
the test-drive frameworks has real utility at all.

Likewise, the advice about design patterns -- while they can be a useful
thing to study, there's a decided tendency among people who study them
to try to push everything into patterns (especially ones that are new
and "exciting"), even if they don't really apply well to the situation.
Learning something about it can be useful, but it's easy to get to the
point that it hinders rather than helps get the job done.
 
R

ralph

JoeC said:
I try to avoid dynamic binding. The only thing I find it useful for is
putting simmilliar objects in the same container. The terrain and the
units are in different containers and are different objects.

But OO-design is almost always about dynamic binding. Most design
patterns use dynamic binding. Object-orientation implies polymorphism.
Why are you trying to avoid it? Is it speed? Virtual functions should
always be at least as fast as a corresponding switch statement.

Ralpe
 
J

JoeC

ralph said:
But OO-design is almost always about dynamic binding. Most design
patterns use dynamic binding. Object-orientation implies polymorphism.
Why are you trying to avoid it? Is it speed? Virtual functions should
always be at least as fast as a corresponding switch statement.

Ralpe

I know how to use it but have yet to find it the right tool for my
projects. Still dealing with pointers and creating handles is still a
bit above me.
 
J

JoeC

}
In line with the above, I'd add something that allows most of the code
to deal with a color as a whole. You've got a couple of choices in that
direction. From the looks of things, you're programming for Windows,
which expects a color to be encapsulated in a DWORD. You could add a
cast to your color class to support that:

class color {
// ...
operator DWORD() { return RGB(r, g, b); }
// ...
};

Or you can add a function like:

SetTextColor(HDC hdc, color const &c) {
SetTextColor(hdc, RGB(c.red(), c.grn(), c.blu());
}

Either way, your code comes out something like:

SetTextColor(hdc, trn[num].c);

where 'c' is a member of type 'color'. Of the two, the cast operator is
less work, but also easier to misuse (often by accident) -- it makes it
easy to use a color anywhere a DWORD is expected, inlcuding places a
color doesn't make sense at all.

I've looked at the rest of the code in your posts, but you've left out
far too much detail to be able to provide much in the way of meaningful
comments on it. Just for some obvious examples:

void SetGr(int, int, int, BYTE c[]); //sets graphic info
void SetData(int, int, int);//sets ofensive defensive and move facors

With no description of what the parameters are/mean, we can't really
provide meaningful advice about whether what you have is close to
optimal, and/or how it could be improved. With that said, my immediate
guess is that the existence and description of SetGr indicates that you
probably have some subset of functionality related to graphics that
should be in a class of its own, and most of what's in SetGr should
probably be in a ctor for that class (with Unit containing an instance
of such an object).

Lacking the information to comment more directly on your code, I'm going
to make some more general observations. I would try to break things down
into a larger number of smaller pieces, each of which has a more
specific purpose. You've started in that direction with the color class,
but my immediate reaction would be that there's probably a lot more to
do in that direction.

Unit deriving from color is almost certainly a poor idea -- a reasonable
derivative of color would be something that represents only a more
speicific version of the same concept -- for example, reasonable
derivatives of "color" would be classes that represent the colors
available in specific color spaces (AdobeRGB, ProPhotoRGB, sRGB, etc.)
Having Unit derive from color is almost certainly a poor and problematic
design.

My immediate reaction would be that it's _probably_ better to make
movement into an algorithm that's applied to something rather than being
part of the Unit itself -- though that's something of a judgement call.
If Unit is the base class of anything and everything that can be moved,
it might make some sense to keep it as a member -- but IMO, such a base
class is probably a poor idea to stat with.

Code that deals specifically with individual key-strokes (e.g. VK_UP)
should definitely be moved into a class that deals only with input from
the user, and translates it to a logical signal. The remainder of the
program should be 100% oblivious if you decide to change it to use input
from a joystick or mouse instead of the keyboard, for example.

Commenting a bit on some other advice you've received: I'd take the
advice about test-driven programming with a grain of salt. While it's
useful, at least IMO, it's often over-sold (including this case). While
the technique itself has uses, I've yet to see good evidence that any of
the test-drive frameworks has real utility at all.

Likewise, the advice about design patterns -- while they can be a useful
thing to study, there's a decided tendency among people who study them
to try to push everything into patterns (especially ones that are new
and "exciting"), even if they don't really apply well to the situation.
Learning something about it can be useful, but it's easy to get to the
point that it hinders rather than helps get the job done.

--
Later,
Jerry.

The universe is a figment of its own imagination.

Is there a way I can post the whole program?

I look at this advice and I do my best to incorperate it into my
programs. When I write programs I try also to implement what I have
learned and also try to solve the problems at hand. Some of the
details are good improvments but don't change the way my program works
overall. It is true that some tools I am weak on understanding like
operators, exception handling and what ever may become appearant
looking at my code. It may be that I am not awair how a tool may make
my code better. Many times I try to choose the best solution for the
problem from the tools that I have. There is also that I can only
learn so much or work with a limited number of concepts at one time.
In other words my program could be realy bad but I can only do so much
at one time to fix it. My main consern is the big stuff. How the
object interact is not very good and I am having trouble figuring out
how best have the terrain units and the board work together. If I can
do the color better add new units with dynamic binding or adding to my
game in the future great. I am in a tight spot because expansion is
dificult because my design while being the best I can come up with may
not be very good.

It also, it can be dificult to translase some small demo program from a
book to a project that I am working on. Finding good source code is
dificult for good examples. About 20 years ago I would get computer
magazines with games and programs in the back and they were very
helpful. Windows game programming is also very useful for me.

I have my some of my work posted at:

http://www.planetsourcecode.com/vb/...&txtCriteria=creaney&lngWId=3&B1=Quick+Search
 
P

Philip Potter

The above was written by Daniel T. Please don't remove attribution lines.
I took that advice and did, it was redundant code from my terrain
class.

class color{
protected:
int r, g, b; //color red, green, blue

public:
color() : : r(0), g(0), b(0){}
int red(){return r;} //returns colors for display
int grn(){return g;}
int blu(){return b;}


class unit : public graphic
: public color{

Is there any reason you chose to use inheritance to relate unit and color?
I'm not saying what you did was wrong, because there are no right or wrong
answers in design; but it did surprise me. I would have expected
composition:

class unit : public graphic {
color c;
// ...
unit(color c_) : c(c_) /*, other stuff */ { }
}

since a color is "part of" a unit, but a unit isn't a "kind of" color. See
the comp.lang.c++ FAQ, and have a read of the "inheritance" questions - but
question 19.2 is particularly appropriate here.
I realy appreciate this advice. I do take it and try to create better
programs.

Best of luck to you!

Philip
 
D

Daniel T.

One book I think should be on every programmer's shelf and read at least
every other year... "The Pragmatic Programmer" by Hunt and Thomas.

OK, I have been looking into getting a design book but not sure which
ones are worth it. I have been looking into the mythical man of the
month.[/QUOTE]

Do this, go to Amazon.com or some such and write down the title, author
name, publisher, and ISBN of the books you are interested in, then go to
your nearest library and ask them about inter-library loans. Tell them
you want to borrow the books. When the books you are interested in come
in, read through them and see if they are worth buying. That way you get
maximum learning with minimum expense.

Personally, I don't think Mythical Man Month would be a good book for
you, it covers more management issues and you are far from that stage.
 
J

JoeC

Is there any reason you chose to use inheritance to relate unit and color?
I'm not saying what you did was wrong, because there are no right or wrong
answers in design; but it did surprise me. I would have expected
composition:

class unit : public graphic {
color c;
// ...
unit(color c_) : c(c_) /*, other stuff */ { }
}

since a color is "part of" a unit, but a unit isn't a "kind of" color. See
the comp.lang.c++ FAQ, and have a read of the "inheritance" questions - but
question 19.2 is particularly appropriate here.
I did have the color data as part of the object. But it was a
duplication with another object. So what I did is just create a new
color object. Crating a color inside the object would have been more
work because I would still need to have the accessors to the color
functions:

if(b->GetSpace(y,x)){
num = b->GetSpace(y,x);
SetTextColor(hdc,RGB(trn[num].red(), trn[num].grn(),
trn[num].blu()));
trn[num].display(hwnd,convert(y),convert(x));

My thought proscess is that each thing has a different color each unit
and terrain is a graphic but each of the is a has-a relationship with
color. It has been suggested that I put the set text color inside the
color function.

I solve the problems that I create the best I can. I often decide on
my projects based on my skill. I think I can do X and I figure out how
to do it.
 
J

Jerry Coffin

[ ... ]
Is there a way I can post the whole program?

You seem to have already found one way. Seriously, it's probably a bit
overboard to try to post all of it here -- and probably not particularly
helpful either. Things like Windows message loops are fairly set, and
not really topical in any case. OTOH, it would be perfectly reasonable
(IMO, anyway) for you to post more of your code here, as long as the
code in question is at least reasonably topical -- something that
happens to refer to Windows-specific functions isn't necessarily a
problem, but something that's entirely Windows-specific wouldn't really
be topical here.

[ ... ]
There is also that I can only
learn so much or work with a limited number of concepts at one time.

Trust me -- we _all_ run into that on a regular basis!
In other words my program could be realy bad but I can only do so much
at one time to fix it.

What I've seen of your code doesn't look "really bad" to me -- open to
improvement, sure -- but then nearly all code is...
My main consern is the big stuff. How the
object interact is not very good and I am having trouble figuring out
how best have the terrain units and the board work together. If I can
do the color better add new units with dynamic binding or adding to my
game in the future great. I am in a tight spot because expansion is
dificult because my design while being the best I can come up with may
not be very good.

This is probably the single largest challenge in programming in general.
Nearly anybody can fairly easily write small bits of code that work
reasonably well. Making it scalable so you can put together a large
program that still works coherently is much more challenging.

[ ... ]
I have my some of my work posted [ ... ]

Doing a quick glance through one of these, a few things virtually jumped
out at me:

1) nearly complete lack of comments.
2) most things work at too literal of a level.

Some people advise against commenting much, and I they have a point --
it's easy to write silly comments, like:

direction = up; // set direction to up.

Simply echoing what's obvious from the code isn't useful. Comments
should typically explain what larger blocks of code are intended to
accomplish, and (in many cases) why that particular method was chosen --
e.g. I might include something like 'here we're using an insertion sort
because we expect most of the data to be sorted, with a small block of
items out of order at the end".

As far as being too literal. Things like this:

bool space::canMove(){
if(graphic != '#'){
return false;}
else {return true;}
}

Here the rest of the code seems to know how you've represented a space
that's occupied (or maybe impassable). I'd start with something like
this:

enum terrain_types { water, planes, hills, mountains, max_terrain };

Then, for example, when you want to move a particular direction, the
player is concerned with the type of terrain, NOT with how you happen to
be drawing it on the screen. Obviously there has to be SOME code that
knows how to draw mountains on the screen, but it should be restricted
to one piece of code that does essentially nothing else. In a few months
you might decide to change to draw things in real graphics instead of
character cells -- but a particular player's ability to walk across the
mountains shouldn't be affected by how you draw them. Sometime later you
might get still more ambitious and decide to change to use OpenGL to
draw fully-rendered 3D graphics of the terrain and players -- but the
logic should still remain the same.
 
N

Noah Roberts

JoeC said:
I am a self taught programmer and I have figured out most syntax but
desigining my programs is a challenge. I realize that there are many
ways to design a program but what are some good rules to follow for
creating a program?

http://c2.com/cgi/wiki?PrinciplesOfObjectOrientedDesign

Answers your question directly. The following derive from those.

http://c2.com/cgi/wiki?CodeSmell

http://www.soberit.hut.fi/mmantyla/BadCodeSmellsTaxonomy.htm

http://www.codinghorror.com/blog/archives/000589.html

http://www.refactoring.com
 
J

JoeC

Daniel said:
OK, I have been looking into getting a design book but not sure which
ones are worth it. I have been looking into the mythical man of the
month.

Do this, go to Amazon.com or some such and write down the title, author
name, publisher, and ISBN of the books you are interested in, then go to
your nearest library and ask them about inter-library loans. Tell them
you want to borrow the books. When the books you are interested in come
in, read through them and see if they are worth buying. That way you get
maximum learning with minimum expense.

Personally, I don't think Mythical Man Month would be a good book for
you, it covers more management issues and you are far from that stage.[/QUOTE]

I looked at that and came to the same conclusion. I have seen books
that look intersting but at times I don't rember tittles of the books.
I like AC++ and Rumination on C++ but it is a bit above me.

I don't think I am the firt person confronting these problems and I
awlays feel like I have to re-invent the wheel. I do the best I can.
 
J

JoeC

[ ... ]
I have my some of my work posted [ ... ]

Doing a quick glance through one of these, a few things virtually jumped
out at me:

1) nearly complete lack of comments.
2) most things work at too literal of a level. <-- What does that mean?

It could be a fatal flaw in my whole thought proscess.
enum terrain_types { water, planes, hills, mountains, max_terrain };

Then, for example, when you want to move a particular direction, the
player is concerned with the type of terrain, NOT with how you happen to
be drawing it on the screen. Obviously there has to be SOME code that
knows how to draw mountains on the screen, but it should be restricted
to one piece of code that does essentially nothing else. In a few months
you might decide to change to draw things in real graphics instead of
character cells -- but a particular player's ability to walk across the
mountains shouldn't be affected by how you draw them. Sometime later you
might get still more ambitious and decide to change to use OpenGL to
draw fully-rendered 3D graphics of the terrain and players -- but the
logic should still remain the same.

--
Later,
Jerry.

The universe is a figment of its own imagination.

Thanks for the encouragement. enumerated lists are weak point for me.
Somthing, I have read about but never realy used. I am not used to
working in programming teams or working with other people's code so I
don't realy know the best way to use comments. I would assume if I was
reading somone's code I and the questions I had would be how I would
use comments. For me my program is pretty obvious but I know what I
did in the program. I at times play with directX I have done small
things but I don't like the book I have too much is in C not C++ so it
is hard for me to follow.
 
J

Jerry Coffin

[ ... ]
I have my some of my work posted [ ... ]

Doing a quick glance through one of these, a few things virtually jumped
out at me:

1) nearly complete lack of comments.
2) most things work at too literal of a level. <-- What does that mean?

It could be a fatal flaw in my whole thought proscess.

I've taken a while to answer this, largely because it's a hard question
to answer well and I've had to think a while about how to say what I
mean and have any hope of getting my point across.

Good code is often a bit like an allegory -- many of the "characters"
are a lot more pure and idealized forms of some particular idea than
you'd usually deal with in real life. In a book or movie, that can lead
to one-dimensionality -- but in code, we're usually more concerned with
clarity and efficency than depth. Much as a politician tries to portray
a world in whcih "we" are pure good and "they" are pure evil, it's often
convenient and useful for us to create characters as the pure essence of
a single idea.

As character development goes, it tends to stink. It's too quick and
easy to understand a character in a novel who's too one-dimensional, so
they lose our interest fairly quickly -- they're too predictable so it's
hardly worth reading the novel to find out how they'll act in a
particular situation.

For code, however, that's much more what we want -- something that
quickly becomes almost boring, because we hardly have to think to know
how it'll act or react in any given situation. Something we in which we
can quickly lose interest because it's obvious and predictable.

Like an overly-obvious allegory, we also want it to be obvious exactly
what concept each of our characters represents. In fact, we usually go
much further than even a really obvious allegory, and do our best to
make a single character represent only a single concept, with no other
characteristics at all.

Then, when we need a "character" with more than one characteristic, we
literally compose it out of the individual characteristics we've already
defined. IOW, we create a class that directly includes instances of
those other classes the represent the characteristics.

In practice, that means well-written code tends to be built up in
relatively small steps. Each step adds only a _few_ simpler concepts
together into one slightly more complex concept, but (with skill) does
so in a way that's still simple and straightforward to understand.

To use a rather different simile: your code is a bit like a spandex
mini-skirt on woman in her mid-50's. We're only separated from some
things that are less than beautiful by one thin layer.

What we'd like is more like a belly-dancer's costume -- lots of layers
that don't cling too closely to each other. They look a lot more
transparent than the mini-skirt, but still do more to cover up any warts
underneath.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top