55 comments

  • Buttons840 2385 days ago
    This makes me miss my early days of programming, where no code was too verbose or horrible to stop me from progressing towards my goal, no matter how misguided I was. Nowadays I'm distracted by the first hint that there might be some better way, and all progress stops. I think I'm just beginning to recognize this, and maybe one of these years I'll learn to recognize when the right abstraction is really important and when it's not worth sweating the small stuff.
    • Iv 2385 days ago
      As I had to work more with teams and then supervising teams I changed the abstractions I value from when I was programming solo: Now I care less about my project's function than the structure of the team. There is a saying that any complex project will end up mimicking the communication structure of your organization. I must confess I thought it was silly until I realized it happened to us.

      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.

      • nickbauman 2385 days ago
        > allows programmers, these very territorial beasts, to have their own little realms they control

        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.

        • Iv 2385 days ago
          I agree that my wording maybe gave a wrong idea about the strength of the "ownership". Code has to be readable and commented and peeking into each other code is welcomed, calling for help or reinforcement on a module is recommended. "Realms" is something that is unenforced and that emerges implicitly.

          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.

          • boomlinde 2385 days ago
            > On the other hand, joint code ownership leads to endless discussions about proper whitespace formating, variables naming and accessors.

            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.

          • meheleventyone 2385 days ago
            > 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.

            Seems less a problem with joint ownership and more a problem with poor leadership.

            • WillReplyfFood 2385 days ago
              Only a broken peasant, reduced to a mere Automaton, garants the quality and innovation- that this company is so proud to produce.

              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.

              • meheleventyone 2385 days ago
                The point was if you’re trying to make joint code ownership work through those things you are already doing it wrong. Want everyone to run with their own style? Fine. You need to make the style sensitive parts of the process work. Whether that’s to adopt local style or something more complex.

                If all you can do is not enforce some poor coding standards then you are defacto not a lead.

              • s73ver_ 2385 days ago
                I think the same thing could be said of those who refuse to follow the coding standards.
            • miko1293949 2385 days ago
              This is mind base
        • shrimpx 2385 days ago
          There's a tension between "everyone writes some of it" and individuals having autonomy to focus and make decisions. If everybody has autonomy in a shared codebase, you end up with a heterogeneous spaghetti of unrelated design decisions and styles overlapping everywhere. To solve this, you normally end up with a hierarchy of authority, where most people have to have their work vetted by seniors. In this process, people lose autonomy and can't fully act on their own vision.

          The alternative is to think up new architectures and team structures that allow more people more freedom to work.

          • onion2k 2385 days ago
            If everybody has autonomy in a shared codebase, you end up with a heterogeneous spaghetti of unrelated design decisions and styles overlapping everywhere.

            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.

            • speedplane 2385 days ago
              > 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.

            • shrimpx 2384 days ago
              Good point. I think what you're hinting at is good if all or the vast majority of people are on board. In my experience this is not generally the case. People usually climb up the authority ladder not because they are emphatic toward others, or because they compromise on their choices to help the team, but because they solve technical problems and deliver product to customers, often while cutting corners and making executive decisions in the code base. More junior and newer people are at the whim of these more senior people, regardless of whatever egregious technical decisions they like to make.

              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.

            • watwut 2385 days ago
              The trouble is that in closely cooperating teams where I worked, people who did what you suggest ended up in submissive position against people who just do their thing ignoring others. If I proactive think about others and you don't, you get to work however you like it oftentimes making my work more difficult - while I am more restricted and have harder time to make my ideas reality.
              • infinite8s 2385 days ago
                What you describe doesn't really sound like a "closely cooperating" team.
                • watwut 2385 days ago
                  I meant team without clear responsibilities and "turfs" supposed to work together :). Clear reasonable responsibilities are an awesome thing and kill whole bunch of insecurities and resulting behavior.
              • arthur_pryor 2385 days ago
                > people who just do their thing ignoring others

                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.

          • nicoburns 2385 days ago
            A good alternative to this that I have found is peer review: everybody gets their code reviewed by at least one other person on the team. Everybody gets to work autonomously initially, and everybody gets their code checked by the rest of the team.
          • speedplane 2385 days ago
            Strict hierarchies suck because if you're a leaf in the hierarchy, it's very difficult to collaborate or work with other leafs that are not in your same sub-branch.

            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.

            • shrimpx 2384 days ago
              A large set of small loosely-connected groups is an alternative. Groups can communicate with other groups on a need basis. This might be a pipe dream. Some would argue that the emergence of an uber-group that every other group must subordinate to is imminent.
            • posterboy 2385 days ago
              no it's not, broadcasting is linear, alas its not strictly parallel.
              • speedplane 2383 days ago
                Each person can broadcast at any time. So at any time, it's possible to have N^2 messages being sent around the company.
                • posterboy 2378 days ago
                  That's a non-sequitur, I guess you mean if every sender sends one message per listener. I don't think it's a broad cast if it targets sole recipients per message.

                  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

          • arthur_pryor 2385 days ago
            > If everybody has autonomy in a shared codebase, you end up with a heterogeneous spaghetti of unrelated design decisions and styles overlapping everywhere.

            "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).

            • shrimpx 2384 days ago
              Great points. By "act on their own vision" I mean technical vision, the how to solve a problem, not which problem to solve. In my experience this is where many engineers become depressed and want to quit. They're interested in the problems the company is solving, but when implementing solutions they become bogged down in myriad rules with which they do not agree. Coding style is simple enough to adapt to. Having to follow a technology stack, core architecture, and core APIs that you find unintuitive is harder. In fact I'd venture to say (as a corollary of Conway's law) that companies that follow the "everybody writes some of it" style breed narrow monocultures, where everybody sees things roughly the same way.
        • humanrebar 2385 days ago
          > 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.

          • nickbauman 2385 days ago
            What you said is contradictory. Jumping in and contributing and improving things happens when everyone is encouraged to change the code anytime. When individuals get territorial is when it rots because people are afraid to touch that "other person's code."
            • humanrebar 2385 days ago
              That could happen. But if your technical leaders are rejecting patches for ego reasons, you need to correct that regardless of how you organize your code. Worst case, some people aren't cut out for technical leadership.
        • nnq 2385 days ago
          People need that feel of "ownership", not based on who made something, that's really bad and lead to "not touching Joe's code, no f way", and probably what you said...

          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 ;) ...

          • xg15 2385 days ago
            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.

            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.

        • watwut 2385 days ago
          There are some people who are easy to joint code with. But there are many people who are not assholes, but joint owning with them is still something uncomfortable to be avoided. Joint code ownership oftentimes means less clear structures and less predictable code, because neither is able to actually execute coherent vision.
        • nradov 2385 days ago
          Yes collective code ownership generally produces the best overall outcomes. Individual developers or small agile teams need to be able to work through an entire vertical slice of the application to deliver a complete feature that has actual value to users. When you divide up the work by code module rather than by application functionality then the user's needs stop being the primary focus.

          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.

        • wiz21c 2385 days ago
          Could you expand on this :

          >>> 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)

          • mekkkkkk 2385 days ago
            The word 'diva' originally described headline singers of opera. The "stars" of the opera world. Nowadays the word is used to describe someone who thinks highly of themselves, and think that their own needs or wants is more important than others. "Throwing a fit" is to start a disproportionally angry argument over something.

            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.

          • colejohnson66 2385 days ago
            A “diva” is generally used nowadays to mean someone who complains about everything. So a diva fit would be a diva throwing a fit. Basically the adult version of a tantrum.
      • Clubber 2385 days ago
        Absolutely this. Some people think silos are bad, but it absolutely works brilliantly in terms of team cohesion. No stepping on toes. Few arguments because everyone is responsible for their own stuff. No nitpicking over irrelevant style preferences. Pride in ownership, self accountability, thoughtful decision making (mostly). All this leads to good working relationships that come in handy when cross-realm issues arise.

        Every place that had a great team did it this way.

        • curun1r 2385 days ago
          Until someone goes on vacation, their area blows up and everyone else has to panic fix some code that they've never seen before.

          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.

          • Iv 2385 days ago
            You are right that this is something to consider. In my case the "realm" think was emergent and not enforced at all, but it was a bit implicit that if possible, you ask Bill his advice before rewriting a function of his model. The lead dev was still nosing around everywhere and had authority to call a piece of code defective and impose a rewrite.

            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.

          • humanrebar 2385 days ago
            There are infinite ways to organize teams so your concerns are addressed. For example, you can have primary, secondary, and backup developers for each component of the system. That keeps you bus factor down and makes it more clear what the progression of responsibility looks like.

            But, absolutely, a lack of peer review, authentic feedback, and general teamwork causes all sorts of issues in so many ways.

            • vog 2385 days ago
              > That keeps you bus factor down

              Small nitpick: I assume to wanted to say this keeps your bus factor up.

          • Clubber 2385 days ago
            I understand your concerns. That never became a crisis for us because of a few reasons. 1. An individual rarely deployed their stuff right before vacation (because of this reason). 2. We had an exhaustive QA process (full regression had to pass before deployment). 3. Everyone on the team was senior and could debug other people's code quickly and easily. 4. Other people's code wasn't crap (see #3). 5. Everyone was familiar as to what the other modules were doing.

            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).

          • Klockan 2385 days ago
            > As a manager, one of my main jobs is ensuring that the team's bus number is always above 1

            Bus number of 1 would be nice to experience for once, I have yet to see a team with a bus number above 0...

      • TeMPOraL 2385 days ago
        I believe so too, but it's not even that much a function of team structure. A proper design will have lots of places that are mostly self-contained at various levels of abstraction - more than people you have in your team. I believe work should be distributed among those boundaries, because it lets people agree on the interfaces and work mostly in isolation.

        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.

        • foota 2385 days ago
          Re: 0 sometimes I wish I could just be paid to read and understand code.
          • boomlinde 2385 days ago
            Are you being paid per written line of code or something? I just can't think of a reason to believe as a programmer that your job responsibilities don't include reading and understanding code.
            • foota 2385 days ago
              They definitely do, but there's so many other things, and they come with all sorts of distractions. (I love my job, don't get me wrong)
          • TeMPOraL 2385 days ago
            Unless one's in constant crunch mode, just hammering out whatever crap that makes tickets disappear, there's always time for that in programming. Often it's just jumping into a library method and looking around instead of opening a new browser tab and typing "how XYZ works stackoverflow".
      • humanrebar 2385 days ago
        > It also allows programmers, these very territorial beasts...

        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.

      • stormbeta 2385 days ago
        I refuse to work with people which such fragile egos, but I agree on the architecture.

        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.

      • WillReplyfFood 2385 days ago
        I laughed at ascii-string protocolls- then i realized how great self-explaining interfaces are.
      • vog 2385 days ago
        > There is a saying that any complex project will end up mimicking the communication structure of your organization. I must confess I thought it was silly until I realized it happened to us.

        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?

        • AndrewDucker 2385 days ago
          They aren't saying it's bad. They're saying it happens. And that you need to be aware of that if you want your code to end up maintainable.
          • vog 2385 days ago
            What does it mean to "be aware" of this? What should one do differently from one would otherwise do?
            • speedplane 2385 days ago
              It means that poor communication among team members will lead to poor code, and likely a poor or late product.
      • nradov 2385 days ago
        Project managers usually shouldn't define interfaces between code modules. That's a design lead or architect responsibility.
      • r3dk1ng 2385 days ago
        You're talking about Conway's law.
    • awj 2385 days ago
      Premature abstraction is generally worse than immature abstraction. Write the most straightforward thing you can, and wait for that feeling that it won't work out.

      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.

      • adrianratnapala 2385 days ago
        Indeed, it is concreteness that is the virtue and abstraction that is the necessary evil.

        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.

      • always_good 2385 days ago
      • misja111 2385 days ago
        This is so true. Even a horrible God class with 6500 lines of code is still many times better than an overdesigned framework with 100 classes of 65 lines each.
        • siliconunit 2385 days ago
          Totally agree, and as for ownership imho it all depends what level of complexity we are a taking about, if it's some web bs (no offense) it's one thing, if we talking about some parallel gpu FEM physics solver trust me there will be ownership and I think it's a good thing...
        • posterboy 2385 days ago
          hard to tell what you think would be the significant difference between horrible and overdesigned.
      • Ace17 2385 days ago
        I feel James Coplien's advice on the question is interesting: https://www.youtube.com/watch?v=KtHQGs3zFAM&t=500

        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.

      • dkural 2385 days ago
        YES, this 100 times.
    • staunch 2385 days ago
      "first you learn the value of abstraction, then you learn the cost of abstraction, then you're ready to engineer"

      https://mobile.twitter.com/KentBeck/status/25831623306839654...

      • justicezyx 2385 days ago
        "Any problem in computer science can be solved with another layer of indirection"
        • Anchor 2385 days ago
          Except for the problem of too many layers of indirection.
          • adwn 2385 days ago
            And for the problem of insufficient performance.
            • Rexxar 2385 days ago
              Cache are a level of indirection and they increase performance.
              • adwn 2385 days ago
                Some problems of insufficient performance can be solved by layers of indirection, but not all. The original quote quantifies over all problems:

                > "Any problem in computer science can be solved with another layer of indirection"

                Otherwise, good point – I did not think of this.

    • coltonv 2385 days ago
      Earlier today I wrote a ruby script to go through a JavaScript file, find all ocurrences where a method was written in a certain way, and convert it to a new format.

      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.

      • louithethrid 2385 days ago
        .. the next day, my boss called- and he had the exact same problem, so i used the script, so its a tool at our company now, and several collagues added to it.
      • makapuf 2385 days ago
        That's basically why I have a personal project. Low level C code, no operating system, no heap memory handling on embedded, no problem ! Also, almost no abstractions but "infinite" time spend on pointless micro optimizations tweaking assembly. That's a relief from daily work where I'm much more disciplined.
    • voltagex_ 2385 days ago
      Give yourself permission. I have a GitHub repo called "junkcode" for this very purpose - sometimes projects are promoted out of there, sometimes not.
    • CodeWriter23 2385 days ago
      Something I recently read helped me with this. The guy said “refactor often”. So I code the solution for the problem at hand and when something else touches it, and a refactor is necessary, I do it right then, schedule implications be damned. Early on it can be a hellish bit of regressions, but after a time, the refactors move from less disruptive to smooth. And I get two bonuses: technical debt stays low, and analysis paralysis is optional.

      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.

    • seanmcdirmid 2385 days ago
      It is often impossible to write code the first time anyways, just do it, realize your technical debt, and come back and refactor it when the better abstraction is more obvious (if any).
      • imron 2385 days ago
        Compression oriented programming - https://mollyrocket.com/casey/stream_0019.html
      • stevenwoo 2385 days ago
        Ah, but try that in an interview and see what happens.
        • seanmcdirmid 2385 days ago
          Interview coding skills are different from real world coding skills.
          • stevenwoo 2385 days ago
            Yes, sorry I was not clear. The OP was correct in stating that sometimes one just need to get started, but it's hilarious that what one does in the real world is not something that is valued in an interview where one is expected to come up with a solution and iterate on it to have it fully optimized in 45 minutes.
        • cabaalis 2385 days ago
          I'm no Google, but I would hire someone who follows that methodology.

          1. Make it work 2. Make it work fast 3. Make it work well

          In that order.

    • cel1ne 2385 days ago
      There's a way around that: First time, you do it "like a sketch", no criticism allowed. Then you can work over it. Every creative work that ever got finished was made like that ;).

      Better finish 80%, than miss 100%.

    • Gonzih 2385 days ago
      > no code was too verbose or horrible to stop me from progressing towards my goal

      Sounds like programming in go :)

      PS. It's a joke, I enjoy go myself.

    • zem 2385 days ago
      i keep posting this to hn, but it keeps being relevant: http://prog21.dadgum.com/21.html
    • wmccullough 2385 days ago
      I miss the rush
    • jackmott 2385 days ago
      watching the creator of The Witness do some live stream coding made me realize this too. he just typed the convenient thing he needed at each moment and didn't try to abstract away the mess. just forged ahead.
      • baby 2385 days ago
        Thinking of video game, I think this is a good analogy: a lot of what you write in the beginning are just tools to your own program.

        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.

        • jackmott 2385 days ago
          But you can go too far there. The Witness guy explained it like this: You need to do a breadth first search of your code. If you rabbit hole for weeks making the perfect level design tool before you have already made a working prototype of the game for example, you might then months later, as you build out the game, realize the level building tool you have made isn't really suitable.

          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.

      • DanielRibeiro 2385 days ago
        Oh yeah, Jonathan Blow's coding videos show an amazing exercise of pragmatism: https://www.youtube.com/user/jblow888/videos
    • b0rsuk 2385 days ago
      John Carmack's advice (I don't remember exactly):

      "If you don't know which way is better, do it both ways and compare."

      • mikenew 2385 days ago
        What if you're not sure which of 17 different ways is better?
        • TeMPOraL 2385 days ago
          Spend a few minutes thinking about the problem in order to reduce those 17 ways into ~3-5 ways, and then apply Carmack's advice.
    • 0xbear 2385 days ago
      By the time this happens you’ll be “overqualified” and “unlikely to be happy”, and therefore unemployable.
  • userbinator 2385 days ago
    Maybe the introductory text primed me to expect much worse, but I actually found the code quite readable although definitely underabstracted. I was expecting the opposite, the sort of code I usually see from beginning Java programmers: classes and methods everywhere, but almost no real work.

    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...

    • bendbro 2385 days ago
      I wholeheartedly agree.

      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

      • sytringy05 2385 days ago
        most stuff I look it is 95% boilerplate. At least this code does something :P

        @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...

    • c3534l 2385 days ago
      I love me some good abstractions. But abstractions don't automatically make code more readable or efficient. They're overhead that shows their worth through volume and use. I follow the rule that you never abstract based on one instance, or even two. Show me three places you know this will be used, then if we know how it's going to be used we can figure out the best way to generalize that functionality.
      • speedplane 2385 days ago
        The worst is when the abstraction is designed prematurely for some limited use case, and then when you want to expand on it, you're stuck in some rigid format and have to either hack at it or rebuild the entire abstraction.

        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.

  • twic 2385 days ago
    Reminds me of a rather insightful comment from a Hackernews a few years ago [1]:

    > 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.

    [1] https://news.ycombinator.com/item?id=7653762

    • egeozcan 2385 days ago
      I think that has a lot to do with the IDE as well. When I'm using Visual Studio, I autocomplete and peek until I find something that even remotely does what I need in the library and move on. I come back and optimize when I see smoke coming out of the CPU or my project manager :) (Of course I'm responsible with my code and this is an exaggeration but could this be called "too mature optimization"? :) )
      • giancarlostoro 2385 days ago
        I'm guilty of this, matter of fact I'm sure a good number of us (developers) are. Though lately I find myself looking up documentation aside so I can read through examples and find more information. Some languages / libraries are better documented than others, and sometimes Stack Overflow fills a niche. I noticed one library that was not afraid to document things recorded on Stack Overflow that they made into official documentation and made a reference back to Stack Overflow which I thought was perfect since you get the context behind that documentation, as well as it solved a real problem.
  • yathern 2386 days ago
    • bcbrown 2386 days ago
      • danbruc 2385 days ago
        That is probably (x + 1) % 10 assuming x is non-negative. That kind of code is responsible for quite a bit of the verbosity, the author was obviously not aware of many of the little tricks usually used in this kind of code.
        • raxod502 2385 days ago
          Original author here.

          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.)

        • baddox 2385 days ago
          Also assuming that x <= 9.
      • hacking_again 2385 days ago
        Well, it's faster than %, but I bet it's premature.
        • CydeWeys 2385 days ago
          Why do you say it's faster? It's guaranteed to fail branch prediction one out of ten times. My guess is that'd be a lot slower than using the integer modulo operator, which is not an expensive operation.
          • hacking_again 2385 days ago
            On their own, % and / are way slower than +, -, *, <<, >>. Cycle counts depend on your architecture, you can look them up. That mod is so slow and should be avoided is a kind of folklore based in truth - kind of like function calls being slow - but like everything time-sensitive the mistake lies in not profiling before (manual) optimization.

            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.

            • 35bge57dtjku 2385 days ago
              > On their own, % and / are way slower than +, -, *, <<, >>.

              And the branch instruction is free??

              • hacking_again 2385 days ago
                More or less, assuming you can predict it. But there's a penalty for misprediction. So it boils down to whether using % frequently (either as a native instruction or as a sequence of instructions) is more or less expensive than predicting a branch frequently, given a certain misprediction rate.
                • 35bge57dtjku 2384 days ago
                  > More or less, assuming you can predict it. But there's a penalty for misprediction.

                  Yeah, no, that's not free.

                  • hacking_again 2383 days ago
                    Ok, so what changes would you make to my explanations?
          • CUViper 2385 days ago
            At least in C++, GCC and Clang will both use a CMOVE: https://godbolt.org/g/W1GWyP
    • sparky_ 2386 days ago
      My favorite part is the overloaded print methods: https://github.com/raxod502/TerrariaClone/blob/master/src/Te...
      • js2 2385 days ago
        Maybe those are stubs the author intended to do something else with later?
        • raxod502 2385 days ago
          Original author here.

          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.

          • js2 2385 days ago
            In that case, I think you might have been happier in a language other than Java. :-)
          • userbinator 2385 days ago
            That's actually not such a bad idea, since you seem to have discovered one of the traits of good abstraction: it makes code more concise.
          • bitexploder 2385 days ago
            It always was rather onnerous.
          • taw55 2385 days ago
            It IS a great idea!
    • alexwebb2 2386 days ago
      I'm sure there was a good reason for that.
      • Nition 2385 days ago
        I'm not so sure. In the readme he says there are over 500 cases of "unnecessary boxing."
        • Agathos 2385 days ago
          Raise your hand if you were excited when you heard Java 1.5 would introduce autoboxing.
    • SuddsMcDuff 2385 days ago
      A textbook example of a quasi-class: http://www.idinews.com/quasiClass.pdf
  • avenoir 2385 days ago
    The best thing about this is the open issue claiming it's "Too much like the real Terraria source code." [1] :)

    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!

    [1] https://github.com/raxod502/TerrariaClone/issues/2

    [2] https://en.wikipedia.org/wiki/Battle_City_(video_game)

    • TeMPOraL 2385 days ago
      Holy shit.

      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...

      • sciolistse 2385 days ago
        You used to be able to decompile Terraria into perfectly readable code, since its c# and they didnt use an obfuscator. The code base was atrocious, but it is impressive that they got something working, and pretty fun, together as quickly as they did.

        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.

        • Kuraj 2385 days ago
          If I remember correctly, the author of Terraria was also just learning C# as he went on with this project.

          It's a huge success story in my book.

        • Too 2384 days ago
          I think Unity forces you into a pattern that you are not used to, this can easily get you out of your comfort zone resulting in very funny architecture before you get used to it.

          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.

        • rootw0rm 2385 days ago
          off the top of my head Rimworld comes to mind
      • taw55 2385 days ago
        Bloody Hell, that code “snippet” just keeps on giving. Makes me feel a bit better about that tightly coupled ball of mud I barfed out last week. Lol.
  • mcdirty 2385 days ago
    I did a 3 month contract working on porting Terraria (the actual game) from XNA to Unity and updating things like UI from sprite batching etc.

    Coincidentally and fwiw, the actual source code to Terraria was also a hellscape of spaghetti code.

    • photojosh 2385 days ago
      Ah, so you're the one to blame for the "loss" of hour upon hour of my kids' lives. It's pretty nice to see them sitting side by side on the couch, each with an iPad, muttering gibberish at each other. Warms this nerdy father's heart. :)
    • doesnt_know 2385 days ago
      > porting Terraria (the actual game) from XNA to Unity

      Can you talk about this? What was involved? Why do it? Major roadblocks? Do you feel it was it worth it?

      • MBCook 2385 days ago
        XNA is limited to MS platforms isn’t it? Is imagine it was so they could port/sell to iOS, PlayStation, Mac, etc.
        • doesnt_know 2385 days ago
          Monogame is practically a drop in replacement which has multi-platform support/targets. FNA is also effectively the same, with a slightly more "purist" approach.

          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.

      • 201709User 2385 days ago
        You can hire cheaper ready-made Unity devs afterwards. There is even a certification now.
  • beala 2386 days ago
    I think true spaghetti code requires teamwork. I mean that seriously. You need at least 3 people all with different incomplete and incorrect mental models trying to modify the same codebase at the same time.
    • eric_h 2385 days ago
      I disagree. I inherited an app that I'm maintaining that was written by one person over ~12 years. When requirements were added, he just cloned the app and started making the changes so the new app would meet the requirements. Repeat 2 more times, and you get to now, where there are 4 similar but not identical versions of the same code base, with inconsistently applied fixes to various bugs. All 4 still need to work for the organization to function.

      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).

      • harrisonjackson 2385 days ago
        I'd say one person over ~12 years is basically multiple developers working on it. I look back on code after a couple months and it often feels like someone else wrote it.
        • eric_h 2385 days ago
          Yep, and in particular, one person over 12 years with one to three month breaks between sessions of working on it. He had no choice but to "monkey see, monkey do" what his past self did, and the resultant product is ... difficult to maintain, to put it nicely.

          [Edit: I don't blame him - I understand how it happened, and also why he wanted to get out ;)]

        • zelos 2385 days ago
          git blame regret: "who wrote this crap?...oh, right, I did"
      • hinkley 2385 days ago
        One of the things it took me a while to intellectualize is that 'you' a year ago is a very different person from 'you' today.

        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.

        • eric_h 2385 days ago
          Absolutely. When I stumble upon some code in my full time codebase that I find distasteful, my first thought is "what idiot did this". git blame and sure enough, it's me.

          Past me has been and always will be an idiot as far as present me is concerned (with some infrequent exceptions).

          • moomin 2385 days ago
            If you like comic books where the hero has to travel in time to fight himself, you'll love programming.
            • pferde 2385 days ago
              I want this on a t-shirt.
          • Nition 2385 days ago
            I always think when this happens, "At least I must be improving."
      • iaw 2385 days ago
        My inherited spaghetti codebase took only 24 months for my predecessor to build. I was told: "don't worry, it's in SVN and all of the important switches are clearly laid out at the top."

        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.

        • quickben 2385 days ago
          Was the comment of that commit 'initial commit'? :)
          • iaw 2385 days ago
            Yes. It actually was LOL
          • koolba 2385 days ago
            Not GP but probably: “Here be dragons
            • taw55 2385 days ago
              I actually did that once.

              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.

              • quickben 2385 days ago
                > "The favicon was 20MB large"

                Well, that's actually impressive :D

      • eric_h 2385 days ago
        I should add that I volunteered to maintain this project, in exchange for free stuff from said organization (not money), before I knew what I was volunteering for (heh, lesson learned).

        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.

      • swivelmaster 2385 days ago
        I swear I know a guy who would have done this. I have worked with him. I have cleaned up his code. I have asked him to clean up his code and been yelled at in response.
        • eric_h 2385 days ago
          Pretty sure we all do. The constraints under which he was operating to create the mess I took over I understand well, and I do not blame him for the end result.

          He is a manager now, though, not a day-to-day programmer ;)

      • adrianratnapala 2385 days ago
        I think that's a perfectly good way to develop a bunch of somewhat-similar apps for different customers. As long as you refactor all the time.

        If you don't then you are basically one developer doing a serial simulation multiple developers miscommunicating in parallel.

      • ukyrgf 2385 days ago
        Your description is a 100% spot-on description of what I inherited a few weeks ago. I wake up every morning making groaning noises I never knew my body was capable of.
    • russellbeattie 2386 days ago
      I agree. But then again, I'm like a completely different programmer than I was a few years ago, and even more different than I was years before that. I've got some long running personal scripts and projects I tweak every so often, and the end result is pretty much the same. "What the hell was I doing here? Whatever... I'll just add a bit of code and get it working. Done."
      • davisdude 2386 days ago
        That describes my experience with some of my GitHub projects fairly accurately.

        Actual commit I did a few days ago:

        > Begin rewrite of rewrite of rewrite

        • worldsayshi 2385 days ago
          Yeah, that sort explains why it's so hard to get anywhere with vaguely defined free time projects.
          • davisdude 2385 days ago
            Yeah. The trouble is, I have a very clear idea of what I'm doing when I start it, but then I get busy and drop the project for weeks to months at a time, only to pick it back up again. Sometimes I remember exactly what was going on. Most of the time, though, I look at the code, think "This was done horribly! Why are there so few comments?" then proceed to do the exact same thing.

            It's a vicious cycle...

    • zokier 2386 days ago
      Instead of having everyone working at the same time, stretch out the team over longer time with some overlap. This ensures both the "broken telephone" effect and discourages any major improvements.
    • contravariant 2385 days ago
      Nah, just the one incomplete and incorrect mental model will do just fine.
  • indescions_2017 2386 days ago
    I'd actually try to recruit raxod502 at the high-school senior level. It certainly shows passion and commitment. You just need to grok the higher level abstractions. And may in the end even find your "spaghetti" version is actually more performant at run time ;)

    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!

    • apo 2386 days ago
      Writing code in spare time, not to mention 11,000 lines of it, already sets any high schooler (or any beginning programmer) apart from the majority of peers. It's shocking how little students in "AP" computer science courses actually end up doing, and how few do anything outside of class.

      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.

      • criley2 2386 days ago
        I had a rather unique AP Computer Science high school experience a number of years ago.

        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.

        • johnvonneumann 2385 days ago
          Comments like this kill me a little on the inside, I can't stand having real work devalued for the sake of contrived assessment criteria.
          • jackmott 2385 days ago
            well the AP comp sci test stuff is not all contrived. it is also useful to know (mostly)
        • cl0ne 2385 days ago
          I had a similar experience in high school. I took a "Technology" elective class where most people were just playing Warcraft III because the teacher didn't really care what we did. I don't remember him actually teaching us anything.

          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 :)

      • moomin 2385 days ago
        When I was 12 (and computers weren't really a thing) I wrote an RPG. In ZX Spectrum Basic. It wasn't great (let's be honest, TerrariaClone sounds like the Mona Lisa in comparison), but it worked. I didn't realise at the time that this weird little hobby of mine would stick me right at the front of an emerging field. Nor did my family who thought I should be doing.. almost anything else. I got ridiculously lucky, all because I started writing bad computer games in high school.
      • lubujackson 2385 days ago
        It's particularly encouraging to see it posted with mistakes. Sure, it's a bit of a joke, but it's also an experience to learn and grow from. Reflecting on past projects is so rare that I think it might be the best indicator of a programmer who will continue to improve.
    • jackmott 2386 days ago
      I did pong in rust to learn some rust, and it got me thinking how, doing pong was really easy (as an experience programmer) but if you wanted to do pong "properly", say supporting 4 different platforms, 5 languages, proper settings menu and high score table, supporting all manner of screen resolutions, full screen and windowed, sound, all popular controllers (keyboard, mouse, mobile input, game pads, joysticks) etc etc etc

      then even pong is pretty hard.

      • mikestew 2385 days ago
        I've often said that a team couldn't ship a production-ready version of Tic-Tac-Toe in less than a month...even if the implementation were already written.
    • azr79 2386 days ago
      > And may in the end even find your "spaghetti" version is actually more performant at run time

      not with those O(N^2) loops it ain't

  • danbruc 2386 days ago
    That actually doesn't look too bad to me. Sure, it's verbose, repetitive, and deeply nested, but just from skimming it, it looks quite comprehensible. Load all the data from files instead of filling huge arrays and maps in code, abstract similar code into methods, tame the usual mess when dealing with grids with some helper functions taking care of clamping or wrapping around coordinates, replace all the parallel arrays with structures, and you should be able to have some reasonable good code in no time. Might be a nice exercise in refactoring.
    • yathern 2386 days ago
      Truthfully - I wouldn't call it spaghetti code. I think of spaghetti code as way to many abstractions (AbstractEntityFactoryFactory). This code has the opposite problem - needing more abstractions - which is the easier direction to move.
      • flatline 2386 days ago
        Global state causes code to be spaghettified. Having worked on several code bases that qualify as spaghetti code, the hallmark trait is that the execution flow is wound back around itself many times, like noodles in a bowl of spaghetti, in a way that's not easy to trace. You may have nice abstractions or none. You may have deeply nested type hierarchies or a seemingly nice flat structure. You may be using an IoC container with neatly separated services. None of it matters, you can get spaghetti code with all of them.

        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.

        • MBCook 2385 days ago
          That’s sort of what I thought of. Is soon as I read a bit about having global variables at the top of every file I am mediately remembered how I used to program BASIC when I was first trying to learn it.
      • jdmichal 2386 days ago
        > I think of spaghetti code as way to many abstractions...

        That's usually termed lasagna code. Lots of layers with a little bit of filling in between.

        https://en.wikipedia.org/wiki/Spaghetti_code#Lasagna_code

      • watwut 2386 days ago
        Spaghetti code is when procedural/functional coding goes wrong which is pretty much opposite of too much abstaction. Basically, spaghetti is what was before OOP when it went bad. At least, I did not heard people to refer to too much abstraction as spaghetti before.

        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.

      • grtrans 2386 days ago
        I dunno, i would call spaghetti code code with waaaay too many entangled concerns, for which this and global state definitely qualifies.

        Personally i associate it with lack of abstractions, or extremely leaky abstractions.

      • marzipan 2385 days ago
        Spaghetti code by its original conception, code that uses GOTO to jump all over the program willy-nilly, mostly died with the adoption of procedural languages that eliminate or mitigate the usage of GOTO, forcing naive procedural style into something more reminiscent of straight-line code(which is generally a good practice, but still easy to deviate from with nested loops, function calls, state machines, etc.). But the general idea of "pasta code" that is hard to follow is going to stick around by any name.
      • fleitz 2386 days ago
        Yeah, I call the abstract code problems astronaut code, or more generally J2EE best practice code.

        To me this perfectly fits spaghetti code.

        https://www.joelonsoftware.com/2001/04/21/dont-let-architect...

  • Scaevolus 2386 days ago
    The real Terraria code isn't much better. Here's their 3MB [decompiled] NPC.cs: https://raw.githubusercontent.com/csnxs/Terraria/67de21a27e1...

    They had serious problems implementing multiplayer because they had to synchronize objects with 50KB of state every frame.

    • maxton 2386 days ago
      Important to note is that this code is not the source code, but rather was generated by dotPeek, a C# decompiler, as mentioned in the repo's README: https://github.com/csnxs/Terraria/
      • Scaevolus 2386 days ago
        Variable names and comments are lost, but the overall control flow structure of decompiled Java and C# code closely matches the original.
        • danbruc 2386 days ago
          Even variable names are usually not lost.
        • TeMPOraL 2385 days ago
          Still - does that decompilation roll back any kind of array unrolling C# compiler may be doing (assuming it's doing it)? If not, it could explain those long chains of if/else seen in the decompilation. Maybe they're arrays of constants in the real code?
    • kbenson 2386 days ago
      From the first couple hundred lines, they obviously know how to use a switch statement (as in how it works at least), but the odd cascade of if statements at the bottom makes me question whether they know when to use a switch statement (but then again, the stuff a the top makes me wonder that a bit as well).

      Edit: As someone else noted, if this is a generated file, that might explain a lot of this.

    • warent 2386 days ago
      I just scrolled to the bottom and all I see is } } } } } } } } } } } } } } } } } } } } } } } } } } } } } }

      What the fuck

      • mikeash 2386 days ago
        This is decompiled code, not the original source, so much/most/all of the craziness probably comes from that.
        • danbruc 2386 days ago
          Decompiling .NET or Java binaries usually yields code very close if not identical to the original source code, at least unless an obfuscator was used but that seems not to be the case here. Chances are very good the original source code looks almost exactly like that code, maybe with some additional comments.
          • thefifthsetpin 2386 days ago
            In this case, it's just that the decompiler didn't think of "else if" as a single control flow construct/keyword in the way that the original programmers did.

            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{
                  }
                }
              }
            • danbruc 2385 days ago
              I will try this tomorrow, I am pretty sure dotPeek can recognize and output else if. Might be a coding style option though.
              • mikeash 2385 days ago
                Wouldn’t “else if {“ and “else { if” compile to identical bytecode?
                • ufo 2385 days ago
                  Sure, but the decompiler can choose to always decompile to "else if {", which is more readable and more likely to match the original source code.
                  • mikeash 2385 days ago
                    That's my point. The compiler's choice of "else if {" or "else { if" is unrelated to the programmer's choice.
                • danbruc 2385 days ago
                  It does and at least the current dotPeek 2017.2.2 decompiles it to else if and does, other than I thought, not allow to customize it.
                  • mikeash 2385 days ago
                    Obviously whatever decompiler was used here decided to do it the other way.
          • amyjess 2386 days ago
            Mind you, a lot of Java 5 and later features like generics, switch on Strings, Iterable-based for, etc., are syntactic sugar implemented in the compiler, not part of Java bytecode, so those features don't decompile well.
            • danbruc 2385 days ago
              I am not sure about Java decompilers, but the .NET decompilers I have used all perform pattern matching in order to detect and reverse language features implemented with compiler transformations.
              • amyjess 2385 days ago
                At least the last time I used it (2015), IntelliJ's decompiler didn't.
    • jcl 2386 days ago
      Per the description on https://github.com/csnxs/Terraria/ , this isn't the Terraria source code -- it's a decompilation of the binary.
    • kevindqc 2386 days ago
      Those SetDefaults methods.. ouch.

      On the plus side, it's fun to press the page down and see the code 'animate' from left to right

      • k__ 2386 days ago
        yes, also that it comes back to the left after it hit the right end lol
    • XR0CSWV3h3kZWg 2386 days ago
      This looks as if this was a compile target, not the source code.

      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.

      https://github.com/CleverRaven/Cataclysm-DDA

      • TeMPOraL 2385 days ago
        It was, or still is? Also, are you still working on it?

        I'm currently having lots and lots of fun playing this game (experimental builds). It's pretty much halfway there to Dwarf Fortress...

        • XR0CSWV3h3kZWg 2385 days ago
          I stopped many years ago. I was working on it in between sending out job applications, I was happy to gain experience working on a code base larger than I felt comfortable reading and one that is ugly but a rewrite is not an option.

          I didn't add too many features, I was mostly reducing the amount of compiler noise and fixing any bugs I ran across.

    • monsieurbanana 2386 days ago
      Surely this file can't be edited by humans as is, right?
    • MrMember 2386 days ago
      Wow, I just glanced at the how they're generating random names and it's incomprehensible. What a bizarre way to do something rather simple.
      • mattchamb 2386 days ago
        My guess is they are using partial classes and generating a bunch of the code from other, much simpler files.
    • taw55 2385 days ago
      Oh wow. That might explain a lot of my lag I’ve had when multiplaying on large maps (on LAN).
    • saltedmd5 2385 days ago
      This gave me palpitations and then killed my browser.
  • ddevault 2385 days ago
    I have an implementation of Minecraft I'm pretty proud of: https://truecraft.io

    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.

    • Posibyte 2385 days ago
      So I see you everywhere on HN. You usually have the not-so-consensus opinion that I usually agree with. First off, so we have a baseline. I never thought to check your profile and look for projects or blogs or anything.

      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 :)

      • Sir_Cmpwn 2385 days ago
        Thanks for the kind words :)
  • writeslowly 2386 days ago
    This reminds me of the C# source code for DRAGON. Its code was actually much worse, because the creator wasn't aware of things like loops or method definitions (the main game loop and class appear to have been generated by a framework).

    The C# code is here, and it works well enough that you can buy it on Steam, apparently: https://gist.githubusercontent.com/alessonforposterity/832da...

    • dividuum 2385 days ago
      I'm a bit reminded of the central GAME.C file from the original Duke3D source code: https://github.com/videogamepreservation/dukenukem3d/blob/ma...

      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 :-)

    • serhei 2385 days ago
      The ability to buy something on Steam is sadly no longer a guarantee that it works.
      • jackmott 2385 days ago
        I played it. it worked.
  • S_A_P 2385 days ago
    As Ive gotten older, I have severely relaxed my dogma on coding standards. I agree that code should be maintainable, legible and logically formed. Sometimes though, you just need to get things done, and architecting a large solution of abstractions and frameworks, just doesn't seem like a good use of time.
    • hinkley 2385 days ago
      For me it feels more like a zero sum game.

      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.

  • XR0CSWV3h3kZWg 2386 days ago
    And here is someone that is trying to rewrite it in scala:

    https://github.com/BusyByte/TerraFrame/tree/convert-to-scala

  • 1001101 2386 days ago
    I had to see for myself. Yep, that's bad. What's not bad is the author's attitude about learning and improving. It also looks like this was a stop on the way to Harvey Mudd CS. [1] So, a happy ending, perhaps.

    [1] https://github.com/raxod502

    • iaw 2385 days ago
      With one exception I've never looked back at code I've written and thought "well that's well designed."

      Typically every few months I've improved enough to notice the quality difference.

  • vilius 2385 days ago
    Not sure if this is a common story for most programmers or maybe me and the author have same personality traits. Back in the Delphi 6 days I was 16, with no internet access I started learning about programming. It all began by reading an article of how to write assembly code in Delphi. Had no idea what it meant, but it was interesting. So I've started.

    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 :-)

  • fancyPantsZero 2386 days ago
    This makes me sad. Not because of the code quality, but because it makes me think of all the games I used to write back in middle school that are now lost to the swirling sands of time. The youngins don't know how good they have it with github!
    • sgs1370 2385 days ago
      Your comment reminded me of a game (maybe the only one) I wrote in middle school, on a TRS-80 Color Computer (I think 4K, although maybe I had the 16K upgrade by the time I wrote the game). I wrote it in basic & saved it on some cassette tape... random blocks of one color on the screen, and you are a block that starts at the bottom and you use arrow keys to avoid the blocks as you are thrust upward. (I guess it was basic in more ways than one). I might have added a 3rd color block that gave you points if you hit those.

      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...)

    • speedplane 2385 days ago
      Missing out on the nostalgia definitely is a loss. But re-reading that old code, or worse, putting it on github for all to see makes me cringe.
  • tgb 2385 days ago
    When I first started programming (this was in C++), I decided that the obvious optimisation was to declare all these redundant local indices i,j,k as globals. Then the program won't need to make all this redundant crap! Of course that led to absurdly subtle bugs that only occasionally showed up since whenever I called a function which had a loop in it from inside of another loop, I would use i as the index for both loops. Error! I learned several important lessons when I figured that one out.

    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?

    • raxod502 2385 days ago
      Original author here.

      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

    • MetallicCloud 2385 days ago
      I'm sure it would have lead to problems, that's just one of the examples of beginner mistakes with the code. That's kind of the point of this post, for the author to poke fun at themselves for the number of newbie mistakes they made.
  • zokier 2386 days ago
    > The TerrariaClone.init() method, which is over 1,300 lines long, actually grew so large that the Java compiler started running out of memory trying to compile it!

    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.

    • jcl 2385 days ago
      Given the relative size of the function and typical memory, I suspect that the issue the author ran into was actually the JVM's 64KB limit on the bytecode size of a compiled function.

      https://stackoverflow.com/questions/17422480/maximum-size-of...

    • tigershark 2386 days ago
      In one of my previous jobs there was ClassSomething1, ClassSomething2 until 5 just because java can't have more than 65535 methods in a class..
    • ecshafer 2386 days ago
      Not having looked at the code, my guess would be what the 1k+ loc of method is doing. If it's mainly a bunch or if elsea or a switch statement that jumps to another function, which is what most gross long Enterprise code is, I imagine it's fine. But if you have 1k loc that is procedurally creating objects and doing a lot that depends on previous operations then I could see starting to run out of memory. We also don't know how much memory they had, most Java code for Enterprise is running on pretty big servers or workstations.
  • mwexler 2385 days ago
    The ability and willingness to slag your own defective work is rare, especially in public. Compliments to the dev, who recognized how much he's changed and was able to point out flaws with no holds barred and some humour.
  • chris_wot 2386 days ago
    The Terraria clone is apparently very much like the original:

    https://github.com/raxod502/TerrariaClone/issues/2

  • mickronome 2385 days ago
    Done 15 years as a consultant, and that code looked much better than some of the code I've worked with. Even right now I work with code that looks worse in many aspects, although in a slightly different way. The code of the game is very obviously written by someone which at the time had much more passion than knowledge, but who tried his/her best anyway. It's a lot easier to deal with that, than with 3000 line methods of complete and utter madness written by people who really should know better, people who actually get paid.
  • aryehof 2385 days ago
    I think this is a good example of what has become standard thinking for much of general programming. That the way to write a complex application is an "agile" approach of hack it 'till it works. The result too often is that slowly over time, the result increasingly approaches being a big ball of mud as seen here.

    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.

  • tbodt 2386 days ago
    A perfect example of "it's so bad it's good."
  • hinkley 2385 days ago
    I would love if we could get together as a community, take a project like this, and use it as an example for what a little refactoring can do.

    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.

  • kevan 2386 days ago
    It's beautiful. I have a sudoku solver that's almost as bad (but not as impressive as yours) written in Scheme when I was first learning how to code. It's good to look back on your past work every once in a while and see how far you've come.
  • arianvanp 2385 days ago
    This reminds me of the original RuneScape codebase. It's a 16k line God class, with some utility classes for networking and graphics. Decompiled code floats around on the web under the name "runescape 317 deob" if you want to check it out.

    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...

  • stuaxo 2386 days ago
    I've seen way worse code than this in my time, some in the last year.
  • yellowapple 2385 days ago
    Reminds me when I first stumbled upon a book on BASIC at my elementary school library, then got ambitious and tried to write my own Galaxian-ish game. Started with a whole screen with all the enemies and stuff, prompted for an input, and started trying to map out every single possibility.

    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).

  • beager 2386 days ago
    I did the same trying to write a Minecraft clone back in 2012: https://github.com/beager/craftalike

    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.

    • k__ 2386 days ago
      I did one too.

      We basically gave up after the networking stuff grew over our heads.

  • jason_slack 2385 days ago
    The fact you took the time to follow your idea is great. Kudos.

    Also, the fact you "think" your code is spaghetti shows you have grown as a developer. Kudos.

    Love the part about codeToLarge()

  • DubiousPusher 2386 days ago
    A little more egregious than usual but some of this is not that far from code I've seen in multiple AAA games. Some of which you've probably played.
  • partycoder 2385 days ago
    I have seen way worse. At least this code is indented, it executes, etc.

    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.

  • BearOso 2385 days ago
    This isn’t too bad. Check out the source code for qb64, it’s hilarious:

    https://github.com/Galleondragon/qb64/blob/master/internal/c...

  • flavio81 2386 days ago
    Beauty. I see beauty. I see God in one 6000-line class (TerrariaClone.java), overflowing with constant data / tables embedded in the code.

    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

  • zackify 2385 days ago
    Looks just like the Freepbx codebase, but that's php https://github.com/FreePBX/core/blob/release/13.0/Core.class...
  • danschumann 2385 days ago
    When technical debt gets so large that you go bankrupt ( quit the project ). I did this with an actionscript game. Then an html editor. I did not know what I was doing. I looked back at the code and decided that starting from scratch would be much faster than refactoring what existed there.
  • smithkl42 2385 days ago
    I'd hire in a second anybody who's thought this hard about how to critique their own code.
  • keithpeter 2385 days ago
    http://sohcahtoa.org.uk/kepler/tmoon.c

    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.

    • Retr0spectrum 2385 days ago
      Wow, that indentation...
      • keithpeter 2385 days ago
        Yup. Was written about 20 years ago. I'm an amateur.
  • gigatexal 2385 days ago
    Props to you man for making a game clone as a way to learn: even if it sucks that’s more than I’ve done to date (making useful utilities in python isn’t as cool as a game). I think it’s good to ever remember the past and learn from it so that you don’t repeat it.
  • codingdave 2385 days ago
    Normally when I hear people disparage their early attempts at code, I think to myself, "Oh, come on... how bad can it be?" Well, this is bad. Really, really bad.

    On the other hand, there was nowhere to go from here but up. Gotta start somewhere, right?

  • andrewstuart 2385 days ago
    I like that people have the courage to start the process of learning and improving.
  • imron 2385 days ago
    I remember when I first started programming, and I couldn't figure out the obscure error message preventing the Turbo Pascal game I was making from compiling.

    Turned out having over 65k of global variables was too much :-D

  • BlakeCam 2385 days ago
    I wonder how hard it would be to write a program to automatically refactor code like this into something reasonably clean. My intuition thinks it should be difficult but possible... and extremely useful.
  • amatecha 2385 days ago
    I can barely even read the README.md ... too scary. This is perfectly in time for Halloween season! :'D
  • nuclx 2385 days ago
    The code doesn't look much worse than some of the production code bases I encountered.
  • smrtinsert 2385 days ago
    6560 loc in TerrariaClone.java. Closed tab, will never look again.
    • hinkley 2385 days ago
      A lot of that file is data.

      Some of it is just plain data (arrays), a lot of the rest is a bunch of setters one after another.

  • azr79 2386 days ago
    O(N^2)is hell of a drug
  • kdazzle 2385 days ago
    You are so brave
  • Zekio 2386 days ago
    I forgot this existed, high quality code right there
  • d--b 2385 days ago

                        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;
                                    }
                                }
                            }
                        }
  • louithethrid 2385 days ago
    Open the Git Repository. Eyes glaze over. Just like the Robotsourcecode, you get to see every day, if you work in automation. Close the Git Repository.

    Dear Author, at least you know while and for.. it can be worser.