Can game development excel with abstract concepts?
But as for the particular problem of "how do I fix a bug in the middle of a bunch of loops" - that's just a matter of good application of debugging tools. If you know what iteration of the loop your algorithm breaks on you can set up your breakpoints to only break when they've been hit n times. Or you could add a condition to the breakpoint to only break when the condition is true.
You can also scatter asserts to make sure that assumptions you have about your algorithm are not violated.
And most importantly, you can break down your algorithm into smaller steps and test those smaller steps more easily.
If you knew what you were looking for (stepping through a debugger, you could tell if you had found the bug) there's probably a way to either set a conditional breakpoint, or just add an if statement to detect the error case and put the breakpoint inside.
A lot of great scientists were visual thinkers. Michael Faraday comes to mind: very limited mathematical education, but was able to visualize what electromagnetic experiments were conveying. Einstein and Paul Dirac also talked about the importance of reframing problems visually. Eleven dimensional physics you can't get into your head all at once, but there's lots of tricks that can help. You can visualize two 3d spaces, where up in one is left in the other, but the dimensions are otherwise separated. You can say "a 1d being in a 3d world is kind of like a 3d being in a 5d world...You can visualize a network of points with edges along the dimensions, and consider how it changes as the dimensions go up.
I'd say the most important skills are breaking a problem into different parts: A is true iff B and C and D are true, and finding isomorphisms. Much of science starts by analogy. If you can reframe a novel problem in terms of a well known one (like a visual problem), you can use that wider toolset. The more math and logic you know, the more isomorphisms you can draw from: is this equivalent to eigenvalue finding in a matrix? To trigonemetry? To calculus?
But as for the particular problem of "how do I fix a bug in the middle of a bunch of loops" - that's just a matter of good application of debugging tools. If you know what iteration of the loop your algorithm breaks on you can set up your breakpoints to only break when they've been hit n times.
Of course if I knew "n", for me that would be a no brainer. But i don't know "n".
Or you could add a condition to the breakpoint to only break when the condition is true
My guess is you haven't encountered this sort of situation before otherwise it would be obvious that you wouldn't know the condition on which it fails. This kind of bug normally happens when there is a special case which your algorithm has not yet considered. You only know that about the bug because you can see the wrong output visually.
Even the wrong line of code will pass the test because this special case is not yet known to your algorithm
If you knew what you were looking for (stepping through a debugger, you could tell if you had found the bug) there's probably a way to either set a conditional breakpoint, or just add an if statement to detect the error case and put the breakpoint inside.
Again the special case applies here. The maths algorithm is all about web of logics. So knowing what i'm looking for means i know all the special cases of the logic and incorporated it into the algorithm. In non-trivial novel situations i don't know this. Sometimes you only get to know all the right conditions and special cases to incorporate into the algorithm via r & d
Eleven dimensional physics you can't get into your head all at once, but there's lots of tricks that can help. You can visualize two 3d spaces, where up in one is left in the other, but the dimensions are otherwise separated. You can say "a 1d being in a 3d world is kind of like a 3d being in a 5d world...You can visualize a network of points with edges along the dimensions, and consider how it changes as the dimensions go up
Hmm.. very smart way of visualising and tackling the problem of multiple dimensions
If you knew what you were looking for (stepping through a debugger, you could tell if you had found the bug) there's probably a way to either set a conditional breakpoint, or just add an if statement to detect the error case and put the breakpoint inside.
Again the special case applies here. The maths algorithm is all about web of logics. So knowing what i'm looking for means i know all the special cases of the logic and incorporated it into the algorithm. In non-trivial novel situations i don't know this. Sometimes you only get to know all the right conditions and special cases to incorporate into the algorithm via r & d
But if step through the debugger works, there's something that you can see in the data that would make you say "aha! Here's the issue!" So you have some internal representation of what represents a good state or what a degenerate state looks like. Hence SMKViper's suggestion to use asserts, or my suggestion to create if statements that catch situations you would find interesting.
I agree it's very tricky when you don't know what's wrong and the only way to define what's right is the algorithm that's broken, but if you start coming up with "what could be wrong, how could I detect that", you can usually get somewhere. Another good approach is to throw all sorts of test cases against it, especially weird ones. Do only some break? Do some break worse? Does this suggest a useful conditional?
If all else fails, there's always binary search. Break at the midpoint. Is it already broken? If so, restart and break a quarter of the way through. Still painful, but much better big O behaviour.
AlwayBiased i find the attiude of saying things like "you can't understand, you've never dealt with such a bug" a bit egotistical. Many of us here have been programmers for a long time, maybe we havent done your particular problem, but we've likely ran into similarly complex bugs. The thing is we also are trying to tell you there are alternatives to debugging then stepping over an entire loop to find your bug.
For example, you say you can visually see that their is an error in your output. This likely means for a given input you can produce said bug(making your bug reproducable is the start to solving it). Once you've isolated how to make your bug appear, you can begin narrowing down the code associated with that data and since this is a problem you can visually inspect, it's likely you could say "break on index x/y" after having inspected where in the image the bug first appears.
If this isn't a viable tatic, another tatic is to dump the output at each iteration, rather than walk through your code, dump lots of data about your code. Then you can go through this data and start to narrow down where things go wrong.
There are a multitude of ways to tackle solving complex bugs, but saying things like "you can't possible understand" is not helpful to yourself or those trying to help.
Or you could add a condition to the breakpoint to only break when the condition is true
My guess is you haven't encountered this sort of situation before otherwise it would be obvious that you wouldn't know the condition on which it fails. This kind of bug normally happens when there is a special case which your algorithm has not yet considered. You only know that about the bug because you can see the wrong output visually.
Even the wrong line of code will pass the test because this special case is not yet known to your algorithm
Except you know when it fails. So now you have to figure out how to represent the knowledge of "when it fails" into computer code that can break when it happens.
You say "visually" - are you dealing with pixels and shader bugs? Ok, most shader debugging tools let you pick an individual pixel and "replay" the shader code that produced it on demand.
If you're only saying you can see the error when you represent it visually - well then, again, you've got some code that is representing the data visually. So you know what the wrong value is, so break on the wrong value. Is it only because the value is a large difference from adjacent values when it should be smooth? You can represent that as well.
Every problem can be broken down into smaller problems that are trivial to solve. The trick is figuring out how to break the issue down, and whether your code design allows you to do the breakdown in the first place.
If it is an edge case you haven't considered, well, play the "evil user". Look at your function. What values does the compiler let you pass the function vs what values do you expect to be passed to the function? For example, if your function accepts a pointer, what if it is null? Your function accepts integers, what happens if it is passed zero? Or the minimum or maximum value for integers? If you accept floats, what happens if you pass in two adjacent values? Or if you're really evil - what happens when you pass in an invalid enum value?
That meant i would have to click 400x800x5 (1,600,000) times or less!!!
.
If there is a "quantifiable" logic error in the matrix, wouldn't it be easier to to create a dump file with the results of each iteration, than write a script to automatically scan the file and report on all the abnormal ( out of expected bounds ) behaviors ?
Note: I have actually done something like this before to find logic flaws with a fractal-noise program I wrote.
AlwayBiased i find the attiude of saying things like "you can't understand, you've never dealt with such a bug" a bit egotistical.
Oouch! That hurts
I agree it's very tricky when you don't know what's wrong and the only way to define what's right is the algorithm that's broken, but if you start coming up with "what could be wrong, how could I detect that", you can usually get somewhere. Another good approach is to throw all sorts of test cases against it, especially weird ones. Do only some break? Do some break worse? Does this suggest a useful conditional?
If all else fails, there's always binary search. Break at the midpoint. Is it already broken? If so, restart and break a quarter of the way through. Still painful, but much better big O behaviour.
For example, you say you can visually see that their is an error in your output. This likely means for a given input you can produce said bug(making your bug reproducable is the start to solving it). Once you've isolated how to make your bug appear, you can begin narrowing down the code associated with that data and since this is a problem you can visually inspect, it's likely you could say "break on index x/y" after having inspected where in the image the bug first appears.
If this isn't a viable tatic, another tatic is to dump the output at each iteration, rather than walk through your code, dump lots of data about your code. Then you can go through this data and start to narrow down where things go wrong.
There are a multitude of ways to tackle solving complex bugs, but saying things like "you can't possible understand" is not helpful to yourself or those trying to help.
If you're only saying you can see the error when you represent it visually - well then, again, you've got some code that is representing the data visually. So you know what the wrong value is, so break on the wrong value. Is it only because the value is a large difference from adjacent values when it should be smooth? You can represent that as well.
Every problem can be broken down into smaller problems that are trivial to solve. The trick is figuring out how to break the issue down, and whether your code design allows you to do the breakdown in the first place.
If it is an edge case you haven't considered, well, play the "evil user". Look at your function. What values does the compiler let you pass the function vs what values do you expect to be passed to the function? For example, if your function accepts a pointer, what if it is null? Your function accepts integers, what happens if it is passed zero? Or the minimum or maximum value for integers? If you accept floats, what happens if you pass in two adjacent values? Or if you're really evil - what happens when you pass in an invalid enum value?
I can see these debugging methodologies clearly now. The disadvantage of a lone wolf like me is i am developing a software that a in a company a team of probably 5-10 programmers develop(where ideas are shared, burden is distributed but i don't have that luxury), so one person doing the job of ten developers, the consequences are that a lot of times, under intense pressure, my brain is exhausted, my eyes are clouded and i see less.
Well you learn everyday
I can see these debugging methodologies clearly now. The disadvantage of a lone wolf like me is i am developing a software that a in a company a team of probably 5-10 programmers develop(where ideas are shared, burden is distributed but i don't have that luxury), so one person doing the job of ten developers, the consequences are that a lot of times, under intense pressure, my brain is exhausted, my eyes are clouded and i see less.
Well you learn everyday
Heh - that's not exclusive to small teams, that happens to everyone. Especially during crunch time when you're trying to ship something.