Why do bugs come back?

I'm guessing you've never worked in coding or programming. Variables strings, linked lists, definitions, etc so funny things that often seem unrelated to other things being changed. Especially once the code is compiled.

^^ This!

He is correct... coding isn't a simple task as one would believe it to be. One wrong misspelled or misplaced variable/string, logic hierarchy, function type and/or parameters, etc. can mess up the entire program your building. Also in a game like Elite there are thousands, if not, hundreds of thousands of lines of code to sort through to even find just one error. Its' like searching for a word in a dictionary that's not in alphabetical order.

Think of it like this... what if you could only make post in these forums when you have all of your spelling, grammar and punctuation correct. Most of us will still take hours to find what is causing that error and others will never be able to post. It might be a ";" to the tense of a word being used incorrectly. Same (sort of) holds true for code, it's a very precise format.
 
^^ This!

He is correct... coding isn't a simple task as one would believe it to be. One wrong misspelled or misplaced variable/string, logic hierarchy, function type and/or parameters, etc. can mess up the entire program your building. Also in a game like Elite there are thousands, if not, hundreds of thousands of lines of code to sort through to even find just one error. Its' like searching for a word in a dictionary that's not in alphabetical order.

Think of it like this... what if you could only make post in these forums when you have all of your spelling, grammar and punctuation correct. Most of us will still take hours to find what is causing that error and others will never be able to post. It might be a ";" to the tense of a word being used incorrectly. Same (sort of) holds true for code, it's a very precise format.

You know, we've had tools to find those kinds of issues, called "syntax errors", since 1951.
 
Automated testing of some of the features and bugs of Elite Dangerous would be extremely difficult just because of what it *is*.

Unit tests are easy to write if the code is structured to support them. They help to stop bugs in the behaviour of individual functions. Given the sort of bugs we don't see in live builds, Frontier probably have a ton of these.

Functional tests are harder to write. They help stop bugs in the behaviour of individual features. In this context, a feature would be (at its biggest) "a pulse laser" or "the ability for a ship to roll" rather than anything we might think of as a feature. They're basically a test that you've put the unit-tested functions together in a sensible way so that the end result of calling a high-level function is a set of calls to various low-level functions which does the job. We don't often see bugs make the live builds that these would prevent, but there's a few now and then.

Acceptance tests are the hardest to write. They help stop bugs in the behaviour of the application as a whole. These check that a particular design goal or use case is met - e.g. "it is possible to undock a ship from a station". Most of my test-writing time is spent on these, in the apps I write. They're very powerful, because they can test the behaviour of the application as state changes.

So, for example:
- unitTest "testShipExplode" confirms that this function sets ship->exploding to true.
- functionalTest "firePulseLaser" confirms that the weapon can fire, various objects like the laser beam graphic get instantiated correctly, capacitor levels reduce, etc.
- acceptanceTest "weaponsTest17" confirms that firing a pulse laser on a target until it runs out of hull causes the target to explode (and not, say, the firing ship) ... and that the third time in a row the pulse laser fires you don't suddenly get massive recoil ... and so on

Acceptance tests are extremely difficult to automate for a game like Elite Dangerous because acceptance tests care about (non-minimal) state. So to write them you have to set up a known application state, then carry out a known series of steps, then see if the resulting state matches the desired state in the important aspects.

Let's take the recent comms menu bug that was introduced in 3.0.1 and fixed in 3.0.3 for an example.

All the unit tests for "displayBitOfCommsMenu" will have passed. So will the functional ones - there were lots of situations in which it worked. The bug occurred only after a particular - fairly common in real gameplay, as it happened - sequence of state manipulations. Most theoretical acceptance tests would also have passed. To catch this bug automatically you'd need an acceptance test which:
- added two player ships to an instance
- had one of them leave the instance
- had that one then check its comms panel and perform various actions on it
- have the test interpret the result of that sequence of actions against a known good result
...in a test environment that's running most if not all of the code, so effectively running (perhaps in a headless mode) two game clients and a set of game servers.

