Loughter for Developers

Let the flames roll in...
Err... yeah, well I suppose you can talk about other stuff as well, maybe?

Moderator: Halleck

klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Loughter for Developers

Post by klauss »

Found this around Ogre forums, and just had to share it... so... funny...

http://thc.org/root/phun/unmaintain.html
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
snow_Cat
Confed Special Operative
Confed Special Operative
Posts: 349
Joined: Thu Jan 05, 2006 12:43 am
Location: /stray/
Contact:

This made me smile.

Post by snow_Cat »

Meow,
it somewhat falters my confidence to know that my code is not comliant with tea vernicular;

I learned to use hexes addys back in the days when I could still read C=/ASM and this has lead to some problems when I have to work with other programmers; fortunately we do use that Oracle 'code' database the article describes, and each programmer subsitute see their own working 'token', that will transparently return to the master code as my beloved though (obscficated) hexy.
^ - -^ meowr *hugs the hexy*
edit wrote:I've finally found the time now to sit down and read through the articles and all I have to say is "Hey! He's describing the exact program I've been working on for the last three years!"
BTW: This could be a concidence, and he could be describing another application that is being developed from stolen and depreciated Sabre-client code for a corporate 'client' that is too stupid to know that 'new' does not necessairly mean 'improved'; and has also sold a multi-million dollar finanacial comapny for a pittance to pay a fat dividend to it's pathetic 'core' shareholders who themselves...
Ok-y time for a new job.
Last edited by snow_Cat on Wed Jan 11, 2006 2:16 am, edited 2 times in total.
dandandaman
Artisan
Artisan
Posts: 1270
Joined: Fri Jan 03, 2003 3:27 am
Location: Perth, Western Australia
Contact:

Post by dandandaman »

Ya, that's a cool one klauss :-)

Dan
"Computers are useless. They can only give you answers."
-- Pablo Picasso
Ryder P. Moses
Daredevil Venturer
Daredevil Venturer
Posts: 593
Joined: Mon Sep 26, 2005 3:59 am

Post by Ryder P. Moses »

It'd be funny, except I just spent the past hour doing damage control on a website that managed to pack about half of these in. Into HTML and Javascript, the simplest, hardest-to-critically-fuck-up coding languages on Earth. It hurts my brain to know there's someone out ther that can even do that. And I thought I'd escaped all that goddamn bughunting years ago.
Halleck
Elite
Elite
Posts: 1832
Joined: Sat Jan 15, 2005 10:21 pm
Location: State of Denial
Contact:

Post by Halleck »

Myself and my java coder friends all find this hilarious. :D
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

I printed it out and gave a copy to my boss and said "this is a new guidelines proposal". He was laughing not just because of the ideas therein but because he knows most of the programmers around here already master most of that stuff... ;-)
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

chuck_starchaser wrote:He was laughing not just because of the ideas therein but because he knows most of the programmers around here already master most of that stuff... ;-)
I think that's the catch in most cases. I even recognize some habits of mine (like one-letter variables).
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

I'm usually quite careful with my code; but that is my downfall; I can't follow anybody else's code. I tend to expect the same from others. And not to start a flame about formatting, but really, if I see code where the opening curly braces are at the the end of the line, I simply can't follow the flow at all. The braces have to line up, for me. I was trying to decipher the lib3ds code, and, not only do their braces NEVER line up, but on top of it they don't use types like char, int or float. What they use, instead, is Lib3dsChar, Lib3dsInt, Lib3dsFloat, and I just want to get a BFG9000 and rid the world of their kind... (Actually, there's a lot more than that to lib3ds, like recursive functions that are inscrutable, lack of comments, and just too much code... by the time you look into the function called by the function called by the function called you forget what you were looking for in the first place... or at least I do.)

