Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The real payoff to me is when someone asks why they didn't just try more ways of making companions unkillable without/before going through all that debugging. The response:

> that was our fallback, but

> -without actually knowing the cause, we couldn’t be sure that’d fix it

> -whatever the cause of the problem is might be causing OTHER problems, so we should find it

> -games near ship are fragile and it’s best to not make changes you don’t 100% understand

_THIS_ is someone that is practicing good software practices. I have no doubt this is why Outer Worlds is so much less buggy than, say, recent Bethesda _patches_. I saw a report this morning that the latest Fallout 76 patch causes some armors to degrade when a weapon reloads. This sounds exactly like the kind of bug you'd get from "fixing" something without understanding the actual cause, and thus just kicking up more emergent bugs because of your fix.

Complex interactions (like modern games), filled with shortcuts and assumptions (like modern games) means some bugs are inevitable. Requiring rigorous understanding before making changes can keep those bugs from multiplying.

...says someone with zero experience in coding games, but plenty of experience both fixing and generating bugs.

[Edit: fix formatting]



> _THIS_ is someone that is practicing good software practices.

There's nothing specific about software in there. My mechanic does the same type of reasoning.


You must have a much better mechanic than usual. Most of the ones I've worked with tend to make a quick guess at what's broken, and just replace it. I call it "throwing parts at the problem" when it goes badly.

Though in defense, most of them are good enough to guess right 90% of the time. And mechanics generally get paid by the task, not hour. Replacing the probably misbehaving X pays. Spending an extra half an hour making sure that X really is broken and replacement is the best solution doesn't pay. So they just replace the X and hope for the best, and then replace something else if it didn't work.


Replacing a standardized part in a mechanism that is built entirely from such parts is quite different, though. You don't have to worry about breaking something - and that is entirely by design. This kind of thing is what makes the logistics behind our civilization scale so well.

That we do have to worry about breaking something in the software industry field, just tells us how far we've yet to go.


Agreed; it's a blessing. I'm actually keeping my brand of car as long as my mechanic retires, and I have 2 brands that I won't ever touch again due to bad experiences with contract garages.


It would be a good software development practice if they fixed it in a couple days top. It is not really acceptible if such a bug survived so long.


I disagree. Placing a time cap on finding , fixing, and documenting the root issue of a bug incentivies beating the clock over working the actual issue. However, this all depends on the buisness goals for a software development team. If long term stability is not that important, then I can understand why a time cap for fixing a bug is encouraged. Ideally though I would encourage developers to find organisations that allow developers to understand the root of an issue before fixing it.


You can always do the both. If there was an "easy" fix that can be applied in a day or two, it should have been done.

Take all the time you think you can afford if yyou software is not released. But it is being used by customers and such a large bug is in it and if you are not reacting to it then imo it is a problem.

I think people disagreeing with me is unable to see from the perspective of customers. In this case a player that loses hours of progress because of a bug deserves some atention


> You can always do the both.

> If there was an "easy" fix that can be applied in a day or two,

> it should have been done. Agreed.

However, when someone asks for this, the implicit assumptions are that the "easy fix"

- actually fixes the symptoms (even though ignoring the root-cause),

- and does NOT introduce additional unexpected behaviour.

Ensuring this may sometimes make the easy fix just as time-consuming as a proper fix, thus favouring doing it once properly.


Unless you understand the root cause of a bug there is no guarantee that an easy fix won't cause it's own problems. And if a system us so complicated that you cannot understand the root cause of a bug before doing a fix then it's very likely that the fix will have unexpected side effects. The end result is more rather than fewer bugs.


You are underestimating how seriously difficult some bugs can be to diagnose. I've seen super difficult bugs in large complex systems take over a month of dedicated effort to solve, despite the eventual fix being only a few lines long. That's the kind of bug where you take dozens of pages of notes as you puzzle through figuring it out. And this is at Google, with smart engineers. As the old saying goes, it's knowing where the problem is that's hard.


I don't buy this at all.

This is the antithesis of defensive programming. It's a game-breaking bug that's allowed to happen because of two things:

1. They allowed companions to take damage because they marked them with the wrong property

2. They never checked if the companions went somewhere silly to warp them back to where they should be

That's not defensive, that's like calling an API without a defensive try/catch if something goes unexpectedly wrong.