That's not impossible to automate, but it's really difficult. And that's an easy acceptance test. Consider what a proper automated test that a massacre mission is possible would need to do:
- find mission (the mission board can be pre-seeded to have one, since other tests will theoretically be checking generation, but it can't have an artificially low count)
- take the mission
- launch, fly to the right system, kill a bunch of stuff, fly back, dock
- hand in the mission
...remember that absolutely everything that occurs on this must be either completely non-random, or with randomness that doesn't break the test, over hundreds of thousands of game-loop cycles.

So most acceptance tests - for any application - are not automated. And that means rather than them completing in seconds per test, someone has to sit down, set up the initial situation, run through the steps of the test, and assess the result. And that rapidly gets both expensive and time-consuming the more such tests you have ... would the players be happy with months between the end of beta and live as the full test suite is run through?

That was fascinating to read. Thank you for taking the time to explain how bug checking works in a complex piece of software.
 
You know, we've had tools to find those kinds of issues, called "syntax errors", since 1951.

Yes, most compilers have a syntax error report.
I'm still learning code but from what I understand so far... syntax errors points out errors preventing the program from running not some of the other erroneous issues within the program, from what I've experienced. In code, the syntax may be correct but the values one wishes to calculate/display may be wrong or not happen in the sequence that's required. Not adhering to the order of operations in math problems, for one, can produce incorrect results but may still be calculated without a syntax error. A second example would be if/else/elif statements. If you don't have one of these in the correct order then what you desired the program to do might not happen in the sequence you wanted it to or not at all, without a syntax error.

I've really learned a lot by playing around with the EDDI app and Voice Attack! I'm always sorting out my own errors when I mess around with the coding (I keep a backup just in case). I'm in no way saying I'm right but providing another perspective. Like I said, I'm still learning.
 
Because often the actual root cause of a bug cannot found in a timely fashion and the solution is to bypass the troublesome code with a workaround.

However, a later change to something entirely unrelated may open up a new logic path that uses the troublesome code again.

Sometimes it doesn't even have to be broken code but just weird cross-contamination of systems. Do you remember the NPC ramships of doom that appeared for a bit waaay back in the day? An NPC could run into your ship and cut it apart harder than a modern-era ramming vessel. I can't recall if it was restricted to just patrol fighters but it really was forever ago.

It turned out they had been provided a gargantuan fueltank stat to prevent them gassing out while on maneuvers and such when spawned in an instance; good job NPC ship stat table-filling person! Now these ships will never idle out and just stop randomly when deployed for an extended time in a player's presence.

Sounds good so far, right? But since fuel is treated as an in-game "object" and adds mass >__> , the NPCs with overclocked tanks using fuel-as-object also turned into incredibly over-massive smash-hammers.
 
Yes, most compilers have a syntax error report.
I'm still learning code but from what I understand so far... syntax errors points out errors preventing the program from running not some of the other erroneous issues within the program, from what I've experienced. In code, the syntax may be correct but the values one wishes to calculate/display may be wrong or not happen in the sequence that's required. Not adhering to the order of operations in math problems, for one, can produce incorrect results but may still be calculated without a syntax error. A second example would be if/else/elif statements. If you don't have one of these in the correct order then what you desired the program to do might not happen in the sequence you wanted it to or not at all, without a syntax error.

I've really learned a lot by playing around with the EDDI app and Voice Attack! I'm always sorting out my own errors when I mess around with the coding (I keep a backup just in case). I'm in no way saying I'm right but providing another perspective. Like I said, I'm still learning.

You're correct. Syntax errors are compile time errors. There are runtime errors but bugs are not errors. When you see an old bug return it's usually a mix up in terms of code merging. They release version 1 while version 2 is still being developed. The bug fix from version 1 isn't merged to version 2 so it reemerges.

The other possibility is far more horrible. It's when things are so interconnected that fix 2 breaks fix 1. I think it's highly unlikely because the resulting bug rarely looks exactly like the original.
 
Last edited:
The simple explanation is that bugs coming back is often the result of someone reintroducing broken bits of code.

Yeah there are a million more uber complex ways things can go wrong, but in practice this is what happens.
 
I'm guessing you've never worked in coding or programming. Variables strings, linked lists, definitions, etc so funny things that often seem unrelated to other things being changed. Especially once the code is compiled. It's often like this:

http://web.mit.edu/adorai/www/seuss-technical-writing.html

Or this:

https://i.imgur.com/PMXHem2_d.jpg?maxwidth=640&shape=thumb&fidelity=medium

I remember reading a book called "The Pragmatic Programmer." There was a section in there about "Programming by Coincidence" It's basically the MEME you posted.

This can happen when your code is so complex (poorly structured) that you can't predict what the effects of a change will be.

My guess is the engine ED uses works by events. You write an event handlers to handle events. You change the game state in those event handlers. The complexity can come in if multiple handlers are changing the game same game state based on these events and overriding each other. It become very difficult to debug because certain error only occur depending on the order of events. I could be totally wrong about them using an event-driven approach. If someone has more insight, I'd love to hear.
 
Sometimes it doesn't even have to be broken code but just weird cross-contamination of systems. Do you remember the NPC ramships of doom that appeared for a bit waaay back in the day? An NPC could run into your ship and cut it apart harder than a modern-era ramming vessel. I can't recall if it was restricted to just patrol fighters but it really was forever ago.

It turned out they had been provided a gargantuan fueltank stat to prevent them gassing out while on maneuvers and such when spawned in an instance; good job NPC ship stat table-filling person! Now these ships will never idle out and just stop randomly when deployed for an extended time in a player's presence.

Sounds good so far, right? But since fuel is treated as an in-game "object" and adds mass >__> , the NPCs with overclocked tanks using fuel-as-object also turned into incredibly over-massive smash-hammers.

Huh, is that actually what was causing the scan ramming? I've not heard that explanation before, but it seem like a reasonable error that could happen, lol!
 
Anyone who has ever done any complex, team-based coding understands. You know you did your part exactly right. The other teams know they did their parts exactly right, mix them together and... bugs happen. Then you fix them and hope they don't respawn. Sometimes they do, and then it's hours, days, weeks or longer trying to figure out what is going wrong and why, and most importantly how to fix it.

Humans are imperfect, and computers are only capable of doing what they're told. Exactingly what they're told, especially when that exactness causes an unforeseen issue.
Right on. Endlessly baying for updates and new features does not help either.
 
there are plenty of games way more complex than elite, which dont have these sorts of problems.

You are right. I bet Planet Coaster doesn't have the Dav's Hope connection problem, or the mission ranking problem :) And the airline baggage monitoring software (that still loses baggage) doesn't have these sorts of problems :D
 