One obfuscation technique the author forgot about is making floating point variables carry special meanings when they assume a special value, like if it's zero, then get the value from somewhere else, or if it's -1.0f then flash a light instead. Vegastrike's favorite. Ah, and also initializing floating point variables with literal integers, like float foo, bar; then in some other file, foo=0; bar=1. To help the reader forget they are floating point... Come to think of it, it has the added advantage of generating a stupid warning. Produce enough pages of useless warnings like that, as compiling VS does, and more serious warnings will be lost in like a needle in a haystack.
hellcatv
Developer
Developer
Posts: 3980
Joined: Fri Jan 03, 2003 4:53 am
Location: Stanford, CA
Contact:

Post by hellcatv »

you can always use the program called

"indent"
to fix a C file to your liking... you configure your own style and it goes aheads and indents the code as if it were following that style


plays hell with cvs, but if it's a library then go ahead!!

and if you want to use it with cvs get familiar with diff -w and patch (I can give you instructions if you need them)
Vega Strike Lead Developer
http://vegastrike.sourceforge.net/
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

hellcatv wrote:you can always use the program called

"indent"
to fix a C file to your liking... you configure your own style and it goes aheads and indents the code as if it were following that style
Cool! I'll google it up.
plays hell with cvs, but if it's a library then go ahead!!
and if you want to use it with cvs get familiar with diff -w and patch (I can give you instructions if you need them)
What klauss and I agreed we're going to do, after Ogre, is to start going around the code, module by module, refactoring and cleaning it up. That way, we can announce in the forum "Cleaning crew in module such and so; expect cvs alerts; don't get jumpy." As we do that, I'm thinking, we'll reformat the code using an automatic tool --indent, for all I know. That way, by the time we're finished, all the code will have a common format, and then coders can reformat to taste, before working on a file, because they can use the tool to put it back to the original, standard format before committing.
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

I should add... I didn't mean "cleanup" as in just cosmetic cleanup.
I meant real cleanup... restructuring things.

Not everything, but some things do need to be restructured.

Since we'll be restructuring both graphics and sounds, we're only a step away from restructuring other stuff.

I don't know yet which aspects stand good chance of benefiting from such work... and I don't really feel like thinking about it right now, but certainly, if the changes mean only fixing up whitespace and changing variable names, certainly it isn't worthy.

One main aspect that has to be somewhat restructured (as in... at least documented, and somewhat refactored), is AI. Mostly because after Ogre kicks in, we will be able to use its dLoad subsystem to dynamically load "AI plugins" writen in C++. I think we all see the benefit in that. That won't happen without some refactoring, though, so there lays our first big chance at code tidyization.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

