good question- for the “engine” aspect of the code, I was keeping performance characteristics in mind through my choice of languages, and there were a few false starts along the way. (i built this entire game once in JS and once in lua in the past)

for the “logic” code in species.rs that defines how elements behave, i felt able to do whatever I wanted, including lots of branching, some higher order functions, abstractions, casting type of numbers, etc. (but, definitely very little heap allocation). This is notable because language expressiveness here indirectly impacts how fun the game is, but this code is also super hot and runs thousands of times per frame.

an interesting anecdote here is that I unwittingly wrote most of the game with my rustc optimization strategy on “z”, optimize for binary size. once the project was already quite developed I realized this and switched it to o3 which things like inlining and gave me a big performance boost, where i had been being frugal!

The texture types they support (the fluid sim is in floats, but on phone browsers I could only take data in or out of the shaders via unsigned byte textures, required some munging)

There’s also a maximum # of bound texture units of 8, and I had to plug a lot of gaps in my knowledge of how OpenGL works in order to correctly bind textures for each program and stay under that limit.

all of this was made more complicated by the fact my only phone is an iphone and I don’t own a macbook. Apple only allows you to connect to the safari devtools from a mac >:’( So i was debugging somewhat blind.

Apple requires developers to both own a mac to build and also pay them a yearly fee to be able to offer even free apps on their app store. This kinda sucks, but on the other hand the hardware + macOS is okay.

I’m using firefox 63 on arch linux. Here’s a screenshot of what I’m observing. Actually, from experimenting with chrome, it seems like almost everything is going in the wrong direction. Fire floats downward, “gases” float up, and ice falls instead of staying put.

I’m sorry that it doesn’t work, you may have better luck on a smartphone.
WebGL has a huge surface area of browser and platform specific implementation details, and I don’t think I could hunt down the issue unless I could reproduce your issue locally. (FWIW, firefox 60 on ubuntu works for me)

I followed this tutorial to get started on my falling sand game project*.
It’s a concise introduction to some really useful tools - using this ecosystem has been a total joy and has enabled me to build things in the browser with incredible performance, without sacrificing the web niceties I’m used to like quick feedback cycles and performance tracing via devtools.
The browser support is also really strong, my game (mostly, WIP!) works on mobile and most browsers (I think)
Highly recommend this book!

Holy crap. That game is awesome. The way the different elements interact so intuitively is just incredible. I was playing around with destroying things with acid, but then I realized half my screen was acid and it was fun trying to get rid of it. I love how gas and lava interact, and also how ice will cause surrounding water to freeze. And also, putting a bit of lava under some wood and then using wind on the wood actually scatters the embers of the wood. Wow.

thank you so much!
falling sand games were a part of my childhood, I love their mode of play through experiment-building.

My eventual goal is to allow the user to program, fork, and share new elements of their own design, and mix them. Defining an element right now has an intentionally simple cellular automata api surface, and I hope to eventually figure out how to compile and link wasm modules in the browser to allow hundreds of elements, so you can try out usernameFoo’s “Alien Plant v4” against usernameBar’s “pink super acid”

I’ll need to understand the wasm toolchain a lot better to make that happen though

Thank you! This is a bit silly considering that I posted this on a public forum, but my one request is to please not share the game more broadly yet, I have a lot of things I still want to implement before I show it to people outside the context of it being a tech demo. Posted it here because I appreciate this learning resource so much!

People who’re participating, what languages are you using? I’m starting to learn Typescript, so I’m thinking of using that for practical reasons, though I’d probably rather do OCaml or something a bit more esoteric.

Last year I used 6 languages, and this year my goal is to use 12!
Carp, Fennel, and Reason are some new-to-me languages I hope to touch on.
I will likely do most of the problems in clojure because I enjoy manipulating data-structures in it so much, but rarely feel like it’s the practical choice for my projects.

As much as I am tempted to try ReasonML, I wrote a modest amount of Elixir back in 1.2 (three years ago, and stable is now 1.7), and have an upcoming need for it again. Will probably do that to brush up on any changes.

In an attempt to make it challenging is I am going to try and pick up Emacs while doing so. I have heard that the lineage inherited from Erlang provides a decent ecosystem in Emacs for other BEAM languages. Does anyone know if that perception is correct?

I think this year I’ll forego going for leaderboard, and use the opportunity to brush up on my Elixir skills. I haven’t had a good chance to touch it for quite a while, so it should be a good refresher. I really enjoy thinking in and solving problems with the toolset available in Elixir.

I’d second this. Maybe also devcards. But this setup makes it really easy to write some code, save and see the changes right away as it re-renders. Even if your desired target isn’t the web, the same Quil code should then work in eg. OpenGL as well.

I found myself in this position a lot at work, and wrote a post about to be useful when you’re in the junior developer tasked with reviewing code from people who know the system better than you do - because it can be intimidating and difficult!!

map and filter capture common operations in a really solid way that is almost always an advantage over a loop.

In my experience, the bar is a lot higher when considering rewriting loops into reduces. A reduce isn’t necessarily much more opinionated or explicit than a loop, and so you need to be careful to ensure that you’re choosing it over a loop for the right reasons.

If your reducer body is longer than a single statement, or your output data structure is more complicated than a single literal, you might not be gaining much by using reduce.

Thank you for mentioning Redash. Actually Redash’s features extend beyond QueryClips, as it allows to visualize the data, create dashboards, alerts and more.

@dpaola2 on the website you mentioned that you created QueryClips after being frustrated with the lack of simple, easy-to-use tools. I created Redash for the same reasons ;-) I just wonder, did you have the chance to evaluate Redash before creating QueryClips? :-)