If they'd have done either of these things (and sent back error reports when it happened), they'd have caught it way sooner.

I don't write games and appreciate the interactions can be very complex. While I can understand your delight in them finding the root cause, I can't understand your support for failing to put in some defensive measures when they couldn't recreate a frequently reported bug.


> I can't understand your support for failing to put in some defensive measures when they couldn't recreate a frequently reported bug

From the tweet series: "There were one or two cases before launch where this issue seemed to happen, but no one in QA ever managed to reproduce it and despite our best efforts we couldn't learn anything concrete about it"

Assuming this is true, before launch, it was NOT a frequently reported bug.

After launch, they dove in and figured out what was happening AND what triggered it.

Your complaint appears to be that they (1) had a bug, and (2) didn't resolve boundary checking in the production code. Given the number of "fall through the map" bugs in countless games, I assume #2 is, in fact, hard. Writing non-trivial code without bugs (to avoid #1) is also hard, based on...all the smart coders I've read.

Regardless of the source of the bugs, I'm cheering that they didn't just put in defensive measures and called it a day. To the point that defensive measures can be a source of bugs, consider how many "violent vibration" bugs we've seen in, say, Skyrim, Fallout, and GTA. (While I don't play, based on clips I've seen from GTA and Red Dead, those engine(s) spam duplicate entities when the boundary overlap is detected, where Skyrim/Fallout just vibrate and rattle). I find it very plausible that attempts to "warp" characters having positional bugs without understanding the source of those bugs will end up a source of new bugs.


Re: (2), see https://caseymuratori.com/blog_0005 to see exactly how difficult it may be


The "rattling" in Skyrim/FO is not specific to those engines but seems to happen in all games that use Havok (e.g. all Source based games exhibit the same behavior when something gets stuck in something else).

RAGE/GTA/RDR2 are so insanely buggy games that a game developer probably can learn nothing from them, except how to not do it, and that no matter how broken your games are, you can still earn billions.


>Given the number of "fall through the map" bugs in countless games, I assume #2 is, in fact, hard.

Can’t gamedevs reinvent solidness and make underground/walls solid? Viscosity/density/archimedes?


There's lot of great ways to ensure your collision detection is perfect. Sadly none of them run at 60fps.


collision detection is pretty hard to do in real time. you can't just iterate through every single entity and check if it's intersecting every single triangle in the whole world and have an acceptable frame time.


They are (a solid surface), but game physics are somewhat fuzzy due to performance requirements. Some games teleport you back on top of the ground layer if you fall too deep.


Those defensive measures you describe are the kind of hacks that introduce more and more complexity.

Defensive programming is not fixing bugs with more features, quite the opposite: it is failing hard when a condition does not hold.


Yeah... The whole try/except "in case it throws" without an understanding of IF it should and WHY it might is a huge anti-pattern that creates more bugs down the line than it may potentially solve in the short-term.

If it shouldn't throw, don't try to catch... That is an unexpected failure that needs to be understood.


I get so irritated whenever this is brought up as an "additional security measure". Like, guys, we just found the source of the bug and put in some code to fix it. If it fails again it shows we haven't understood it completely and should take another look. Not just throw in a random try-catch where the outcome is that if it fails again it's just that some string won't be rendered in the application anymore or whatever. Could take months before anyone notices and we learn that something basic has been broken all along.

Thank you for standing up for confident programming! (We could make this a new term if we wanted to :D)

EDIT: Wait, maybe there's a better term than confident programming already... I would appreciate some input if someone sees this.


Wikipedia seems to call it "offensive programming": https://en.m.wikipedia.org/wiki/Defensive_programming


There is a third route. You can add a try catch and then throw a more detailed exception (or otherwise automatically surface the issue while not degrading the user experience) showing the context of what failed, then fo attempt to fix a poorly understood bug for which you may have an incomplete set of reproduction circumstances for.

The best solution is, as always, context and resource dependant.


When I was interning at IBM (~15 years ago now), I saw a bug report closed with "added catch for NullPointerException" as the solution. Something tells me that developer didn't really dig to the bottom of the issue...


Well it depends on where. For ex: If a request handler in your web server is throwing an exception, it's not a good design for the whole server to go down because you thought it was a bad pattern to catch any exception that handling one request might throw. The whole request should fail, return a 500 to the client, and log exception details for later examination, but shouldn't be allowed to disrupt the rest of the server.


