What I Learned Coding X-Wing vs. TIE Fighter: Peter Lincroft
What I Learned Coding X-Wing vs. TIE Fighter: Peter Lincroft
What I Learned Coding X-Wing vs. TIE Fighter: Peter Lincroft
Curator
Lim Cheng Soon
Contributors
Fejes Jozsef
Peter Lincroft
Steli Efti
Bobby Grace
Michael Bromley
Alvaro Castro-Castilla
James Greig
Proofreaders
Advertising
Published by
Netizens Media
46, Taylor Road,
11600 Penang,
Malaysia.
Emily Griffin
Sigmarie Soto
Contact
Illustrator
Thong Le
Ebook Conversion
Ashish Kumar Jha
Printer
MagCloud
Hacker Monthly is published by Netizens Media and not affiliated with Y Combinator in any way.
Contents
FEATURES
Jozsef
Lincroft
STARTUPS
18
By Steli Efti
PROGRAMMING
20
By Bobby Grace
24
By Michael Bromley
28
By lvaro Castro-Castilla
SPECIAL
38
By James Greig
FEATURES
6 FEATURES
When you look at the end result, this one looks very much like the first one, only a little bit
blurred. Whats very different is how it grows. It uses a different algorithm that makes it look
like a coral. The best is when it is 90-95% finished, as shown here.
8 FEATURES
And finally, a blend between the second and third: ordered by hue, growing like a coral. When you look at the
intermediate one, be sure that its shown 1:1 and not resized because that looks bad. The end result is just weird.
10 FEATURES
the
X-Wing vs. TIE
Fighter project, our
goal was to create the first multiplayer space combat simulator to
be playable over the Internet. There
were several major problems that
we had to be overcome to accomplish this goal, not the least of
which was the Internet itself. I will
review the problems we faced, the
approach we took, and the results
we achieved. I hope the lessons I
learned will prove to be valuable to
those who read this paper.
hen we started
The Approach
Given this set of problems, we
designed a network model that we
hoped would address all of these
issues in a satisfactory way. The first
decision we made was the biggest,
and would be the source of most of
our headaches later on. We decided
that we did not want the network
model to restrict the complexity
of the missions, and we knew that
11
12 FEATURES
13
14 FEATURES
15
16 FEATURES
Conclusions Drawn
The conclusion is obvious: the
Internet sucks. We were pretty
disappointed in how our game
performed over bad Internet connections. But looking back on it
now, I believe we did as good a job
as anyone else, given the style of
game we were building, and the
constraints we were forced to deal
with.
The lack of a dedicated server
turned out to be a huge problem.
In cases where the lost connection phenomenon lasted more
than a few seconds, it was clearly
easier to send the entire state of the
world than it was to re-send all the
packets that had been lost. This was
not practical, however, because the
computer that would have to do
that would be one of the players,
and could not spare the bandwidth.
A dedicated server could have
addressed this problem, and doing
so would have been equivalent to
allowing a player to join a game
that was already in progress. Late
join was a feature we really wanted
to have in the game, but we felt
it just wasnt practical without a
dedicated server.
17
STARTUPS
Startup Sales
Negotiations 101
18 STARTUPS
Here is what your response should be when someone asks for a discount without having tried your
product:
Thanks for inquiring about pricing options! Why
dont you sign up for a trial and give the product a go?
If you find out that its a great fit Ill take care of you
and make sure you get a price that makes you happy.
Sound fair enough?
This works every time. The reply you usually get will
be:
Great! Just signed up and giving the product a go.
Thanks!
19
PROGRAMMING
20 PROGRAMMING
triggered a layout, built more HTML, and so on. Multiple insertions for each card. Times a thousand. Thats
a lot of layouts. Now we render those sections before
inserting the card into the DOM, which prevents a
bunch of layouts and speeds things up.
In the old way, the card view render function looked
something like this
render: ->
data = model.toJSON()
@$.innerHTML = templates.fill(
'card_in_list',
data
) # add stuff to the DOM, layout
@renderMembers()
@renderLabels()
# add even more stuff to the DOM, layout
@
With the change, the render function looks something like this
render: ->
data = model.toJSON()
data.memberData = []
for member in members
memberData.push member.toJSON()
data.labelData = []
for labels in labels when label.isActive
labelData.push label
partials =
"member": templates.member
"label": templates.label
@$.innerHTML = templates.fill(
'card_in_list',
data,
partials
) # only add stuff to the DOM once, only one
# layout
@
21
Progressive rendering
Even with all the progress, the browser was still locking up for five seconds. That was unacceptable, even
though I technically reached my goal. According to
Chrome DevTools Timeline, most of the time was
being spent in scripts. Trello developer Brett Kiefer had
fixed a previous UI lockup by deferring the initialization of jQuery UI droppables until after the board had
been painted using the queue method in the async
library. In that case, click long task paint became
click paint long task.
I wondered if a similar technique could be used for
rendering cards progressively. Instead of spending all
of the browsers time generating one huge amount of
DOM to insert, we could generate a small amount of
DOM, insert it, generate another small amount, insert
it, and so forth, so that the browser could free up the
UI thread, paint something quickly, and prevent locking
up. This really did the trick. Perceived rendering went
down to 960ms on my 1,000 card board.
That looks something like this
We could probably just do a for loop with a setTimeout 0 and get the same effect since we know the
size of the array. But it worked, so I was happy. There
is still some slowness as the cards finish rendering on
really big boards, but compared to total browser lockup, well accept that trade-off.
We also used the translateZ: 0 hack for a bit of
gain. With covers, stickers, and member avatars, cards
can have a lot of images. In your CSS, if you apply
translateZ: 0 to the image element, you trick the
browser into using the GPU to paint it. That frees up
the CPU to do one of the many other things it needs to
do. This browser behavior could change any day which
makes it a hack, but hey, it worked.
Friday
I made a lot of bugs that week, so I fixed them on Friday.
That was the whole week. If rendering on your web
client is slow, look for excessive paints and layouts. I
highly recommend using Chrome DevTools Timeline
to help you find trouble areas. If youre in a situation
where you need to render a lot of things at once, look
into async.queue or some other progressive rendering. n
Bobby Grace is a designer and developer working at Fog Creek
Software in New York City. He is big time into computers and
eating and bouldering and raw juice.
Reprinted with permission of the original author.
First appeared in hn.my/trellofast (fogcreek.com)
22 PROGRAMMING
23
Confessions of an
Intermediate Programmer
By Michael Bromley
programmer.
I have a pretty good grasp of
the basics. I have made enough
mistakes to have a good idea why
they were mistakes. I am aware
there is a lot that I need to know
more about. Crucially, I have some
idea of what those things are, and I
am actively and energetically working on improving.
It has taken a while for me to
get to the point where I am confident enough to admit that I am
only average in ability. I no longer
feel the need to hold second-hand
opinions that I dont really understand. Im not so afraid of being
found out when I dont know about
something.
It hasnt always been this way.
You might not credit it, but I used
to be something of a programming
guru.
This erroneous evaluation of my
own ability can best be attributed
to the relatively isolated environment in which I developed my
skills. Back in those days, even
owning a computer was a little bit
special; knowing how to use it even
more so.
am an intermediate
24 PROGRAMMING
My Magnum Opus
In the late 90s, I created a website
for a small but expanding mailorder retailer. At first, the site was
just a few static pages brochureware complete with a navigation
menu in a frameset and the obligatory visitor counter on the home
page.
When we started getting more
and more enquiries from the website, we decided to experiment with
adding e-commerce functionality.
We iterated over several off-theshelf packages, whose quality
ranged from utterly terrible to just
terrible. My memory of the first
version is predominated by fiddling about with cgi scripts and the
bizarre use of <select> elements
for almost all user interaction. A
later version was a monstrosity of
framesets and JavaScript long
before it was anywhere near advisable to base your apps functionality on JavaScript. Another version
was powered by a Microsoft Access
database.
At length we came to the realisation that, if we wanted to have a
genuinely okay-ish or even decent
online shop, wed need a custom
solution. I considered my past success with fgen.exe and its sequel,
not to mention a string of excellent
websites Id built by this time, case
25
26 PROGRAMMING
Worst Practices
Despite what I now refer to as my
worst practices approach, the
thing worked. Every bad tutorial,
every anti-PHP blog post it was
all there. Spaghetti code? Check.
Inconsistent naming of data and
routines? Check. Presentation
mixed nay, fused with business logic? Check. Magic numbers
and global data galore? Check.
To me, the object-oriented
approach was just a bunch of
unnecessary overhead and boilerplate, and I had plenty of misinformation to back me up. I knew all
about testing too click through
your feature a few times, seems
good, upload to production! I was
dimly aware of other (fancy, overlycomplex) architectures but as far
as I was concerned, mine was a perfectly sensible (and probably much
faster) way of doing things.
The proof of my rightness in
all these things was the fact that I
had written, from scratch, with my
bare hands and wits, a functioning and full-featured e-commerce
website. Furthermore, one that
My Epiphany
When I sat down to re-write all the
data-access functions, something
profound occurred. I realised that
this was going to be tough. And
I realised why it was going to be
tough.
It was going to be tough because
these functions were scattered all
over the place; because I had no
real way of knowing if I was going
to break something in some subtle
way; because the code was inconsistent and Id have to carefully study
how each instance slightly differed
from the last; because much of the
code was tightly coupled with other
parts which might also subtly break
when I made changes. In short, it
was going to be tough because of
all the bad practices and lack of
understanding that had informed
the creation of this sprawling mess
that only now revealed itself to me.
All the justifications, the defensive reasoning, the ignorance started
27
The Best
Programming
Language
28 PROGRAMMING
Ada
Ive always been curious about the idea of designing a
language around memory safety. That makes sense for
applications in real-time operating systems and critical systems in general. Probably if you are considering
using this language you dont need to read this, and
you come from a highly specialized background. This is
one of the languages that you use once you know what
you are doing, and then you dont have many options
either. Some bits of Ada:
function Best_Shuffle(S: String) return String is
T: String(S'Range) := S;
Tmp: Character;
begin
for I in S'Range loop
for J in S'Range loop
if I /= J and S(I) /= T(J) and S(J)
/= T(I) then
Tmp := T(I);
T(I) := T(J);
T(J) := Tmp;
end if;
end loop;
end loop;
return T;
end Best_Shuffle;
C
Well, you have to respect C, even if you dont like it.
Its arguably one of The Great Languages. The language
that programs machine reality (not models of). Its
the father of UNIX, all the languages of the capital
C, and the lingua franca of systems development. Its
been battle-tested, time-tested and hype-tested. The
plethora of tools available for developing, debugging,
profiling and supporting C development make it for all
29
C++
A monster. It was my first language, and I didnt really
understand how it was screwing my productivity and
limiting my skills until I tried many others. The bad
reputation of C++ is promoted by some well-known
programmers, and I agree completely. C++ seems
as if Bjarne Stoustrup took every single feature he
could think of and added it to C. The cognitive load
it imposes might make you more than 80% less productive. Think of it this way: you have a brain of X
capacity, and that capacity is limited, doesnt matter
how much capacity you have, and you want to leave
as much as possible of it for the important things. The
wise thing to do would be to reduce the amount of
brain power used for the language per se, and use the
most of that brain for solving the problem and encoding an algorithm. If the language is complex, no matter
how smart you are, youll need to use more of your
brain for the syntax and the semantics of the language
and less to efficiently projecting your ideas onto code.
I think C++ is the quintessential example of too
much complexity for not that much gain. I agree,
building large programs in C is difficult (but arguably
an option, look at the Linux Kernel). Go, Rust and D
are better languages by all measures, except for the fact
that C++ is what the world actually uses.
30 PROGRAMMING
C#
Enterprise language that aims at reducing any kind of
programmer creativity that might hinder its replaceability in any large organization. Object-oriented,
statically typed, verbose, with heavy libraries and lots
of boilerplate. You can see Microsofts hand behind
this creation. But dont get me wrong, it is not a bad
language. It just isnt sexy, which precisely is what
Microsoft wanted in the first place. At least, it is a radical improvement when compared with Visual Basic. I
would use it for:
Windows development.
There are huge things going on in this language: Unity3D, Xamarin, .NET, XNA.
Objective-C
I have a much better opinion of Objective-C than of
C++ (and C#). Its syntactically ugly, but I like it as a
language. Its got a great set of libraries based on NextStep, with the plus of being a real improvement upon
C, without growing too much out of control and bringing ambiguities in keywords with its parent language.
As I said, its a bit ugly and difficult to read, especially
when nesting functions, but definitely its beauty resides
in its conceptual approach, not in its syntax. See this
nested call:
char bytes[] = "some data";
NSString *string = [[NSString alloc]
initWithBytes:bytes length:9 encoding:NSASCIIStr
ingEncoding];
if (i <= n) {
[sample addObject:item];
} else if (rand() % i < n) {
sample[rand() % n] = item;
}
return sample;
When you want to use the JVM technology without the Java thing. Both programmer happiness and
productivity will improve.
Exploratory programming that could grow into production code. This is actually an area where Lisps
nature really shines, but Clojure relies on the Java
stack, exposing a lot of production code to it.
};
}
int main(int argc, const char *argv[]) {
@autoreleasepool {
NSCountedSet *bin = [[NSCountedSet alloc] init];
for (int trial = 0; trial < 100000; trial++)
{
SOfN s_of_n = s_of_n_creator(3);
NSArray *sample;
for (int i = 0; i < 10; i++) {
sample = s_of_n(@(i));
}
[bin addObjectsFromArray:sample];
}
NSLog(@"%@", bin);
}
return 0;
}
Clojure
Being a Scheme programmer I have respect for Clojure: its a so-called modern Lisp, with some unique
features. Id say Clojures strong points are Java
interoperability and concurrency utilities in the core
language. Its a sibling of Scala, but differs in their
flavor: lisp vs. hybrid OOP/functional, making Clojure
less popular due to the excess of parentheses. Choosing one of these two for a project is a matter of taste,
because neither are proven technologies with a long
track record of successful production applications, as
compared with Java or PHP, although they both stand
on the shoulders of JVM. Another thing to take into
consideration for any JVM-base language is the startup
time of the virtual machine: it doesnt seem like a very
lightweight solution for small tasks. These are the situations where I would use Clojure:
D
I used to love D. D is like C++ done right. D1 felt
like a low-level-oriented Python. Like a pythonized
C or something like that. Its awesome: you feel
development speed, focusing on the algorithms and
not the language, but you dont sacrifice low-level
31
If you need low-level programming with fast binaries. Again, doing your own thing, like a standalone
program.
32 PROGRAMMING
dec2 dec".writeln;
Erlang
This is a very specific-purpose language. Erlangs web
page describes it very clearly: [] build massively scalable soft real-time systems with requirements on high
availability. Some of its uses are in telecoms, banking,
e-commerce, computer telephony and instant messaging. Erlangs runtime system has built-in support for
concurrency, distribution and fault tolerance. Erlang has
been proven for, and its behind some very demanding applications such as WhatsApp. The code itself
feels very functional, and its syntax is clean and very
readable.
Take a look at the code for a simple concurrent
program:
-module(hw).
-export([start/0]).
start() ->
[ spawn(fun() -> say(self(), X) end) || X <['Enjoy', 'Rosetta', 'Code'] ],
wait(2),
ok.
say(Pid,Str) ->
io:fwrite("~s~n",[Str]),
Pid ! done.
wait(N) ->
receive
done -> case N of
0 -> 0;
_N -> wait(N-1)
end
end.
Go
I havent used this personally. Yet. But its clear that
this is Googles take on making a C with the good
parts of C++ and better than both in its concurrency
support. It has better features than C++, and it is way
simpler. It has no unsafe pointer arithmetic, closures
and first-class functions, and garbage collection. Go
might become the server language in the future. So,
when would I try Go?
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
words := []string{"Enjoy", "Rosetta",
"Code"}
rand.Seed(time.Now().UnixNano())
q := make(chan string)
for _, w := range words {
go func(w string) {
time.Sleep(time.Duration(rand.
Int63n(1e9)))
q <- w
}(w)
}
for i := 0; i < len(words); i++ {
fmt.Println(<-q)
}
}
Java
The same as C#, but for the Java Virtual Machine. It
was there first (in fact C# copied it), and its sort of
the standard object-oriented language in the industry. Its used for everything, from web apps to games.
Almost everything except embedded device software,
and perhaps high performance parallel computation
software. It serves as the foundation for many other
languages (specifically its virtual machine). Take a
look at Processing for an interesting project, where a
wrapper language (just sugar-coated Java) is used for
education and digital art. When would I personally
recommend you use Java?
Haskell
This language truly feels as a more advanced thinking tool than the others in this list. It has libraries for
almost any need and it has a hard-core community.
Arguably its a language with a high barrier of entry. It
will expand your mind, and surround you with some
of the brightest minds in the programming languages
communities, in my opinion.
33
JavaScript
PHP
OCaml
Its sort of like Haskell, but it feels like its more willing to bend to the programmers desires. When there
is need, some compromises to its purity are made
in benefit of easier solutions, for instance when the
procedural/object-oriented approach seems to work
best. There are companies using it, I guess just for this
benefit over Haskell. Take a look at this little snippet:
let n_arrays_iter ~f = function
| [] -> ()
| x::xs as al ->
let len = Array.length x in
let b = List.for_all (fun a -> Array.
length a = len) xs in
if not b then invalid_arg "n_arrays_iter:
arrays of different length";
for i = 0 to pred len do
let ai = List.map (fun a -> a.(i)) al in
f ai
done
34 PROGRAMMING
Python
A pretty language. I definitely like its whitespace-based
block structure: you dont need ugly semicolons all the
time. I like this so much that I tend to write my JavaScript this way. But this is very much a matter of taste,
and as a matter of fact is the very reason many people
dont like the language. Its a clean language that tries
to take the burden of the syntax off of your shoulders. While it is debatable that it succeeds at this, the
language is definitely supported by a great community,
which put it in a very strong position when compared
to its pal Ruby. Its always hard to choose between
these two languages, although Python seems more
widespread, and a more sensible choice for a variety of
fields and applications. When would I use Python?
Web development.
Cross-platform support.
Ruby
Ruby on Rails. The single reason this language could
ever be part of this list. Of course, nowadays its easy
to see it in many other projects, but it all began with
Rails. Before that, Ruby was an obscure programming
language from Japan. This is a perfect example of how
a killer app/framework spawned a great community
which in turn made more killer apps/frameworks and
made the language popular even though the place for
this sort of language was supposedly taken.
One thing Ive heard from many Ruby developers
and I had experienced myself, is the actual joy that
comes from using it. In other words, its the contrary of
a frustrating language, although I dont know if this is
Scala
Seems to be winning the race for the best JVM-based
language award. Im pretty sure that most of it comes
from a familiar syntax, when compared with Clojure,
the other big contender. As in Clojure, the reason this
language is in this list is because its easy interfacing
with Java make it a viable choice for a real project.
Look at this small snippet generating the Hofstadter Q
sequence:
object HofstadterQseq extends App {
val Q: Int => Int = n => {
if (n <= 2) 1
else Q(n-Q(n-1))+Q(n-Q(n-2))
}
(1 to 10).map(i=>(i,Q(i))).
foreach(t=>println("Q("+t._1+") = "+t._2))
println("Q("+1000+") = "+Q(1000))
}
2. Lack of libraries.
Scheme
3. Poor performance.
Well, the first one is partially true (there are too
many implementations), but there are only a handful of good ones and you need to choose the one that
best fits you. The second is also partially true: there
are libraries, but they are scattered. There are some
projects that offer alternatives, and lots of tiny projects
out there. The fragmentation of the language is made
obvious when looking for support code: you need to
make it work with your implementation. However, this
is often not so difficult or time-consuming, and most
importantly, if you use Scheme implementations with
good FFI support, such as Gambit or Chicken Scheme,
you have easy access to all those libraries in C. I actually do it, and it works great, contrary to what you may
think. Finally, poor performance. This one is actually
35
36 PROGRAMMING
Conclusion
I started this long post with my selection of choice.
Programming is a beautiful craft that I love wholeheartedly, so I admit that Im heavily biased according
to my personal experience. Choosing a programming
language for a task or project is sometimes difficult, as
so many variables take place. In my opinion, there are
three that prevail, in this order:
1. Is the project aimed at production, or belongs to a
sufficiently large organization with a culture or bias
towards a programming language?
2. Is the task at hand sufficiently special to require a
programming language with very specific features?
3. Do you love or want to try developing in that programming language?
Thats how I approach this issue. Even though sometimes I break the rules n
lvaro Castro-Castilla is an architect-civil engineer, digital artist
and software developer. In his trajectory he has been playing
with and within the frontiers of these disciplines, exploring and
creating worlds that can be built with code.
Reprinted with permission of the original author.
First appeared in hn.my/bestpro (fourthbit.com)
Dashboards
StatsD
Happiness
*Hosted Graphites mantis shrimp / eagle breeding program has been unsuccessful thus far
37
SPECIAL
By James Greig
38 SPECIAL
39
he end of procrastination
is the art of letting go.
Ive been a lifelong
procrastinator, at least until recent
years. I would put things off until
deadline, because I knew I could
come through. I came through on
tests after cramming last minute,
I turned articles in at the deadline
after waiting until the last hour, I
got things done.
Until I didnt. It turns out
procrastinating caused me to miss
deadlines, over and over. It stressed
me out. My work was less-thandesirable when I did it last minute.
Slowly, I started to realize that procrastination wasnt doing me any
favors. In fact, it was causing me a
lot of grief.
But I couldnt quit. I tried a lot of
things. I tried time boxing and goal
setting and accountability and the
Pomodoro Technique and Getting
Things Done. All are great methods,
but they only last so long. Nothing
really worked over the long term.
Thats because I wasnt getting to
the root problem.