I used to do the things listed in this article, but very recently I’ve changed my mind.

The answer to reviewing code you don’t understand is you say “I don’t understand this” and you send it back until the author makes you understand in the code.

I’ve experienced too much pain from essentially rubber-stamping with a “I don’t understand this. I guess you know what you’re doing.” And then again. And again. And then I have to go and maintain that code and, guess what, I don’t understand it. I can’t fix it. I either have to have the original author help me, or I have to throw it out. This is not how a software engineering team can work in the long-term.

More succinctly: any software engineering team is upper-bound architecturally by the single strongest team member (you only need one person to get the design right) and upper-bound code-wise by the single weakest/least experience team member. If you can’t understand the code now, you can bet dollars to donuts that any new team member or new hire isn’t going to either (the whole team must be able to read the code because you don’t know what the team churn is going to be). And that’s poison to your development velocity. The big mistake people make in code review is to think the team is bound by the strongest team member code-wise too and defer to their experience, rather than digging in their heels and say “I don’t understand this.”

The solution to “I don’t understand this” is plain old code health. More functions with better names. More tests. Smaller diffs to review. Comments about the edge cases and gotchas that are being worked around but you wouldn’t know about. Not thinking that the code review is the place to convince the reviewer to accept the commit because no-one will ever go back to the review if they don’t understand the code as an artifact that stands by itself. If you don’t understand it as a reviewer in less than 5 minutes, you punt it back and say “You gotta do this better.” And that’s hard. It’s a hard thing to say. I’m beginning to come into conflict about it with other team members who are used to getting their ungrokkable code rubber stamped.

But code that isn’t understandable is a failure of the author, not the reviewer.

More succinctly: any software engineering team is upper-bound architecturally by the single strongest team member (you only need one person to get the design right) and upper-bound code-wise by the single weakest/least experience team member.

Well put – hearing you type that out loud makes it incredibly apparent.

Anywhoo, I think your conclusion isn’t unreasonable (sometimes you gotta be the jerk) but the real problem is upstream. It’s a huge waste when bad code makes it all the way to review and then and then needs to be written again; much better would be to head it off at the pass. Pairing up the weaker / more junior software engineers with the more experienced works well, but is easier said than done.

hmm, you make a good point and I don’t disagree. Do you think the mandate on the author to write understandable code becomes weaker when the confusing part is the domain, and not the code itself? (Although I do acknowledge that expressive, well-structured and well-commented code should strive to bring complicated aspects of the problem domain into the picture, and not leave it up to assumed understanding.)

I think your point is very much applicable. Sometimes it takes a very long time to fully understand the domain, and until you do, the code will suffer. But you have competing interests. For example, at some point, you need to ship something.

Do you think the mandate on the author to write understandable code becomes weaker when the confusing part is the domain, and not the code itself?

That’s a good question.

In the very day-to-day, I don’t personally find that code reviews have a problem from the domain level. Usually I would expect/hope that there’s a design doc, or package doc, or something, that explains things. I don’t think we should expect software engineers to know how a carburetor works in order to create models for a car company, the onus is on the car company to provide the means to find out how the carburetor works.