Thing is, request handlers cross a boundary. Thus, you really should expect them to get malformed input. This means wrapping it in a try catch because 'input might be bad' is a pretty sane thing to do.

At the same time, you really should try to validate inputs. The idea being that most exceptions caught should be of the form 'Input was invalid'. Rather than 'function crashed'.


Well the parent seems to argue for at least only a very specific and limited catch. Perhaps the most common error is, say, invalid JSON. You wouldn't want to catch only the exception for that though. Maybe that's the most common, but who knows what other kind of subtle bugs might be in there. And the rule of thumb is that the web server process should never go down, no matter what kind of weird data you throw at it. That makes that indeed a case of catch everything, log it, and then move on to handle the next request.


Sorry, I probably wasn't very clear - I'm not arguing that a try/except MUST be very targeted.

> without an understanding of IF it should and WHY it might

rocqua explains it best - the API handler is an "input" to the overall system. That input may be "invalid" in that it fails to handle its own errors. In that case, you should catch a general exception rather than crashing. In this case, you know that it might raise an error, why it might raise an error, and that it's OK to ignore (well, log/alert/whatever.)

The situation I was responding to is very different - it's basically suggesting rather understand what the API you're invoking may be trying to tell you, just try/catch anything it throws and ignore it if you didn't expect it.


> Those defensive measures you describe are the kind of hacks that introduce more and more complexity.

On the other hand, a system where damage is prevented in some ways and assumed not to happen in others is already an overly complex construction of interacting systems. Switching to an invulnerability flag could simplify the system.


> 2. They never checked if the companions went somewhere silly to warp them back to where they should be

In a modern open-worldish game, this is pretty nontrivial.


This can't be understated. Like, for this particular thing? Yeah, you could say "oh, they're out of range of the ship and that should never happen, warp them back." But you have to have them escape the zone first to know you should do that. And what's the most likely way to do that? Falling out of the world. Not climbing. So there's a good chance you'll miss it even if you thought about it!

This is exactly the sort of bug that anybody under the kind of bone-crunching compression you see in game development is gonna fix after they see it. "Don't start bandaging until you bleed."


I think you're right that it would have been a better design if it weren't possible for the companion to die in the first place. But I also agree with the parent that they were right to find the actual cause of their assumptions being violated before deciding how to implement the fix.


Not sure why this is getting so aggressively downvoted. A coordinate sanity check on entities is trivial to do, and at the very least should be logged.


Its not just that, but why test quest failure for if the companion is dead, if in principle companions can't die? This is a typical case of game design where lower level engine systems like physics dictate behavior/cause bugs in higher level functionality like the quest system.

Game engines do everything every frame by default, and the game has to disable/enable stuff from happening, which leads to bugs like this. With a more functional approach instead of tweaking the engine state these bugs can be avoided.


> why test quest failure for if the companion is dead, if in principle companions can't die?

The game's hardest difficulty setting - "Supernova" - allows companions to die [1] (as well as a bunch of other changes that make the game tougher, not just stronger enemies)

[1] https://www.pcgamer.com/uk/which-the-outer-worlds-difficulty...


That entirely depends on how complex the set of valid and invalid coordinates is.


A very basic implementation would use a bounding box. This is done quite often in MMO type games to make sure players don't end up outside the map geometry somehow.


As I said it can be easy or hard depending on the complexity of deciding what is valid or invalid. Just because you can think of something very basic doesn’t actually make it applicable to the task at hand.


Judging how defensive programming worked out for PHP, I consider it an antipattern.


You are wrong, but not downvote worthy wrong. Lets put a artificial cube around the ship, that teleports npcs back to a safe start location (lets call it there bunk).

Now you created a whole zoo of new troubles, including a whole set of troubles you cant even predict, because you didnt know about them when you made this giant default behaviour case.

if (specific case){

} else (everything else that could ever happen, inlcuding all future edgcases){

// here be dragons

}

Examples? Leveldesigner adds elevator, that transports player and npc ocassionally outside of the teleport box.

Skybox entitys are npcs that live outside of the box- so space battle npcs, get telported to bunks..

etc. etc.

Handling the unknown - with any other paradigm then the fail early, fail loud - is the root of evil.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: