[HN Gopher] Cryengine Source Code ___________________________________________________________________ Cryengine Source Code Author : TiccyRobby Score : 128 points Date : 2020-06-27 07:22 UTC (15 hours ago) (HTM) web link (github.com) (TXT) w3m dump (github.com) | misnome wrote: | Would it be an overreaction to not want to touch this licence | with a barge pole? | | Even ignoring the "We may change this licence at any time and it | applies to you" parts, there seem to be serious restriction on | usage and basically have to ask them to do _anything_ beforehand. | | Maybe it makes sense if you are already in a project that is | using this Licenced? Is this intended as a general engine licence | rather than viewing the source code? | gentleman11 wrote: | I considered using cryengine recently but there was an almost | total lack of learning resources: I could barely find a tutorial | that was newer than 5 years, especially one that involved it's | c++ APIs. | | I suspect that lumberyards greatest advantage over cryengine in | the future will simply be usable documentation provided by | amazon. Cryengine is simply not usable without better docs or | else an incredible amount of time. Crytek is having financial | troubles but I bet their engine would have 10x adoption if they | hired a team technical writers | | Unreals docs are fairly bad also, but at least there are some | third party resources to turn to | mhh__ wrote: | Unreal docs are fairly good for making games but if you want to | modify the structure of the engine it's quite | annoying/nonexistent. | | Case in point: Vehicle physics is no where near as good as the | docs imply (not a toy but still 20 year old vintage), but there | is almost no documentation of how PhysX interacts with the | Unreal engine proper i.e. you can get the PxRigidWhatever | handle but you can't easily replace PhysX with a proper MB | package. Epic seem to be transitioning to Chaos but it's not | documented yet. | | If I ever get good Vehicle physics working I'll write it up | (it's definitely possible but I'm not sure how ACC does it) | zamalek wrote: | That license looks like a minefield. Any lawyers able to chime in | on the reality of becoming tainted? Given their recent history, | this is one codebase you really wouldn't want to risk becoming | tainted by. | gear54rus wrote: | What is their recent history? | zamalek wrote: | Crytek v. Cig, which the court ruled largely in favor of Cig, | and even called out Crytek's behavior (which was an absolute | circus). Crytek will prosecute given even the most | questionable grounds. | | The consequences of taint are a very real risk here. | ebg13 wrote: | Many of the filed issues are "X not work" and not very | interesting, but this one...this one is a real gem. | https://github.com/CRYTEK/CRYENGINE/issues/763 | duncan-donuts wrote: | I'm gonna go with this is a feature not a bug | Nican wrote: | This is on the front page again. Please take some time to read | this wonderful function: | https://github.com/CRYTEK/CRYENGINE/blob/release/Code/CryEng... | | EDIT: That whole function is a minefield. Just taking a quick | look: | | * 814 lines of code | | * goto inside 3 nested for-loops | | * macros | | * commented out code | | * new/delete, with no RAII | | * thread specific variables and locks (?) | dmitrygr wrote: | > new/delete, with no RAII | | There is nothing wrong with this. Plenty of people have no | issues keeping track of memory in their head. | skohan wrote: | I would argue that manual memory management should probably | be avoided as a general best practice, but game development | is a special case where memory management can often be | critical to the performance of the final product, and a | manual approach is sometimes warranted. | ajconway wrote: | Is it an example of bad code? Should we avoid using Cryengine? | krapp wrote: | If it works, it's an example of ugly code. Plenty of game | code is ugly as sin, though. | peterkos wrote: | The code for VVVVVV infamously has switch/case for every | possible screen/level in the game[0], which I think is | hilarious. Best example of "it works!" | | [0] https://www.polygon.com/2020/1/13/21064100/vvvvvv- | source-cod... | skohan wrote: | Games also have a _very different_ set of constraints | than most software. Simulating and rendering an | interactive world at 60-144hz is not an easy task, and | things like code cleanliness, structure and readability | often lose out to performance concerns. | | It's a bit of a strange thing; in my personal experience, | after spending some real time with this type of | constraints, it can be a bit painful to come back to | "general software best practices". You become so aware of | the performance implications of everything you do that | all those things we do in the name of software quality | can feel incredibly wasteful in terms of CPU and memory | resources. One has to remind themselves that in 90% of | cases that level of optimization is not warranted. | user5994461 wrote: | * goto inside 3 nested for-loops | | It's actually a reasonable practice in C and C++ to use goto to | leave nested loops (I am hesitating to say a recommended | practice). | | There is often no sane way to leave the loop otherwise, | break/continue statements only have effect in the most inner | loop. It's possible to set extra variables with lots of | if/break but that gets crazy real quick and much slower (nested | loops are often the hot code path). | aronpye wrote: | It's not just that function, the C file is over 2300 lines | long. It's hard to tell where one function starts and another | one ends in that mess | kccqzy wrote: | Why not? Doesn't the indentation tell you perfectly where | each functions starts and ends? | userbinator wrote: | I'd rather work with this than Enterprise Java. | | At least the logic is all there and you only need to scroll to | see it, instead of jumping around between a dozen or more | different files. | | Math-heavy code tends to look dense to those who are accustomed | to more "mundane" LOB type applications. | kccqzy wrote: | This. The convenience of everything in a single file is | underrated. You can do all the modern best practice like | splitting into more functions, making functions small, and I | wouldn't mind if they are all in the same file. | barrkel wrote: | If the code was separated out into functions that are only ever | called once, I'd find it harder to read. | | Analysing code I'm not familiar with often consists of manually | tracing through calls, producing documentation that inlines all | the single use function calls. | | Ideally function names act as shorthand for the body of the | function, but if they only have one caller they have nothing to | keep them honest. In older codebases, function names are as | misleading as comments; semantic drift, special cases etc. mean | you need to drill into them anyway. | mopierotti wrote: | I agree with the gist of your post, but one positive about | single use functions is that you can be explicitly clear | about data visibility. | | In this contrived example, you can tell that formatting a | title is not affected by user preferences, but formatting the | body is. (And additionally that formatting a body has no | information about the other fields of an entry) | def formatRssFeedEntries(userSettings: UserSettings, data: | List[Entry]) { val titles = data.map(entry => | formatTitle(entry.title)) val bodies = data.map(entry | => formatBody(entry.body, userSettings)) ... } | barrkel wrote: | I agree. Blocks can somewhat substitute with scoping | effects, and that's what I do with my inlined docs - | they're nested {} with plain text description of contents | and mentions of key variables and functions, scope is | useful. | [deleted] | gentleman11 wrote: | 800 lines long. The movement component class in ue4 is about | 10k lines. Why do game engines separate their code so much less | than in other software? | mhh__ wrote: | I feel like C++ makes it particularly difficult to jump | around big projects (mainly headers especially back in the | old days pre good-ide). | | There is also a lot of fear of performance regressions by | breaking up big chunks of code (arguably unfounded with | modern compilers). | an_opabinia wrote: | Games are certainly the most popular piece of end user | software. | | Software that a lot of people use a lot of time looks like | this because the bugs are found and the bugs get fixed. The | code for fixing a bug has to live somewhere. | | What about bugs that computers find? Fuzzers are rarely | recommending to fix bugs that are affecting human users. Part | of that is also that the kinds of bugs that computers can | find are not in, literally, "user interfaces," they are in | APIs and formats. | | Anyway, end user business software also has code that looks | like this. It's not just all tools and infrastructure, I mean | it certainly feels that way. But there are 800+ line SQL | statements. 800+ line transactional method bodies. I don't | want to call this "real code" but the surprise comes from... | well eventually you have to make something the end user | touches. And it's going to be gnarly. | Trasmatta wrote: | Here's a good article from John Carmack on why that can be a | good approach in game development: http://number- | none.com/blow/john_carmack_on_inlined_code.htm... | | I feel like this Cryengine example may be a bad example of | that, though. | [deleted] | smaddox wrote: | Not just in game development. If you have a function that | is only called once, it shouldn't be a function yet. Make | it a function when you have a second or third use for it. | Then, and only then, you will know what the parameters | should be. | oever wrote: | I disagree. Splitting a function up can help with | readability and testability. The parent function becomes | shorter and the child function can have a descriptive | name. The parameters to a function are the fields that | are needed for the function to perform its function. | gentleman11 wrote: | One of my professors used to encourage the heavy use of | helper functions that just... well, like in A or B in | carmacks article, break your code into chunks with clear | names that can be unit tested. | | How common is automated testing in AAA games? | Jasper_ wrote: | Underlying helper libraries like math utilities are often | extracted and put under independent test. A physics | engine often has so much state (and isn't always | guaranteed to be deterministic!) that doing any sort of | unit testing at the functional level is not worth it. To | those that reply with "use less state", I encourage you | to show how. Often times the unit tests I've seen from | junior game programmers are worse than useless and aren't | testing anything of tremendous value. | | Games that use automated tests often drive high level | systems and test high level output. See for instance Riot | Games's automated League of Legends test suite. | naikrovek wrote: | Game development problems are often large global state | manipulation problems. If you don't write games you will | never realize this. | | Almost everything taught in academia and in the | enterprise about software development "best practices" | are absolutely the wrong things for a game. (They're | wrong for enterprise and academia, too, but I'm not | willing to get into that fight on this site.) | naikrovek wrote: | Function calls have an overhead, and if the function is | only used once it makes no sense to break it out. | | It also makes no sense to have a rule on the maximum | number of lines for a function. These rules are often | created by people who don't write software that needs to | have high performance. | artifact_44 wrote: | function calls push registers, allocate a stack frame, | and push a return address. By breaking your inner loops | into more functions you've now generated megabytes of | pointless memory thrash... on a console. Additionally, at | the time this stuff was written, compilers and toolchain | weren't neccessarily standardized, or were customized to | accomodate certain use cases, so they needed more hand- | holding to generate performant code. This is just a | fact.. I'm not saying you're wrong, but you're definitely | viewing this with hindsight. | skybrian wrote: | While this is often a good rule of thumb, occasionally | it's useful to extract a function just to make the inputs | clear for a complicated calculation. Particularly when it | has few inputs and they are unlikely to change. | tobias3 wrote: | With modern C++ you could do this with a lambda | elwell wrote: | There are other reasons for separating logic into | functions besides just keeping it DRY. It's an | opportunity to encapsulate concerns and then, in some | other place, compose the story poetically and clearly. | ConcernedCoder wrote: | ...which is NOT high on the list of concerns for a game | title, what you want instead is massive performance | gains, so you can do more with less, and in the end | produce a better experience than your competitor. -- | function calls/indirection/making your code 'easy' to | understand, all have a RUNTIME cost, and many small costs | add up to a large cost, the reasoning is really that | simple. | pm90 wrote: | I struggle to see how composing into functions adds a | runtime cost when using modern compilers; as others have | pointed out the compiler will inline it if the function | is only used once. | | This rationalization doesn't make sense to me, especially | for game engines which I assume are not limited to a | release or 2 but are used to power multiple titles. If | the software artifact is going to live for a long time, | it's probably worth the effort to make it easier to | understand and test. | tootie wrote: | Breaking routines into functions makes testing possible. | If it's really only called once, the compiler can inline | it for you. | hombre_fatal wrote: | Sometimes with inherently complex performance code it gets | nickel and dimed over time yet maintains so many cross- | cutting concerns and state that there are no clean extraction | points. | | So function extraction ends up taking a bunch of "unrelated" | state with it where, in the end, it feels like you | accomplished nothing but split the code into arbitrary | concatenation points, not logical units. | rurban wrote: | This is physics, not your average function. Those who've never | written physics should not complain. It's actually good code. | gameswithgo wrote: | inside a bunch of nested loops is where you need a goto, if the | language doesn't have labeled breaks (which is just a fancy | goto) | | most of your points are things people notice any time real | actual big software with performance constraints gets posted. | so along with questioning the wisdoms in that function, also | question your own wisdom. maybe some of what you think you know | is wrong. | atombender wrote: | The code looks bad, but not for those reasons, in my opinion. | The logic in this function doesn't look composable. It combines | different kinds of mathematical functions to apply inertia, | whether you're jumping, etc. into one big ball of spaghetti | that would be hard to extend for anyone not deeply familiar | with the code. If I were to try to refactor this, I would try | to decompose it into standalone "behaviour" functions that | could be attached to any entity | Jasper_ wrote: | I encourage you to try! However, a lot of gameplay and | getting movement controls to feel good is difficult and at | odds with the goal of "modularized physics", e.g. you might | want to apply different amounts of ground friction depending | on whether the player is moving, how they're moving, whether | they're holding the jump key, and so on. | | Ultimately, we're trying to simplify a large simulation of | real-world physics and hundreds of controllable muscles and | motor responses trained over a lifetime, down to 5 or 6 | keyboard inputs. That means you tend to have such inputs | doing multiple things, and it's often hard to make separable. | loeg wrote: | There's some RAII: | https://github.com/CRYTEK/CRYENGINE/blob/release/Code/CryEng... | skohan wrote: | As a hobbyist who likes to tinker with game and interactive | media development, a sentiment I often come across is that in | 2020 it makes no sense to implement a game engine, and that I | should just use something which already exists to avoid re- | inventing the wheel. Code like this is one thing which helps me | to calmly ignore than sentiment. | | I came across the same kind of thing when I was kicking the | tires on the Unreal Engine, and I wanted to attempt to add a | double jump. I thought surely this should be an easy task, I | would just need to find where the jump occurs, add a counter, | and remove the restriction which only lets a character jump | when touching the ground. What I found was a monstrous tangle | of indirection similar to this one. | | Now that's not to say that these engines are "bad code" - when | you look at all the things a modern game engine does, including | supporting interactive editing for non-coders, I'm sure there | is some explanation for the level of complexity seen in code | like this just because of how many systems must be layered on | top of each-other. But _that_ is the thing which makes me | question whether general-purpose game engines are really a good | idea at all. | | In most other domains of software we've long ago eschewed this | type of do-everything monolithic software design in favor of | more loosely coupled composible toolsets. I'm not entirely sure | why it seems that game development has yet to escape this | paradigm. | oneshot96 wrote: | Well duh, this is a physics engine. Implement double jump by | placing an invisible floor underneath the player object when | you decrement the counter. | skohan wrote: | I cannot tell if you are joking or not, but needing to | place an entity into the world for a single frame to | accomplish this rather than simply applying an impulse to | the player is precisely the kind of over-complication I'm | referring to | Jasper_ wrote: | Without having read any of the Unreal Engine movement | code, there's a complication here, and that is that | "jump" might be influenced by the floor that the player | is standing on. The force impulse might be related to the | slope in some way. You have to figure out what "double | jump" means in the context of there being no floor. | | Placing a floor that has the influences you want under | the player is, in a sense, a hack, but not an entirely | misguided one. A better design might be not relying on | whatever the "jump" button does, but writing your own, | e.g. applying an impulse to the player directly. | | If this sounds like semantics, consider a game like Super | Mario Galaxy, which has spherical worlds. How do you | determine the correct impulse for which way a "jump" | goes? This is where these sorts of complications come | from. | rtx wrote: | We haven't at place where deciplines interact. | christoph wrote: | I have a feeling you may have been approaching this problem | in UE4 the wrong way. Adding a double jump can be done in | numerous ways, but one simple way is with Blueprints. See | below link where the exact functionality is implemented with | a really simple blueprint. | | https://m.youtube.com/watch?v=hFAr7gYV1rA | skohan wrote: | Oh I am certain I was not approaching the problem in the | UE4 way. But the issue is that the way UE4 expects me to do | things is not the way I would like to approach game | development. | | UE4 has a strong bias about the way things should work. If | I am making something which is fairly well aligned to that | bias, then it's fairly easy to make it work. But if I want | to achieve something which is quite far from what the | engine expects, then I have to invest significant effort | undoing or circumventing what UE4 already does before | adding my own functionality on top. I would greatly prefer | to start from a blank slate, and _only_ add precisely the | behavior I actually want. | | So basically this experience with the double jump just gave | me a window into the level of complexity I would have to | work around in terms of realizing my own goals. | Jasper_ wrote: | I don't think it's the best code I've ever seen, but a lot of | these are surface-level complaints. | | > * goto inside 3 nested for-loops. | | C has no pattern for breaking out of multiple for loops at the | same time. Other languages like Java and JavaScript introduced | "break label;" to handle this edge case. goto is perfectly | acceptable to break out of multiple loops. | | > * new/delete, with no RAII | | They use RAII, but it's not applicable here. In this case, the | developers only want to allocate a temporary array when it | needs to be resized. Since we don't want a large stack | allocation (stack sizes are super small on consoles), using a | delete/free to resize an array seems fine to me. Game | developers have a long-seated distrust of std::vector, and for | good reasons. | | RAII is used for the WriteCondLock which you criticize in the | next bullet point, so it's not like they were unaware of it. | Just not the right tool for the job. | | > * thread specific variables and locks (?) | | You seem to be upset that they have code that uses locks at | all? I don't really know what this bullet-point is saying, | other than "I looked for 5 minutes and didn't understand the | threading structure". | | If I had to take an issue with this code, it's the lack of | enums for e.g. iSimClass, despite it having an enum with | definitions. That's the sort of stuff that's difficult to | reason about and follow along with without having a mapping in | my head. And it has no overhead, so why not do it? | | https://github.com/CRYTEK/CRYENGINE/blob/6c4f4df4a7a092300d6... | messe wrote: | > C has no pattern for breaking out of multiple for loops at | the same time. Other languages like Java and JavaScript | introduced "break label;" to handle this edge case. goto is | perfectly acceptable to break out of multiple loops. | | Yeah, that's not what it does. The code looks like this: | if (pgeom->Intersect(pentlist[i]->m_parts[j].pPhysGeomProxy-> | pGeom, gwd,gwd+1, &ip, pcontacts)) { | got_unproj: if (dirUnproj.len2()==0) | dirUnproj = pcontacts[0].dir; t = | pcontacts[0].t; // lock should be released after reading | t return t; } for(int | ipart=1;ipart<m_nParts;ipart++) if | (m_parts[ipart].flagsCollider & | pentlist[i]->m_parts[j].flags) { gwd[2].R = | Matrix33(qrot); gwd[2].offset = pos + | qrot*m_parts[ipart].pos; gwd[2].scale = | m_parts[ipart].scale; gwd[2].v = -dirUnproj; | if (m_parts[ipart].pPhysGeomProxy->pGeom->Intersect(pentlist[ | i]->m_parts[j].pPhysGeomProxy->pGeom, gwd+2,gwd+1, &ip, | pcontacts)) goto got_unproj; | } } | | Notice (a) the if statement on the same line as the for loop, | and (b) the fact that the goto jumps out of a conditional | inside a for loop inside of a conditional into a conditional | just before the for loop. | | EDIT: Just realised the poster is referring to a different | function. | | IMO this one is more horrifying. | Jasper_ wrote: | That's in a different function, so I wasn't counting it, | but sure. I mean, I would write it differently, but it's | fairly readable. It's jumping to a common function epilogue | once it finds something it can collide with. Seriously -- | try reading through it rather than gawking at the goto. | naikrovek wrote: | It's funny watching people reply to you without knowing | anything about your skill set and experience. | | Jasper_ is the real deal, people. | userbinator wrote: | Either that code is misleadingly indented and you copied | one more closing brace than necessary, or you omitted the | opening brace for the last if's body (which contains a | single goto). | messe wrote: | Good catch. I think I copied one more than necessary, and | then messed up when trying to fix up the indentation for | HN. | nolaspring wrote: | Also Requires visual studio | layoutIfNeeded wrote: | "You may not like it, but this is what peak performance looks | like." | stephc_int13 wrote: | As a professional game developer I disagree with most of your | comments. | | This code is clearly not perfect, but the from what I've seen, | this is something I could work with. | | - Function names are easy to read and understand. - | Indirections are kept to a manageable level. | Nican wrote: | Not going to lie, playing Crysis was a lot of fun, and I | never knew this was the underneath function running it. | user5994461 wrote: | Crysis shipped with a full blow SDK that included most of | its source code. You could actually rebuild the game from | it, the 50MB dll that controlled the whole game. | | Old players maybe remember that the crysis multiplayer was | the most cheated game in its era. It was totally unplayable | due to all the cheating and that killed the game. | | One way to make cheats. You could load up the SDK in visual | studio. Find the code that's removing -1 ammo when shooting | and edit it to not do that (most of the physics and game | logic was editable that way). Compile the DLL. Replace the | original DLL in the game directory. | Nextgrid wrote: | Was ammo in Crysis controlled client-side? I've always | assumed such counters were stored server-side and thus a | server won't apply a "fire" event if the player's ammo | counter is at zero until it receives a "reload" event to | reset the counter. | rurban wrote: | The real issue is clear from their announcement post. | | master (now main) was not always stable (of course, stable code | are in the stable and release branches) so silly people | complained, and the silly PM reacted by closing down pushes to | main, and hereby closing down issues and PR's. He clearly has no | idea how open source code development works. Now they have to | maintain two repos, the internal one and thd public one, and get | no feedback from outside. Well, feedback on one year old code. | reykjavik wrote: | Used to work with cryengine some time ago. That is by far the | worst c++ codebase i've ever seen. | Roritharr wrote: | Interesting sentiment, I sometimes wonder if a "messy" codebase | can have advantages for performance. | | Many very highly performance tuned applications I saw in the | wild would fall into the category of "horrible codebase" when | looked at through that lens. | mhh__ wrote: | I don't think it's necessary. With modern C++ it's possible | to encapsulate high performance code. | | The issue with games in particular is probably partly due to | the performance optimizations being directed at a moving | target (it's not just your supercomputer nodes, it's every | computer CPU). C++ doesn't really help you much in that | regard (or at least better know but certainly not 10 years | ago) | nocturnial wrote: | It falls more in the category of having a lot bugs which | could've been caught if they used static code analysis, code | review, etc... | | I understand that you might think that messy could mean it's | fine tuned for performance. In this case, I highly doubt it | and think it's more reasonable to think it's messy because | they had deadlines. | | The messy part isn't about performance optimizations. It's | more about things that got crammed in there and only works | for a very specific subset of parameters. And even then you | can't be sure it'll work... | | I don't blame the programmers, it feels they had deadlines to | uphold from managment. | noarchy wrote: | >I don't blame the programmers, it feels they had deadlines | to uphold from managment. | | This is my own experience. The teams that spent the most | time on standards usually had the least pressure, in terms | of things like deadlines. Once the focus of the team shifts | to having to ship things, there is less time to worry about | having 100% code coverage (to pull out an arbitrary | number), and so forth. Code review can slip into flagging | only things that really matter, and leaving nitpicks for | another day. | gentleman11 wrote: | What sorts of static code analysis tools do people here use | in their game projects? I know carmack is a big fan of them | nocturnial wrote: | Here are the results for cry engine specifically: | | https://www.viva64.com/en/b/0417/ | | https://www.viva64.com/en/b/0495/ | | https://www.viva64.com/en/b/0574/ | | I'm not endorsing pvs studio nor am I saying it's bad. | Try out some tools and see what works best for you. | gameswithgo wrote: | I have used the Rust compiler, which will catch all | memory errors, data races, and null pointer exceptions | and buffer overflows at compile time as a matter if | course. then you can add cargo fuzz if you like. | wwright wrote: | Let's assume that when code is first written, the cleanliness | and performance is somewhat random within a broad range. | | If we want the code to be clean or performant, we will likely | have to spend time iterating on and pruning the code. Let's | assume that improving performance and improving cleanliness | are at best orthogonal, at worst opposing. | | The project has a limited amount of time, particularly for | games, which often have a relatively low roof for how much | maintenance the code will need. | | The project has a budget on time to spend between cleanliness | and maintenance. Games need high performance and relatively | little maintenance, so they are more likely to spend their | budget on much more performance than cleanliness. | | (Game engines meant for heavy reuse such as Frostbite and | Unreal Engine would likely have a much more even split, and | similar for games which are likely to receive recurring and | invasive updates. I would expect Fortnite's code to be fairly | clean as games go, for example.) | jokoon wrote: | Generally, things that are not open source are rarely not well | written, since there are less programmers who will read your | code, and all questions on the code can be done internally, so | developers only write code so it works. | | Open source generally leads to better quality code, since it's | the best way to attract other developers to contribute to it. | | So I'm rarely interested by any accomplished project that opens | its code. | | For example, if microsoft opened its OS, I doubt developers | would really try to do things with it. The windows kernel would | obviously be high quality code, but a lot of the rest is | probably short lived garbage. | dman wrote: | I disagree with this line of reasoning. I have seen good/bad | examples on either side. I think it actually comes down to | someone on the developer team having a high set of standards | that they push everyone to subscribe to. | mhh__ wrote: | It's only tangentially related to code quality but I do | think open/free source is the only way to write sustainable | software if your aim is to change the world rather than | ones bank account (so to speak). | | There's terrible code all over the place, although it is | definitely true that no one's going to clean up - even | source available - proprietary code out of kindness of | their heart. | gentleman11 wrote: | All the open source projects I have personally seen were | ones meant to live a long time. When there were code | issues, there were always awkward discussions on github | about "there should be unit tests here" or "this code makes | no sense," and weeks later the developer announcing a | cleanup or some sort. Anecdotal but public scrutiny and | pressure is a real thing. | | Just as an example, this is why Bitwarden started getting | some automated testing - lots of propelled bumping github | issues about it in order to get it more visibility | remram wrote: | > things that are not open source are rarely not well written | | I think you got lost in your triple negative there | jokoon wrote: | yes, english is not my main language, thanks for the | correction | squarefoot wrote: | Openness aside, working under constant pressure with | crazy deadlines also paves the way for ugly/barely | tested/hard to maintain code. Game studios often have | extremely strict deadlines, but I've experienced this | pressure also when working in government software; this | code looks like examples from Dr Dobb's compared to the | pile of crap we sometimes could barely stick together in | the old days. | [deleted] | halotrope wrote: | While your opinion is appreciated. It would be more helpful, if | you could point out sone of the reasons why it was so bad in | particular. | dang wrote: | If curious see also from 2016: | https://news.ycombinator.com/item?id=11760298 | | Related significant threads: | https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que... ___________________________________________________________________ (page generated 2020-06-27 23:00 UTC)