Are Some Programming Languages More Aspie than Others?
if (true == fSuccess)
{
fSuccess = DoSomethingElse ();
if (true == fSuccess)
fSuccess = DoSomethingOther ();
}
Why not:
if (true == (true == (true == fSuccess)))
{
fSuccess = (true == ((DoSomethingElse () == true)));
if (true == (false != (true == fSuccess)))
{
if (false != (false == DoSomethingOther ()))
{
fSuccess = ((true != true));
}
else
{
fSuccess = (1 == 1);
}
}
}
And... porting code between languages is a whole different ball game. Trying to pretend that languages has the same semantics, when they have superficially the same syntax, is another way to introduce subtle bugs.
The worst thing of this type I have seen was a set of C macros that made it look as if the written code was in FORTRAN. Dire.
_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer
I never really got into C or C++, circumstances never arose where I needed to learn it. Originally started programming using a Sinclair ZX81 in basic and since then seem to have programmed in most implementations of basic on the planet since. Also programmed in 6502 assembler, Fortran 66 / 77, Cobol, Clipper, DEC JCL and now programming in VB.Net
I still tend to stick with variable names from my Fortran background hence counters are usually simply intI, intJ, IntK but other than that I use long descriptive variable names.
I'm also a heavy commenter - I have had to add new features to software I wrote ten or more years earlier and comments are my saviour.
I like VB because I can write it very fast and get solutions up and running very quickly.
_________________
I've left WP indefinitely.
I'm also a heavy commenter - I have had to add new features to software I wrote ten or more years earlier and comments are my saviour.
A programming aphorism I've just thought up (?):
Never comment the code you write - always comment on what you thought it was going to do.
_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer
I'm also a heavy commenter - I have had to add new features to software I wrote ten or more years earlier and comments are my saviour.
A programming aphorism I've just thought up (?):
Never comment the code you write - always comment on what you thought it was going to do.
The worst code to maintain is always that written by other people. At least I know my own writing style. Other peoples code is especially bad if they have not documented / commented it. I ended up picked up the pieces of a large software package that someone else had developed over the course of several years, hardly any comments at all. Tens of thousands of lines of code that were just black boxes of functionality. The vendor could not afford to scrap the code and have it rewritten but this put huge constraints on the further development of the platform. I phased out huge sections of code but left them there as they were relevant to long obsolete portions of users data files - they still contain sections of essentially mumbo jumbo today because the surgery to remove all this dead code would kill the platform. The software equivalent of "Dead man walking".
_________________
I've left WP indefinitely.
Oh. I think I'd disagree there. The worse code I've come across, is that written by myself, before I learnt how essential good commenting is. When it was just a bit of throw-away code, that "didn't need comments", and then just happened to stick around.
It's far more embarrassing when you don't understand your own code. At least when it's someone else's code, you have that someone to blame.
I can go to the other extreme though. My most excessive bit of commenting meant that the source code (excluding white space) was about seventy times the size of the generated code.
_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer
Most likely, but I didn't found anything in the standard, that "DoSomethingOther" will be really (!) executed after "DoSomething", so my pedestrian way do tell the compiler certainly the sequence..
I always make it a point to learn a language before I use it:
http://en.wikipedia.org/wiki/Sequence_point
It seems that I used in early 1990's a bad compiler. I remember that I found with the MS-compiler for Dos and a compiler HP-UX V did interpret such sequences differently and I started than to force the compiler to analyse the sequences in the way I wanted; I remember also a paper from the German Rail explaining, besides a lot of other stuff, specific on this point why C shall be not used - and I did not care any more - stayed with pedestrian style.
I looked up and the sequence points are even in the Ansi C standard of 1989.
[...]
Unfortunately, writing code that "looks like Pascal", in a compiler that is as dysfunctional as C++ doesn't really work.
Because C++ is so dysfunctional, I strict myself to the most pedestrian code, which I even understand prior my first cup of coffee in the morning. When I started with C and shortly later with C++ in the early 1990s I tried to write the most tricky code; spending than endless time with debugging thought me the lesson to write as pedestrian as possible for a specific purpose.
Code shall be readable and clear.
There the function (or method or procedure) is created: If something can be put together in one logic unit (Init, Processing something specific etc.) than I write a function. This my way of prototyping: When I create a new method (a public method in C++) than I often t write down the method just a sequence of max. four or five methods, which have their specific purpose, so no function/method shall be longer than one page on the screen; optimization of the push and pop I leave to the compiler. I prefer here a classic Top-Down-Approach.
Last edited by Dussel on 08 Feb 2009, 8:39 pm, edited 1 time in total.
if (true == fSuccess)
{
fSuccess = DoSomethingElse ();
if (true == fSuccess)
fSuccess = DoSomethingOther ();
}
I reverse the comparisons so that a mistype of a single "=" generates a compiler error. The newer compilers might optimize the if statements for you, but again, I don't feel like you should rely on the compiler to generate what you mean. You should write what you mean.
I would not do so: Nesting is always a way to louse the overview: One or two levels are fine, a third acceptable, four if it really can't be avoided, but ... better not. But more: Never. The sole benefit of your code is that one expression does not need to get evaluated. The performance benefit is so minimal - also it would be only evaluated if fSuccess is true, so the push and pop would already take more time than this valuation of the method. But is not unlikely that a modern compiler would optimize my to something like your, but this nothing I do care about.
Untrue. Your remarks only apply if you insist on mechanical indentation.
If the structure naturally entails deep nesting, artificially concealing that structure, by introducing irrelevant extra variables, code, and so on, is a sure way to destroy the overview.
When it takes a period of detective activity, before you can establish that some code paths, which appear to be open, are actually excluded because of fine interactions between artificially introduced variables, then you are obfuscating the algorithm.
Sometimes code is genuinely complex. Making all code look more complex than it really is is just a bad habit.
===========
PS. I forgot another aspect of your original code fragment that I find highly obscurantist: functions that return boolean values, but give no hint, by their name, either that they do so, or what the meaning of that boolean might be. Interestingly, your choice that a "true" return indicates success flies in the face of all C library code.
_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer
Untrue. Your remarks only apply if you insist on mechanical indentation.
If the structure naturally entails deep nesting, artificially concealing that structure, by introducing irrelevant extra variables, code, and so on, is a sure way to destroy the overview.
When it takes a period of detective activity, before you can establish that some code paths, which appear to be open, are actually excluded because of fine interactions between artificially introduced variables, then you are obfuscating the algorithm.
Sometimes code is genuinely complex. Making all code look more complex than it really is is just a bad habit.
Even the most complex code shall simple - In my option and experience complex problems can break down to small chunks keeping single methods/function small. Reasonable names of methods/function (better too long than too small) helps here a lot. An acutal example of my code:
A public method:
bool Population::RunGeneration (double rHardness,
double rMutationRate,
double rGoodEnough,
bool *fRunProgram,
int iCurrentGeneration)
{
bool fSuccess,
fRunProgram_loc;
fSuccess = CheckInitCorrect ();
if (fSuccess == true)
fSuccess = CaluclateError (iCurrentGeneration);
if (fSuccess == true)
fSuccess = BuildNewGeneration (rHardness, rGoodEnough, &fRunProgram_loc);
if (fSuccess == true)
{
if (fRunProgram_loc == true)
MutateAll (rMutationRate);
if (fRunProgram != NULL)
*fRunProgram = fRunProgram_loc;
return true;
}
else
{
ErrorHandler::PrintErrorNonFatal ("<Population::RunGeneration>\n");
return false;
}
}
A private method:
{
bool fSuccess = true;
int iLoop = 0;
double rScore;
do
{
rScore = pMatrix->GetError (aSolutionVectors [iLoop]);
if (rScore < 0.0)
fSuccess = false;
else if (rRemainderMinError > rScore)
fSuccess = ResetAllTimeBestVector (rScore, iCurrentGeneration, iLoop);
if (fSuccess == true)
{
aScores [iLoop] = rScore;
iLoop++;
}
else
ErrorHandler::PrintNonFatalErrorInLoop (iLoop);
} while ((fSuccess == true) && (iLoop < iCountVectors))
if (fSuccess == false)
ErrorHandler::PrintErrorNonFatal ("<Population::RunGeneration>");
return fSuccess;
}
When a function/method does not produce an reasonable return value which indicate the success of method (or something went wrong) I would need to go back on exceptions, something I try to avoid, because they are just gotos by an other name (see also the break or the continue statement in C). I always try to construct functions/methods to have a return value which indicates the success of this method. In the example or the pMatrix-GetError-Method per definition an negative value can't be reasonable, so I use the negative value as indicator that something went wrong. If a negative value would be also reasonable than, and only than, I would use an exception.
In my option the error handling shall follow the same lines than the program-flow, but as an indication that something went wrong.
If function can be either successful or not than a boolean datatype is logic choice, if one exists. In C there is no boolean type and therefore the whole mess with 0 (as in Unix-World) started. In C++ there is a boolean datatype, how floppy it may be defined, so it just logic to use this datatype.
Also, when I call a public function of class, I do, if possible, check in of the very lines of this method that the class has bee reasonable initialized, consistence of data - a program shall, in my option check up it own correct run in runtime, to expose hidden bugs for its own. But I am a high admirer of the "paranoid programming".
Critique:
No comments.
Excessive white space.
Multiple exit points from one function (something I would have thought you would hate. Personally, I find it something well worth avoiding, unless there is some very good reason for it. It invariably makes debugging tedious.)
Does any of your code modify the value at fRunProgram? (I'm surprised that you not not name this to reflect the fact that it is a point to boolean, not just a boolean. I dislike incorporating data types in the name, as it makes it hard to reuse code.)
Use of global data. (Obviously this is convenient, sometimes.)
Interchanging the tests, to make it very unclear what is going on: first "rScore < 0.0" then (nested "else") "rRemainderMinError > rScore", which I assume means that rRemainderMinError is positive, and a variable, or you will get a compilation warning(error?).
Apparently trebling up of the meaning of the return value from pMatrix->GetError to mean some sort of "valid" error quantity, when it is in the inclusive range 0..rRemainderMinError, an unconditional error when strictly negative, and some sort of "needs more work but may be an error" condition when strictly greater than the range. Decisions on code paths based on a floating point comparison to anything but zero always make me suspicious of the design.
Omitted semicolon after the "do/while" statement.
Avoidance of usage of "aScores [iLoop++] = rScore;"
... or ...
Separation of the incrementation of iLoop from the test.
Avoidance of the "for" construct, when it is clearly essential. (What if iCountVectors is not strictly positive? Zero, for instance.)
No comments.
No comments.
A lack of defensive programming. (See iCountVectors).
_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer
rScore declared outside the loop is it local to.
_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer
No comments.
Excessive white space.
Multiple exit points from one function (something I would have thought you would hate. Personally, I find it something well worth avoiding, unless there is some very good reason for it. It invariably makes debugging tedious.)
They are at the end of the method an there are only two: One for a successful run and one if the method produces an error. I think therefore it is acceptable. I would not use an exit point e.g within the loop.
Yes - there is local variable fRunProgram_loc which is by reference parameter of BuildNewGeneration. In some cases I do not care about this variable. Thus RunGeneration is a public function which is shown in the next level, I use an NULL-Pointer as an indicator that this particular variable is used - therefore the lines:
*fRunProgram = fRunProgram_loc;
I do not see global data, there are private members of the class, like aScores, pMatrix etc.
In the constructor of this class is a line:
The only place where rRemainderMinError is set is ResetAllTimeBestVector, a private method which is only called on one place, when it had been already checked that rScore is not negative, so at no time rRemainderMinError can have a negative value.
when pMatrix->GetError runs properly it returns a sum of fabs (). Therefore a negative value can't raise within a successful run. If something goes wrong than pMatrix->GetError returns (-1) and this is the indicator that some bad happened.
because they are two different issues - the one the assignment of the value into the array (aScores [iLoop] = rScore;) and the other one is the incrimination of the counter. I do see it as a good style to put to absolute different items into one line.
Also rScore is not necessary within the range of 0..rRemainderMinError. It can (if pMatrix->GetError is successful) have any value 0 ... maxdouble. Only if rScore is smaller than rRemainderMinError the ResetAllTimeBestVector will be called. Independent from this check rScore will written into the array aScores (if anything went right).
A lack of defensive programming. (See iCountVectors).
Therefore the call at the beginning of Population:CheckInitCorrect in the first lines of Population:RunGeneration. Population:CalculateError is a private method and is only called in the public method Population:RunGeneration. CalculateError can't be called called outside the class, so I can be certain that here no bad surprises of this kind can happen. When I would use for-loop in the case of an error, I would need to use break, which is basically a goto by a other name.
t0
Veteran
Joined: 23 Mar 2008
Age: 51
Gender: Male
Posts: 726
Location: The 4 Corners of the 4th Dimension
Unfortunately you can't count on your coworkers to do the same.
I dunno, what exactly are you trying to say there? I don't understand why a person would communicate verbally in such a fashion and I don't think my AS is contributing to the misunderstanding. In my previous example, I was saying "if true is the result of DoSomething()" rather than "if DoSomething". You seem to be saying "if the result of DoSomething is true is true is true."
I find it confusing that you're partially using Hungarian notation (fSuccess, iCurrentGeneration). I would find it easier to read if you specified member variables using Hungarian as well.
You gave a code fragment. I critiqued that code fragment. Your "explanations" appeal mainly to things not shown in the code fragment.
I suggest you take all your comments above, and put them in your code as comments.
==========
Returning "-1"? Don't you mean returning "-1.0"?
I do hope that you do not REALLY use std::numeric_limits<double>::max() the way you have suggested. Do you really rely on positive infinity as a return value? You must be certain that FP handling is set to use affine infinity, otherwise there will be an FP exception error when you come to compare your (nominally) positive infinity, which is the only thing you can hope to be greater than the maximum floating point double value, with that value stored in rRemainderMinError (which is rather a misnomer).
_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer
I suggest you take all your comments above, and put them in your code as comments.
I didn't want to copy-and-past some 1500 lines.
Yes - The actual of the method of matrix is the following:
{
double rReturn = 0.0,
rErrorCol,
*aTempToCheck = NULL;
aTempToCheck = CreateTempAndCheck (pToCheck);
if (aTempToCheck == NULL)
{
ErrorHandler::PrintErrorNonFatal ("<Matrix::GetError>");
return (-1.0);
}
else
{
for (int iRow = 0; iRow < iCountRows; iRow++)
{
rErrorCol = 0.0;
for (int iCol = 0; iCol < iCountCols; iCol++)
rErrorCol += aEntries [GetPointerElement (iRow, iCol)] * aTempToCheck [iCol];
rReturn += fabs (rErrorCol);
}
free (aTempToCheck);
return rReturn;
}
}
in which CreateTempAndCheck does not only extract the data from pToCheck, but also checks that the dimensions fit, that aEntries was set etc. So when it comes to the actual calculation, I do not need check for any bad surprises and can use here safely for-Loops.
I am looking here for an all-lowest value, which is positive value by defintion. In the very first run rScore will have any value lower than max-double and this value will be written into rRemainderMinError. In further runs it will be checked against this value and will, if lower, overwrite rRemainderMinError. I just need a starting point high enough to find my lowest positive value.
Similar Topics | |
---|---|
Have you been in a romantic relationship with another Aspie? |
11 Dec 2024, 3:25 am |
Coming out of the aspie closet |
28 Nov 2024, 6:47 pm |
Aspie dating success stories |
31 Oct 2024, 6:22 pm |