TerrariaClone – An incomprehensible hellscape of spaghetti code
github.com
github.com
I'm really talking about the lines in your code, they're structured so well that they will help forge more code in the middle and later parts of your code life.
Like any good video game, if you produce good tools in the beginning to produce levels, modes, multi-player games, etc... then you will produce something great.
If you don't care about what you're writing, then it will become a huge mess and you will either give up or your users will give up. Or once in a life time, the mess you created will still be fun enough that everyone will start playing it, deadmau5 will make a tattoo of it and Microsoft will buy you out and you will have the most expensive house in the world/LA.
As you start filling out the breadth of your design a time will come when you know an idea is going to work, and you have more knowledge to inform your tool.
Of course to what extent you should approach the coding breadth first vs depth first will depend on how clear of an idea you have for the design. If you were just doing a near-clone of Doom and you have done this before then maybe you can just rabbit hole pretty deep from the get go.
1. Make it work 2. Make it work fast 3. Make it work well
In that order.
Then, ignore that feeling until you get proof. If you've kept your code simple and clean reacting to a lack of abstraction is relatively easy, at least compared to what digging yourself out of the wrong abstraction is like.
We sometimes lose sight of this because when we learn that abstraction is necessary, and see how beautiful it can be, we forget that it is an extra layer of mental indirection.
TLDW: "refactoring your way out" from a simple but too short-sighted design might take a ridiculous amount of work, compared what would have been necessary if you knew what a "correct" design for this problem was.
I now favor code that has a lot of independent modules that can have hacky inner code but that must have clear, explicit and preferably simple interfaces. The project's manager role is to design these interfaces and has the last work on their implementation.
This is a bit the Unix way. Every module has to do one thing (and optionally do it well). This allows veteran programmers who know all the subtleties of the programming language to collaborate with rookie programmers who may write okay-ish modules that we may have to rewrite later but that work well enough.
It also allows programmers, these very territorial beasts, to have their own little realms they control and where they are acknowledged. It helps non-tech managers understand who has to be assigned on different issues and evolutions.
Every place that had a great team did it this way.
As a manager, one of my main jobs is ensuring that the team's bus number is always above 1 and scheduling vacation time so that we always have full coverage should stuff go down. There's a huge difference between a silo and giving someone responsibility for driving the design of a component/module. The latter is great, the former is a failure of the team's leadership. You can still get pride of having built something even if you're building it for the team and, through code review, the team is accepting ownership. But individual ownership of key pieces of code has been responsible for most of the top-10 shit storms I've seen in my career and I'm never letting it happen on a team I manage ever again.
But, absolutely, a lack of peer review, authentic feedback, and general teamwork causes all sorts of issues in so many ways.
Small nitpick: I assume to wanted to say this keeps your bus factor up.
One of the important function of the project manager is also to communicate clearly with upper management about what the team is and can do. We were working on a product that was not deployed yet and our priority was to release a functioning version ASAP, so redundancy was irrelevant. We had n features to develop, assigned to various developer. When one developer is on holiday, their features did not advance. We worked around it thanks to our modular architecture.
It meant that sometimes, <urgent but usually irrelevant feature> was impossible to code before <meeting with potential client next week>. I scheduled or denied those. This team and project structure is optimized for fast development with an heterogeneous team, not for reactivity.
Bus number of 1 would be nice to experience for once, I have yet to see a team with a bus number above 0...
Just to note, this wasn't a small system. At least a million lines of code and it was a decision support system. Bugs could theoretically cost lives (at least that's what we told ourselves, but it was kind of a stretch).
This was in a software shop back when we cut and distributed CDs. We had a 3 month release cycle which really enforced #2. I understand this is a lot harder when you are doing 2 week release cycles in Agile or something. With 2 week cycles, full regression for every release kinda goes out the window because there isn't time. (one of the down sides to Agile).
They should be. It's difficult to get quality experience if you're only designing by committee or executing on someone else's designs.
In other words, carving out niches for people is a great way to get your engineers to level up from junior to senior to beyond. They should, hopefully, appreciate the clarity in career progression also. They should be able to see themselves making bigger and more important decisions as they prove themselves.
My 25 years of programming experience says otherwise. The only place where this works is with good(ish) programmers who are assholes and must have their huge, fragile egos stroked or they'll throw a diva fit. I don't hire or work with those people anymore. Neither should you.
Joint code ownership produces better code because everyone wrote some of it and nothing is mysterious.
I don't think it's one or the other. You need people to be able to jump in and contribute and improve things.
But you also need responsibility for the code as a body of work. If everyone with commit access owns the code, nobody does. As time goes on and it's a snarl of spaghetti code and slapdash design, it turns out it was nobody's job to make sure that didn't happen.
On the other hand, joint code ownership leads to endless discussions about proper whitespace formating, variables naming and accessors. It leads to never-enforced style rules that no one likes nor follows.
> I don't hire or work with those people anymore. Neither should you.
If you are unable to work with some people by refusing to use a code architecture that would allow you to use them, does that really make you a superior project manager?
Don't get me wrong, different projects call for different processes. You don't code a blog framework in PHP the same way you program an embedded medical device. In some cases it is a bad idea to give free reign to individuals.
I simply notice that when it comes to abstracting your code, team structure and general project context is often more important than the project's function. In my case (non critical C# project with easily compartimentalizable functions with diverse team members of different skills, different maturity levels and a propensity to argue over minor formatting details) it meant isolated modules communicating through a well-defined API.
The alternative would have been to fire half the team and make a nicer code in twice the time. Not what I was hired for.
Seems less a problem with joint ownership and more a problem with poor leadership.
Seriously- i hate it when Hackers try to reduce theire co-workers to machines and enforce there personal taste as "programs".
If you are unable to deal with humans, to accept unimportant differences, why do you try to define the interfaces for humans on a project.
If all you can do is not enforce some poor coding standards then you are defacto not a lead.
That is not my experience. Sure, there will be some bikeshedding in the code reviews, but you get rid of most attack surfaces by agreeing on lint/formatting options and just delegating the task to a tool. For me, proper whitespace formatting was whatever gofmt spat out. Later clang-format with the agreed team-wide options and currently pretty-js. The team can instead focus on more important code issues like the overall structure or bugs in the reviews.
> It leads to never-enforced style rules that no one likes nor follows.
If no one likes, enforces or follows them, you can't really call them rules. If it is the mutual understanding that some style aspects are not relevant, what's the problem keeping it that way? There is no need to let that get in the way of enforcing some aspects of style in order to produce code that anyone in the team can easily work on.
> In my case (non critical C# project with easily compartimentalizable functions with diverse team members of different skills, different maturity levels and a propensity to argue over minor formatting details) it meant isolated modules communicating through a well-defined API.
IMO one of the best ways to train a new programmer is to have them work closely with more experienced people and with the same level of review scrutiny. I don't know about the project you are working on and its timeline, but in the long term I believe this pays off by turning newbies into good, independent programmers that produce readable and idiomatic code. And no one needs to argue about minor formatting details with the tooling available today. It's a self-imposed waste of time if anything.
But there needs to be a "Joes is responsible for the well functioning of microservices X1, Y2, Z3" - even if there may be 5 other people working on these same and others.
Also, people's "fragile" egos can be turned to your adavantage, as a manager or owner, but that is "black magick" and an oath I have sworn not to share its ways anymore ;) ...
That implies that Joe has some kind of authority over the 5 other people, I hope. Otherwise that sounds like a "responsibility for blaming only" situation.
>>> they'll throw a diva fit
? I'm not a native english speaker and although I get the general feeling, I don't get the exact picture this should paint in my mind... (and I bet it should be a funny one)
So "throwing a diva fit" is to get mad about something solely because it is not how you'd prefer it to be, regardless of what others think.
The alternative is to think up new architectures and team structures that allow more people more freedom to work.
Being free to do things your own way often means choosing not to do something if it's going to negatively impact other people. Once you realise that you need to think about the way your decisions impact other people you quickly realise that compromising on your choices for the benefit of the wider team results in much better code.
This becomes more and more important as the team grows, as there are more feet that you can step on. Working on a large team is really different than a solo or small team. Large teams are as much about communication, mutual respect, and shared goals than writing good code. Unfortunately, communication takes time and energy, and necessarily slows down the entire process, but it's critical.
The Mythical Man Month lays this out nicely. The possible lines of communication in a N person team grows quadratically at N*(N-1), which explains why large teams are often far less efficient on a per-person basis than smaller ones.
in a professional context requiring collaboration, that's an asshole move, and people who do that sort of thing on a regular basis should be reprimanded.
The microservice approach has its own problems but hints toward a direction where teams are small and autonomous, with ground-up freedom on the architecture of their little service and free from draconian oversight. I'm not an advocate of microservices, but it's an approach that hints at something different.
A flat fully connected hierarchy is better for small groups, but it doesn't scale well as the number of lines of communications is proportional to the square of the number of people.
Quite literally, I think, it could be modeled as a vector space in linear algebra. Each signal is in frequency space, which can be found from the fourier transform integrating the temporal space over different bandwidth channels per sender. You get N² only if the message size is proportional to N, if you will.
a Fourier transform of channel
"everyone writes it" in the long term can still allow specific people to write/fix/augment/refactor/etc specific parts in the short to medium term. i think it's a good goal to never have a part of the code that less than two or three people can maintain, but preferably more (depending on size of team(s) and codebase(s), obviously). i think this generally results in better quality code, and higher bus factor is inherently a good thing anyway.
i used to be kind of against style guides and style checking. but a not-too-rigid set of style norms, the willingness to bend or discard them when justified, and a generally well-behaved group of people that can collaborate well and agree that shared understanding has a lot of inherent value... those things together can get you a good codebase where "everyone writes some of it", or at least everyone can deal with most of it, even if people might have areas of expertise. nowhere near a panacea, and not even necessary depending on the team, but it can be useful even if it means people give up style tics they love or tolerate ones they hate. it also mechanically eliminates a lot of the temptation to nitpick a whole class of things that probably doesn't deserve nearly as much nitpicking as it'd get in code review, because everyone thinks their own personal taste matters more than it actually does (me included, that's why i used to not like style guides).
all the above is much easier if everyone's able to keep their ego in check, be collegial, enjoy the challenge of justifying decisions and accepting constructive criticism, etc. i guess that can be an unfortunately difficult setup to come by, but i've been really lucky on that front, by and large.
> To solve this, you normally end up with a hierarchy of authority, where most people have to have their work vetted by seniors.
if you have what i described above, peer level code review with team leads and managers for the occasional tie breaker should work fine the vast majority of the time.
> In this process, people lose autonomy and can't fully act on their own vision.
if you work on a team, you have to work toward shared goals and vision. if a person wants to fully act on their own vision, they should be self-employed in a company of one (though they'll still be subject to market forces). if you're collaborating, you're necessarily involved in a shifting balance of autonomy, delegation, and being delegated to (which is often but not always where the autonomy comes in).
But with collective code ownership it's still useful to designate a couple of developers as "stewards" for each major component. They don't own the component, but they take responsibility for training other developers on the internal design, making suggestions on refactoring, and reviewing design proposals and code diffs.
Also, most of the time, small self-contained units of code are trivial to fix if the original developer goes under the bus, because small means any half-decent developer should be able to read the code[0] and understand it, and self-contained means you're not afraid to change things because you can easily track how the effect of your changes propagates.
--
[0] - an activity that people often shy away from, or are afraid of. Can't for the love of God understand why.
Having a lot of individual pieces that connect using simple, straightforward interfaces is much more flexible and maintainable in the long run - it's the same reasoning that draws people to microservices.
Is this necessarily a bad thing? I know this quote and it always made a lot of sense for me. But I never understood where exactly is the problem, and why one should go to great lengths to avoid this.
Moreover, in this concrete example, isn't assigning modules to individual developers (as opposed to collective code ownership) essentially the same? i.e. structuring the code along the organization communication structure?
https://mobile.twitter.com/KentBeck/status/25831623306839654...
> "Any problem in computer science can be solved with another layer of indirection"
Otherwise, good point – I did not think of this.
There’s a trade-off between time to completion and designing debt-free code, and I think that one small mantra helped me find the right balance. And let’s be realistic, the only debt-free code is code that is never touched by new implementation.
"If you don't know which way is better, do it both ways and compare."
Better finish 80%, than miss 100%.
I realized before writing it that there I would never use this script after today, no one ever had to see it, and it would never get version controlled. So i just wrote it in the quickest "get it functional for 95% of cases and throw an error otherwise"
It was kind of fun. Multiple parts had godawful big-O run times, multiple anti patterns, etc. But none of that mattered since it would never be used on a massive file and would never be in production. It took me back to that phase where i was young and doing pet projects and i could be as selfish as possible.
Sounds like programming in go :)
PS. It's a joke, I enjoy go myself.
A long time ago, I (briefly) worked with Enterprise Java. The things I saw were far worse than this. 100+ deep callstacks[1]. Dozens of layers upon layers of do-nothing indirection. Dependency inversion and injection used for just about everything. 50+ character-long identifiers. Tons of XML-based configuration. The majority of the code consisted of nothing but methods that only called other methods, perhaps with a trivial conversion or reordering of the arguments.
This is perhaps an excellent example of how severe underabstraction is much better than severe overabstraction. There's very long sections of code here and some of it's very verbose, but it's all very concrete and just about every line is actually "doing something": the ratio of "actual computation" to fluff is very high. If given the choice, I'd much prefer working with a codebase like this than a lot of the Java/C# stuff out there.
I also echo the sentiment from others that the author is clearly very talented and dedicated, and deserves much praise for even attempting to write something like this and getting so far with it.
[1] Not mine, but for an example of this insanity: https://ptrthomas.wordpress.com/2006/06/06/java-call-stack-f...
I've been trying to work that kind of coding style into my job, but it is difficult to do so without feeling embarrassed. My team also tends to jump on me when I try
@Author - Must admit although I'm glad there was a 3d array, I'm a little disappointed there were no object arrays. good job for getting it working, even though it was probably should have been put to bed...
This is a major reason why I no longer like OOP (I used to be religiously wed to it). Lightweight functions in modules, with structures that basically just hold data can be cleaner and far more flexible than a big object.
> People write MLOC monstrosities in Java because they can. You get some boring financial topic and some sub-par programmers and they'll write as much garbage as the language can possibly sustain.
> These things are a testament to how safe and simple Java is as a language.
> Not having massive crappy code bases is a negative sign in terms of how reliable and easy to understand a language is.
https://github.com/raxod502/TerrariaClone/blob/master/src/Do...
which is fortunately only used in a comment here: https://github.com/raxod502/TerrariaClone/blob/9ea04b15add48...
It's actually a method to convert from the index of an inventory hotkey slot into the keystroke used to access it -- there were ten hotkey slots, which were numbered 1–9 and 0 at the end.
But I like all the other interesting interpretations here :P (They all assume way more knowledge than I had at the time.)
There's an example on SO, I got similar results just now when I replicated it:
https://stackoverflow.com/questions/15596318/is-it-better-to...
It doesn't matter on my machine whether the divisor is 10 or 42 (as in the example), the branching is way faster. Now, maybe if the branching were not in a loop and hence not so easily predicted, it wouldn't make a difference. But if this code is not being used in a loop, optimization may be premature anyway (as indicated in my original comment).
Probably f() has something to do inside the main game loop and gets called on a bunch of objects every frame. I haven't looked at the code enough to know if that's a bottleneck.
And the branch instruction is free??
Yeah, no, that's not free.
I can confirm that the actual reason is that at the time I thought typing "print" instead of "System.out.println" was a great idea.
This bring back a lot of memories. Way, way back in the day i wrote a clone of Battle City [2] in XNA with a half-decent AI. I had intentions to learn and use some OOP patterns. I ended up with a handful of monstrous classes and generally a clusterfuck of spaghetti code. But... i learned a lot about AI and path searching algorithms and, best of all, it worked. I think i still have this code sitting on a disk somewhere. This makes me want to throw it on Github.
Thanks for sharing!
Be sure to read the issue. It turns out it's not really a joke - someone in the know points out that Terraria's code is basically the same quality, if not worse...
These days there are a fair amount of production Unity games out that you can extract full sources for.. Can make for a fun read sometimes.
It's a huge success story in my book.
The concept of GameObjects, Components and MonoBehaviours and best practices for how they should be composed isn't exactly obvious. Eg when adding two components of the same type to a GameObject it's hard to know which one of them is which (eg two colliders: one for triggers and one for physics) so instead you add two sub-Gameobjects each with that component attached and use gameobject.GetParent() to modify the parent. Is that best practice or not, i don't know, i just did it and it works but it certainly feels strange.
Coincidentally and fwiw, the actual source code to Terraria was also a hellscape of spaghetti code.
Can you talk about this? What was involved? Why do it? Major roadblocks? Do you feel it was it worth it?
I honestly just assume that anyone that says XNA in the context of development in the last 5 years actually means one of the modern mono implementations.
Actual commit I did a few days ago:
> Begin rewrite of rewrite of rewrite
It's a vicious cycle...
It's old school PHP, with sql queries mixed in with markup mixed in with php business logic - if that's not spaghetti code, I don't know what is.
(I'm replacing it, but it's a very slow process).
Well, it was in an SVN repo... with a single commit.
It did have all the important switches at the top, none of them but the ones that were set actually worked.
Man, I "miss" that job.
It was a wordpress site for a company written by some 16 year old intern. Terribly fun. No version management. The main folder had multiple older copies of itself in seemingly random subfolders. It went deep. The CSS was stored partially in CSS files, of which there were 20 (!) loaded from the theme folder, partially in one of the 40+ plugins used (not an exageration). But there was also plenty of CSS in the templates, the database and seemingly random third party servers. The favicon was 20MB large. It used like 4 plugins for “custom fields” all of which had infected large swathes of the database, and all of which did... something. Much like the root folder had nested copies of itself there was something similar going on in there... I simply didn’t bother by the time I understood what the hell was going on. The templates were basically this premium theme of “customized” php, the fun part was that in some page templates it basically rendered a bunch of different pages inside the template (the guy apparently didn’t understand the concept of closing tags, yet somehow made it work. It was incomprehensible.) and then used custom css to hide the pages that shouldn’t be visible. Basically the entire thing was some satanic equillibrium of bugs cancelling eachother out.
It was a work of art.
Well, that's actually impressive :D
Given enough time, maintaining a much larger body of code than a single person can reasonably handle, you're going to have disagreements with yourself without even realizing it.
Past me has been and always will be an idiot as far as present me is concerned (with some infrequent exceptions).
3 years (of occasional work, maybe 1-4 hours a week) later and I've got a layer on top that can interact with all of the slightly different data models of the four apps and I'm gradually replacing the legacy code with new code and migrating them all back into a single database/app.
Since I'm not working for money, I maintain sole ownership of the code, and I hope to eventually turn it into a passive income source, since it will be useful to other, similar organizations who have it even worse as far as their web applications go.
[Edit: I don't blame him - I understand how it happened, and also why he wanted to get out ;)]
He is a manager now, though, not a day-to-day programmer ;)
If you don't then you are basically one developer doing a serial simulation multiple developers miscommunicating in parallel.
The thing is you sort of need to write like this for the first draft of your first game. And Terraria is pretty ambitious. Considering most people struggle with BlackJack or Pong or Snake!
Given the choice between interviewing a student who had produced nothing but verbiage and one who had produced TerrariaClone, I would go with the latter without even thinking about it.
The AP class was mainly a self or group study class inside of a lower level programming class.
We didn't get as much directed study, but we basically were allowed to chose projects that interested us and spent a lot of time developing them and getting help, iterating, figuring it out.
We ended up doing only OK on the AP exam, but we had built a pretty impressive little java app by the end. A scrolling tile based map, enough network code to run a chat and let users join, and we had started building some game logic on top of our multiplayer game room. Very cool and informative, but not exactly what the AP exam was looking for.
A few of us spent the time working on our own real-time strategy game written in Java and using Anim8tor for 3d models. By the end of the year we had a map, artwork, and some network code to allow multiplayer. You could place buildings, select units, move, attack, etc.
My friend found the source on an old USB drive a couple years ago and we were able to get it running again. Some of the code was hilariously bad, but we were both impressed that we had been able to get that far and that it worked since we didn't really know what we were doing. Fun times :)
then even pong is pretty hard.
not with those O(N^2) loops it ain't
To me this perfectly fits spaghetti code.
https://www.joelonsoftware.com/2001/04/21/dont-let-architect...
For the record, this one is not that bad. It is comprehensible and pretty easy to refactor. Real spaghetti is something you have no idea what it does.
That's usually termed lasagna code. Lots of layers with a little bit of filling in between.
Just use global state! Then you can have something where Module A depends on Module B. Now, at one point Module A calls into Module B which fires off an event that's handled in Module C that then calls back into Module A. If that event is going through a pub/sub notifier, bam, hidden global state. Good luck tracing that subtle bug down when you swapped out implementations of Module C thinking the new one explicitly filled the contract of the old one, or worse yet not realizing Module B indirectly depended on C in the first place, and that A's response to the call from C may repeat the cycle several times. Soon you realize everything depends on everything else and your tooling does you no good. That's spaghetti code, just as bad or worse than the gotos sprinkled through some ugly C code that an undergrad wrote in the 80s.
Personally i associate it with lack of abstractions, or extremely leaky abstractions.
They had serious problems implementing multiplayer because they had to synchronize objects with 50KB of state every frame.
What the fuck
What was no doubt written like this:
if(a < 1){
}else if(a < 2){
}else if(a < 3){
}else{
}
Decompiled into this: if(a < 1){
}else{
if(a < 2){
}else{
if(a < 3){
}else{
}
}
}HitEffect is a quite the function.
This reminds me of working on CDDA[1] before many of the refactors hit.
CDDA is an interesting case, it stemmed from a situation similar to the original post (one person project, embarked upon it before knowing how to do so). It was a complete mess of macros, spaghetti code and data and code living happily side by side.
I'm currently having lots and lots of fun playing this game (experimental builds). It's pretty much halfway there to Dwarf Fortress...
I didn't add too many features, I was mostly reducing the amount of compiler noise and fixing any bugs I ran across.
Edit: As someone else noted, if this is a generated file, that might explain a lot of this.
On the plus side, it's fun to press the page down and see the code 'animate' from left to right
However, it is the evolution of several much more embarassing projects. In order from oldest to newest:
https://libminecraft.codeplex.com/
https://github.com/sircmpwn/Craft.Net
https://github.com/SirCmpwn/PartyCraft
https://github.com/SirCmpwn/TrueCraft
I still hate the client code of TrueCraft and it's due to be ripped out and rewritten from scratch. There were also projects earlier than LibMinecraft which, thankfully, have disappeared from the internet.
But wow, you have written some super neat things I had no idea about.
Though apart from just posting to comment praise, more to the topic, I love seeing developer's old work when they were new. It's almost.. humanizing? Like, I swear EVERYONE at one point has were they said "I'm going to learn programming and make the coolest game, better than the other stuff, because I'm creative with ideas."
And then you try it and you realize how not simple and straightforward that is. But you keep on it, you gain a passion for it. And as you posted here, you can see the evolution of skill and pragmatism.
But apart from the topic again, Truecraft is super cool. Sway is super cool and I didn't know about it. I'm going to play with both of them tonight, so thank you for writing two awesome programs for me to spend my day off with :)
The C# code is here, and it works well enough that you can buy it on Steam, apparently: https://gist.githubusercontent.com/alessonforposterity/832da...
It's almost 10k lines of nested if statements, lots of magic values and so on. Still one of the most enjoyable games of its time :-)
Some things I care about a lot less, others I care about more. The biggest problem I have is with obscure code, and my understanding of obscure has shifted over time.
Basically, I prefer code that gets you to ask the right questions. I'm still trying to put my finger on what qualities those are.
I still care about code that looks one way but does something else, and I care about code that conceals what it's doing and how it accomplishes it by using convoluted delegation.
But a function with a single purpose and clearly named? If it's loaded with kruft I only care if it's on a flame chart or I have to keep stepping through it while debugging another issue. So I care more about functions in the middle or the top of the call tree and less about the leaf node ones.
I still push back on "It's not that hard to figure out this code" on the grounds that when an odd bug happens I'm going to be scanning dozens of functions trying to spot an issue. If every one is chock full of code smells, that process takes forever. In fact it discourages people from doing the right thing and instead they slap more workarounds on top instead of trying to find the real cause.
https://github.com/BusyByte/TerraFrame/tree/convert-to-scala
Typically every few months I've improved enough to notice the quality difference.
12 months forward I had made my first "commercial" product - Power Crypt. A Windows application allowing to encrypt / decrypt files. It as written in Delphi, had a single class of ±5000 LOC and used open source cryptography library.
Main selling point was that it encrypted a file not by using a single algorithm, but with all (about 10 or even more) the algorithms the OS library had implemented. Thus making it more secure :-)
I wonder if I could even write it now - even at low resolution? My limited scripting is now systems-oriented, the tiny bit of UI stuff takes me forever & I find HTML & JS way more complex than basic ever was. (Don't misunderstand, I think my python scripts that interact with various AWS services, postgres, etc are just fine and don't take me long to write or maintain, its just the whole graphics world I never latched onto...)
But now the author here says they're doing that same thing! How has this not inevitably led to problems? Or am I misunderstanding the scoping in Java?
The fact that all the methods were so ridiculously large made declaring loop indices globally less of a problem. But trust me, it caused plenty of bugs... :P
Seems surprising, 1.3kloc doesn't feel that big in the scale of things. I wouldn't be surprised if some of the methods at $work would be on the same scale, and it compiles just fine (relatively speaking..). And based on quick scroll-through, there isn't really anything especially egregious in there that would point towards why the compiler fails.
https://stackoverflow.com/questions/17422480/maximum-size-of...
I find in interviews that nearly all programmers only have an approach for two types of applications. The first being a run-to-completion program that produces an output based on inputs. The second being a program where concepts are modeled as data entities, manipulated by behavior (typically just add/edit/delete) in an application/service/controller layer organized using functional decomposition. For problems that don't fit these two, all that is left is that agile hack-it approach.
My hope is that some additional lessons were learned about how to apply appropriate program design to produce a result that won't just result in a different mess next time.
As a cooperative endeavor it should be doable, but a competition would be more fun, though I can't imagine how you'd judge such a thing.
it's a real "beauty" and hacking around in it to create bots was my first experience with programming.
Edit here it is: https://github.com/Rabrg/refactored-client/blob/master/src/c...
Needless to say, I gave up very quickly and convinced myself that this "programming" thing was way too hard. Didn't even start to dabble in it again until high school (and that was mostly a bunch of mucking about with VB6 in Word/Excel).
I'm very much not proud of the code, it's sloppy, incomplete, quite copy-pasta. But it helped me learn a lot of concepts about game dev that a web dev wouldn't know, and it was tremendously exciting to create something in code that you could compile and play around with. No regrets.
We basically gave up after the networking stuff grew over our heads.
Also, the fact you "think" your code is spaghetti shows you have grown as a developer. Kudos.
Love the part about codeToLarge()
I have seen code that is absolutely devoid of reason, logic, formatting, that doesn't even execute... an evented mess with 40 levels of nested callbacks with methods 6000 lines long made by people that just got fired after an incident with comments in some foreign language slang.
https://github.com/Galleondragon/qb64/blob/master/internal/c...
Awesome!
PS: "Abandon all hope..."
PS/2 * : I saw it and i suspected this was code generated by other tool; then somebody commented that this was based on dissasembled .NET bytecode. This explains it all!
* (c) IBM
Grunge C and huge comment block at start, compiles and works though. One day, I'll revisit this and have a think about data structures.
On the other hand, there was nowhere to go from here but up. Gotta start somewhere, right?
Turned out having over 65k of global variables was too much :-D
Here are some commits where I used it to remove boilerplate from some test cases. The code was written long before MSTest added support for Assert.ThrowsException.
https://github.com/dbremner/PowerCollections/commit/a364a154...
https://github.com/dbremner/PowerCollections/commit/1de2f916...
https://github.com/dbremner/PowerCollections/commit/183e3c7c...
Some of it is just plain data (arrays), a lot of the rest is a bunch of setters one after another.
if (left) {
if (right) {
if (up) {
if (down) {
blockds[y][x] = 0;
}
else {
if (upleft) {
if (upright) {
blockds[y][x] = 1;
}
else {
blockds[y][x] = 2;
}
}
else {
if (upright) {
blockds[y][x] = 3;
}
else {
blockds[y][x] = 4;
}
}
}
}
else {
if (down) {
if (downright) {
if (downleft) {
blockds[y][x] = 5;
}
else {
blockds[y][x] = 6;
}
}
else {
if (downleft) {
blockds[y][x] = 7;
}
else {
blockds[y][x] = 8;
}
}
}
else {
blockds[y][x] = 9;
}
}
}
else {
if (up) {
if (down) {
if (downleft) {
if (upleft) {
blockds[y][x] = 10;
}
else {
blockds[y][x] = 11;
}
}
else {
if (upleft) {
blockds[y][x] = 12;
}
else {
blockds[y][x] = 13;
}
}
}
else {
if (upleft) {
blockds[y][x] = 14;
}
else {
blockds[y][x] = 15;
}
}
}
else {
if (down) {
if (downleft) {
blockds[y][x] = 16;
}
else {
blockds[y][x] = 17;
}
}
else {
blockds[y][x] = 18;
}
}
}
}
else {
if (right) {
if (up) {
if (down) {
if (upright) {
if (downright) {
blockds[y][x] = 19;
}
else {
blockds[y][x] = 20;
}
}
else {
if (downright) {
blockds[y][x] = 21;
}
else {
blockds[y][x] = 22;
}
}
}
else {
if (upright) {
blockds[y][x] = 23;
}
else {
blockds[y][x] = 24;
}
}
}
else {
if (down) {
if (downright) {
blockds[y][x] = 25;
}
else {
blockds[y][x] = 26;
}
}
else {
blockds[y][x] = 27;
}
}
}
else {
if (up) {
if (down) {
blockds[y][x] = 28;
}
else {
blockds[y][x] = 29;
}
}
else {
if (down) {
blockds[y][x] = 30;
}
else {
blockds[y][x] = 31;
}
}
}
}Dear Author, at least you know while and for.. it can be worser.