I think it gets much tricker when the domain is actually computer science based, as we kind of just all resolved that there are people that know how networks work and they write networking code, and there’s people who know how kernels work and they write kernel code etc etc. We don’t take the time to do the training and assume if someone wants to know about it, they’ll learn themselves. But in that instance, I would hope the reviewer is also a domain expert, but on small teams that probably isn’t viable.

And like @burntsushi said, you gotta ship sometimes and trust people. But I think the pressure eases as the company grows.

That makes sense. I think you’ve surfaced an assumption baked into the article which I wasn’t aware of, having only worked at small companies with lots of surface area. But I see how it comes across as particularly troublesome advice outside of that context

How do you resolve those conflicts? In my experience, everyone who opens a PR review finds their code to be obvious and self-documenting. It’s not uncommon to meet developers lacking the self-awareness required to improve their code along the lines of your objections. For those developers, I usually focus on quantifiable metrics like “it doesn’t break anything”, “it’s performant”, and “it does what it’s meant to do”. Submitting feedback about code quality often seems to regress to a debate over first principles. The result is that you burn social capital with the entire team, especially when working on teams without a junior-senior hierarchy, where no one is a clear authority.

Not well. I don’t have a good answer for you. If someone knows, tell me how. If I knew how to simply resolve the conflicts I would. My hope is that after a while the entire team begins to internalize writing for the lowest common denominator, and it just happens and/or the team backs up the reviewer when there is further conflict.

t’s not uncommon to meet developers lacking the self-awareness required to improve their code along the lines of your objections. For those developers, I usually focus on quantifiable metrics like “it doesn’t break anything”, “it’s performant”, and “it does what it’s meant to do”. Submitting feedback about code quality often seems to regress to a debate over first principles.

Require sign-off from at least one other developer before they can merge, and don’t budge on it – readability and understandability are the most important issues. In 5 years people will give precisely no shits that it ran fast 5 years ago, and 100% care that the code can be read and modified by usually completely different authors to meet changing business needs. It requires a culture shift. You may well need to remove intransigent developers to establish a healthier culture.

The result is that you burn social capital with the entire team, especially when working on teams without a junior-senior hierarchy, where no one is a clear authority.

This is a bit beyond the topic at hand, but I’ve never had a good experience in that kind of environment. If the buck doesn’t stop somewhere, you end up burning a lot of time arguing and the end result is often very muddled code. Even if it’s completely arbitrary, for a given project somebody should have a final say.

The result is that you burn social capital with the entire team, especially when working on teams without a junior-senior hierarchy, where no one is a clear authority.

This is a bit beyond the topic at hand, but I’ve never had a good experience in that kind of environment. If the buck doesn’t stop somewhere, you end up burning a lot of time arguing and the end result is often very muddled code. Even if it’s completely arbitrary, for a given project somebody should have a final say.

I’m not sure.

At very least, when no agreement is found, the authorities should document very carefully and clearly why they did take a certain decision.
When this happens everything goes smooth.

In a few cases, I saw a really seasoned authority to change his mind while writing down this kind of document, and finally to choose the most junior dev proposal.
And I’ve also seen a younger authority faking a LARGE project just because he took any objection as a personal attack. When the doom came (with literally hundreds of thousands euros wasted) he kindly left the company.

Also I’ve seen a team of 5 people working very well for a few years together despite daily debates.
All the debates were respectful and technically rooted. I was junior back then, but my opinions were treated on pars with more senior colleagues. And we were always looking for syntheses, not compromises.

I agree with the sentiment to an extent, but there’s something to be said for learning a language or domain’s idioms, and honestly some things just aren’t obvious at first sight.

There’s “ungrokkable” code as you put it (god knows i’ve written my share of that) but there’s also code you don’t understand because you have had less exposure to certain idioms, so at first glance it is ungrokkable, until it no longer is.

If the reviewer doesn’t know how to map over an array, no amount of them telling me they doesn’t understand will make me push to a new array inside a for-loop. I would rather spend the time sitting down with people and trying to level everyone up.

To give a concrete personal example, there are still plenty of usages of spreading and de-structuring in JavaScript that trip me up when i read them quickly. But i’ll build up a tolerance to it, and soon they won’t.

I ended up writing a ClojureScript micro-framework for Node called Macchiato. I primarily work with Clojure, and I found a few cases where the JVM is not the best fit. The two main limitations being relatively high memory requirements and startup time. This makes the JVM a poor fit for things like AWS Lambda. I had a use case for making some lightweight services at work, and wanted to learn a bit about the Node ecosystem, so this was the result.