Last edited:
That's not impossible to automate, but it's really difficult.

it's part of the job. you as a test writer may well know that this part gets often shoved away, and know the consequences.

in the same way code needs to be written to be unit testable, software architectures need to be designed to be end-to-end (*) testable.

the scripters who made the scripts referred to in the recent "bot" thread did automate full mission completion and market operations just by 'reading' the screen and sending commands to the client, that's as bare bones as it can get. much more so can be achieved with an architecture flexible enough and proper tools to set up any arbitrary state and invoke the behaviours without human intervention. you only have to set that up once, and it's not that difficult once you have that. the only question is, are you willing to incur the extra cost and effort up front, and then run the full suite automatically almost for free on every code change if you wish, or would you rather pay the delayed cost of having to test manually, or not test and screw up a delivery, which is orders of magnitude higher?

of course then you might face combinatory explosion in a software piece like elite. well, that's a tradeoff and that's where real experts in qa come in handy. you also cannot avoid load or security testing. there is just no excuse for no testing, so better have it automated than manual.

but i'd also argue the comms panel bug could most probably have been detected with a unit test, it is clearly a problem with the component reacting badly to unexpected state or input: no matter who or what originated it, it shouldn't break. there are several other bugs in the list that show that even unit test coverage in the game has a few holes.

(*) imo 'acceptance testing' is always manual, since it is usually done by the customer to make sure a delivery meets expectations and fulfills the contract. i guess you refer to the automated tests you do to be run prior to submit to a real acceptance test.
 
Last edited:
Unfortunately, the same bug can often be triggered in more than one way. At the office, when we fix a bug, we first write a test (when possible*) to cover the problem, then fix it and verify the test now succeeds. The test is added to our test suite, so that the automated tests will catch it, if it's ever triggered again.

It's clear that FD needs more automated testing; you can NOT expect the QA to catch every reoccurrence.

I'm guessing that FD did not design ED for test. It can be really hard to add testability to code that was not designed with testing in mind. Just because it is hard and time-consuming does NOT mean that it should be skipped. That just adds to your "code debt".

* Some of our code is currently untestable via unit tests (some of it was written by other departments/teams); it will take many man-years to get some of that code under test (requires thousands of files to be reworked). It is MUCH better to design the code for testing in the first place and in many cases, it can SPEED UP development (since you are only running a few unit-tests, not the whole app). Even if it initially takes more time initially, it's worth doing, since it will pay for itself many times over during the lifetime of the app.
 
Last edited:
Back
Top Bottom