I did mean "deep cleaning". Last time I'd found a non-abstract class whose destructor was non-virtual, and it was inherited by another class, AND the inheriting class increased the size of the data footprint; a recipi for memory leak waiting to happen. But neither you nor Hellcat seemed excited about it, and I thought I had CVS access, so I fixed it and tried to commit but found out I didn't have commit access, so that problem is still there. When I looked briefly at the physics, one time, there were major simplifications of that code possible, and on top of that there were unreachable statements within the function. So I meant really deep cleaning, as in bug hunting and optimizations as well.
Data alignment within classes seems not existent, also; sorting from largest to smallest data types can result in major data size optimisations. And there are more subtle improvements that should be done as well, such as NEVER having public virtual functions; --the idiom of having them be either private or protected, and if necessary, accessible through a public, non-virtual in-line adds clarity to the intention of how derived classes should use the virtual function (calling the parent's and decorating it, if protected; substituting for it, if private). As well as making copy constructors and copy assignment operator private for classes not meant to be copied... And how about making member functions that acces data members only through public member functions, non-member functions? Etceteras, etceteras.

EDIT:
Also, maybe trying to look at the big picture, like which classes really need to be publically accessible, and which could be private parts of some package. We could have folders for packages with a "private" subfolder contaning all the classes that are needed to make the package work, but aren't part of its client interface.

For globals:
Globals such as the world, the time, the camera; they could all be embedded in a singleton and use the header inclusion inversion idiom, whereby "clients" (rather the opposite) specify the interfaces they want to see in those globals, and the globals include those required interfaces within a large abstract interface they inherit from, and implement. That way we minimize the risk of header inclusion loops.

Last but not least, we could start looking at the thread-safety aspect.
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

Many (but not all) of what you proposed I do not agree with. We can discuss that later, but mostly, what about:
chuck_starchaser wrote:And how about making member functions that acces data members only through public member functions, non-member functions?
Why? Membership is a conceptual thing, not a matter of having to access private data.
chuck_starchaser wrote:Also, maybe trying to look at the big picture, like which classes really need to be publically accessible, and which could be private parts of some package.
This is more the kind of tidyization I'm looking for... the one that most benefits readability, by simply pruning the amount of code you have to understand to see the big picture.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

klauss wrote:Many (but not all) of what you proposed I do not agree with. We can discuss that later, but mostly, what about:
chuck_starchaser wrote:And how about making member functions that acces data members only through public member functions, non-member functions?
Why? Membership is a conceptual thing, not a matter of having to access private data.
Scott Meyer wrote a (non-) controversial paper titled something along the lines of "Increasing Encapsulation through Non-Member Functions"...

Ah! Yes! I found it:
http://www.cuj.com/documents/s=8042/cuj0002meyers/

Essentially, one idea behind encapsulation is to reduce the impact of changes to implementations. Now, suppose you have a data member that is a char, and later on you decide to change that to a short. You have to change all member functions that access that data member. Now, suppose there's only a few such functions, but the class has 100 functions. You have to go over the hundred functions visually checking for uses of that member. The less member functions, therefore, the better.
Now, if a function accesses members of its class only through other public member functions, it cannot possibly violate encapsulation by becoming a non-member. Therefore it should be.
The meaning of a class' public member function is a public procedure that guarantees that the state of the class is healthy upon exit, if it was healthy upon entry. No function not needing to provide such guarantee needs to be a member function.

EDIT:
Private functions aren't required to guarantee coherent state on exit; therefore a public function that doesn't access data members, is still required to be a member function if it accesses private functions. And that is a necessity of the language as well. Only a function that only calls other public functions needs not be a member function.

This doesn't mean it needs to be declared outside the class, though...

Stuuupid example:

Code: Select all

class my_int
{
    int i;
public:
    my_int& operator+=( my_int const & x ){ i += x.i; return *this; }
    friend my_int& operator+( my_int const & x, my_int const & y )
    {
         my_int temp = x;
         temp += y;
         return temp;
    }
    ....
};
Thus, if I see friend definitions within a class, I don't need to look at them when I change that char to a short, because I know the intent that them being friend definitions signifies.
Last edited by chuck_starchaser on Tue Jan 17, 2006 7:04 pm, edited 1 time in total.
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

I have a better solution:

Put them all together in an "Implementation-independant" group, which you know you won't have to check unless you mess up with the public interface of the "implementation-specific" group.

Really... no need to mess up OO-ness like that.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Klauss, this is NOT messing up with OO-ness. Meyer's paper is pretty famous by now, and this is a generally accepted idiom.

As a matter of fact, if you were to run Lint for C++ on your code, it ill flag for you opportunities to make functions non-members, as per Scott Meyers' paper.

Come to think of it, maybe we should buy Lint....
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

What can I say...
...I disagree with Meyer.
Famous or not.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Well, it's not that important to me. I'm a bit of neat pick. I really like it when I look at code where intentions are clearly expressed through idioms, rather than put in comments and stuff. But if this one is a sticky for you, so be it.
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

Kind of yes... I'm quite strict with my OO-ness.
Notice: my OO-ness... not everyone does it the same way.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Did you see my example, couple of posts back? 'Cuz I was editing when you posted and it was left in the previous page.
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

That's twisting the purpose of friendliness... friend functions are meant to access private/protected members. Plus... you're making it inline implicitly. Nah... not good still.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

The original intent of "friend" was exactly as you say. But as happens many times, useful uses of unintended consequences of a language's featurs are later exploited. In this particular idiom, "friend" is only used for its side effect of allowing a non-member function definition within a class, and the idiom implies that there is in fact no access to private members.

What's that STL that Microsoft bought the rights for, to package with .net? Can't remember the name now... by the same guys that made Lint, in fact... It's considered like the reference STL, but it's not free... Anyways, they use this idiom religiously in their STL implementation.

But like I said; I don't care that much for this particular thing to be part of the refactoring if it disagrees with you. Just wanted to make clear that I didn't pull that concept out of my ass. ;-)
Last edited by chuck_starchaser on Tue Jan 17, 2006 8:11 pm, edited 1 time in total.
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Anyways, given that you don't like it, the simplest solution, I think is to bunch all such non-private-member-accessing- public member functions at the bottom of a class and precede them by a comment to the effect.

By the way, I don't consider myself a "purist", but just thought I'd mention that before Scott Meyers wrote that article, there were many C++ purists who insisted that NO non-member functions should exist, except main().
But since he wrote that controversial article (which, ironically, generated no controversy at all), purists have changed their tuned, slightly, to that non-member functions should be MAXIMIZED, but preferably defined within the body of a class (via the 'friend' idiom).
Last edited by chuck_starchaser on Tue Jan 17, 2006 8:16 pm, edited 1 time in total.
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

Actually, there's a much better option, since it lets the compiler enforce it:

Code: Select all

/* Implementation class */
class punchimball_impl
{
	int x,y;

public:
	T dosomething(const punchimball &a) { ... }
	T dosomeother(...) { ... }
}

/* Interface class */
class punchimball 
{
private:
	punchimball_impl *impl;

public:
	punchimball() : impl(new punchimball) {} //Although... make sure it isn't inlined
	~punchimball() { delete impl; } //again, non-inline

	(wrap functions in impl, inline form)

	punchimball doveryusefulthing(...)
	{
		...
		impl->dosomething(...);
		...
		impl->dosomeother(...);
		...
	}
}
EDIT:
Fixed - was not useful before.
The ugly part is that you have to have wrappers for every function in impl.
The very nice part is that you have binary compatibility when changing only the implementation side - which is extremely useful if, for instance, you want that as a plugin or part of a dll...
If you follow strictly the non-inlined constructors and destructors rule, you have completely separated (binarily) all dependency between implementation and interface. Very nice. I considered using it several times... but the overhead of having to wrap all implementation-side functions that are supposed to be publicly accesible (that also serve as interface) is annoying.

EDIT:
Alternatively, the old method may not be that bad if you don't mind allowing access to protected members, and loosing binary independence:

Code: Select all

/* Implementation class */
class punchimball_impl
{
	int x,y;

public:
	T dosomething(const punchimball &a) { ... }
	T dosomeother(...) { ... }
}

/* Interface class */
class punchimball : private punchimball_impl
{
public:
	punchimball() : impl(new punchimball) {} //Although... make sure it isn't inlined
	~punchimball() { delete impl; } //again, non-inline

	(wrap functions in impl, inline form, to promote them to public access)

	punchimball doveryusefulthing(...)
	{
		...
		dosomething(...);
		...
		dosomeother(...);
		...
	}
}
Last edited by klauss on Wed Jan 18, 2006 3:37 pm, edited 2 times in total.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Sure. I'm sold.
Where the idiom I mentioned really shines is with operators, really.
Like the '+' operator; I find it a bit distasteful to see the '+' operator being a class member; and lint will give you a big warning. There's more to it than distaste; I've seen practical examples of snafus concerning '+' being a member function; but I don't remember any more.

Anyhow, that looks good. For many classes, in fact, we might consider the pimpl idiom, which implies having an interface and an implementation, anyhow.
Post Reply