forked from Hardmath123/hardmath123.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuse-imperfect-tools.html
198 lines (189 loc) · 11 KB
/
use-imperfect-tools.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/static/base.css"/>
<title>Use Imperfect Tools - Comfortably Numbered</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script>
MathJax.Hub.Config({
tex2jax: {inlineMath: [['($','$)']]}
});
</script>
</head>
<body>
<header id="header">
<link rel="stylesheet" href="/octicons/octicons.css">
<script src="static/cheet.js" charset="utf-8"></script>
<script src="static/main.js"></script>
<h1>
<a href="/"><span class="left-word">Comfortably</span><span class="right-word">Numbered</span></a>
</h1>
<!-- You're reading the source to my blog? What do you think?
Do you have dinner plans? -->
</header>
<article id="postcontent" class="centered">
<section>
<h2>Use Imperfect Tools</h2>
<h4>Tuesday, March 17, 2015 · 4 min read</h4>
<p>As I look back on programs I’ve written, I almost always notice that the most
successful are the hacks. The ones whose source code is spaghetti, the ones
which consist of patches upon patches, and <em>not</em> the ones where I painstakingly
mapped out a beautiful API.</p>
<p>I speak of such monstrosities as <code>alchemy</code>, an IRC bot to play <a href="https://littlealchemy.com">Little
Alchemy</a> collaboratively in IRC. <code>alchemy.py</code> is
almost fully contained in a single while loop, and important game functions are
nested so deep that they must be indented more than 80 characters to be valid
Python. <code>alchemy</code> might be one of my most successful software projects if
measured by total amount of happiness brought to users.</p>
<p>Speaking of IRC bots, the <code>jokebot</code> skeleton code introduced in a previous post
is probably the most-forked of my projects, giving rise to 3 derivative bots
within a week of its first commit. <code>jokebot</code> was written with no heed for
efficiency, and so the unpatched <code>jokebot</code> was a big fat memory hog.</p>
<p>I also speak of <code>bouncy</code>, a screensaver I wrote over the course of a couple of
hours for no good reason, which has been adorning my mom’s Mac every 10 minutes
for the past two years. I have no idea what <code>bouncy</code>‘s source looks like, but
I do recall abusing nested <code>NSArray</code>s because Xcode didn’t let me create a new
class.</p>
<p>I speak of Snapin8r, which began as a Pythonic mess, was then ported to
JavaScript line-by-line, and then heavily patched as bug reports rolled in.
Most things are handled by one giant if/elif chain in a for loop. Again,
Snapin8r is used by a disproportionately large number of people considering how
shaky the entire thing is.</p>
<p>And I speak of <a href="http://scratch.mit.edu/projects/10490996/">miscellaneous</a>
hacked-together Scratch <a href="http://scratch.mit.edu/projects/1322628/">projects</a>
that have, over the years, accumulated dozens of “remixes” as people ran into
them and used their code for amazing derivative works.</p>
<p>I do <em>not</em> speak of things like <code>nearley</code>, which despite hundreds of commits by
several authors, has only one legitimate dependency on <code>npm</code>. Or, for that
matter, any of my other well-organized projects on Github. </p>
<hr>
<p>Perhaps there’s a reason for this. As logical people, programmers instinctively
build
<a href="http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/cathedral-bazaar.ps">cathedrals</a>,
not bazaars. “If we get it right the first time,” we say, “we’ll have a good
foundation and won’t have any showstopper bugs.” And then we spend a few weeks
building up these “foundations” and then release monoliths.</p>
<p>But, as I’ve observed, that’s not how effective software gets created. The
best software gets used as it’s being developed. The way it’s used affects its
development, so that instead of just a theoretical curiosity designed to be
perfect and modular, the program solves real-world problems from day 1. The
best software begins as a funny IRC bot or hackey Bash script.</p>
<p>And so the lesson I want to teach myself by posting this post is that the most
important thing isn’t to pick the perfect APIs, tools, libraries, frameworks,
algorithms, and languages. The most important thing is to just start writing
code.</p>
<p>This is <em>really</em> hard.</p>
<p>Even selecting a language for a new project is hard. I want my project to be
fast, but C is too low-level. Scheme would probably be the best choice
algorithmically. Should I use Racket or Chicken? Racket seems more documented,
but it doesn’t compile to native code cleanly. Chicken has yucky documentation,
and I don’t like Chicken’s package manager. Maybe I should do it in Python? But
I hate Python. Hang on, I’ve been meaning to learn Haskell for a while, now.
Wait, no, I/O in Haskell is hard, and I’ll need a good POSIX interface for this
project.</p>
<p>Speaking of which, how should I accept input? Stdin? File name? In what format?
JSON? YAML? I don’t know how to parse JSON in Scala yet. Actually, maybe my
program would be better as a service hosted over HTTP?</p>
<p>How about command-line arguments? Does Rust have a good option parser? Will I
have to write it myself? I probably won’t be able to write an option parser
that’s as efficient as industry-standards. Parsing is hard. Maybe I should use
JavaScript; I already know how to use nomnom.</p>
<p>But if it’s in JavaScript, I can bypass all this and create it as a sleek,
intuitive, and beautiful GUI in the browser. Then again, I want my project to
be fast…</p>
<hr>
<p>I think I’ve made my point: you can spend as long as you wish trying to choose
the right tool. The truth, of course, is that there is no “right tool”. In
fact, whatever tool you pick, you’re going to hit a limitation at some point.
It’s reality. So instead of spending ages choosing the right tool, just pick
the one that <em>feels</em> right and get some code written. Imperfect code is always
more useful than no code. You should think about interfacing and efficiency
<em>second</em>.</p>
<p>Ok, fine, I’m going to regret saying that. There’s a very good argument to be
made for thinking about the architecture of a project before starting on it. It
leads to clean, maintainable code. It minimizes the amount of refactoring
drudgery.</p>
<p>But I think all those things are secondary to actually having a working
prototype. Yes, you’re going to run into painful distribution issues—it’s
happened to me, and it was annoying enough to make me give up on the project.
But the open-source world came to the rescue, and someone forked and continued
it. What matters is that I put my idea into code and gave it to the world.</p>
<p>So my promise to myself—as of publishing this post—is to spend less time
debating tools and more time using them. This means forcing myself to
consciously use imperfect tools, which might cause mild internal bleeding.
Let’s see how long I survive.</p>
</section>
<div id="comment-breaker">◊ ◊ ◊</div>
<!--
<section>
<center>(<a id="comment-toggle" href="#comment-toggle">Click to load comments…</a>)</center>
<div id="disqus_thread"></div>
<script type="text/javascript">
var disqus_shortname = 'comfortablynumbered';
var disqus_identifier = 'use-imperfect-tools.md';
window.addEventListener(
'load',
(function() {
document.getElementById('comment-toggle').addEventListener('click',
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
}),
true);
}),
true
);
</script>
</section>
-->
</article>
<footer id="footer">
<div>
<ul>
<li><a href="http://github.com/Hardmath123">
<span class="octicon octicon-mark-github"></span>
Github</a></li>
<li><a href="feed.xml">
<span class="octicon octicon-rss"></span>
Subscribe (RSS)</a></li>
<li><a href="https://github.com/Hardmath123/hardmath123.github.io/issues/new?title=Hi&body=How's%20it%20going%3F">
<span class="octicon octicon-comment-discussion"></span>
Feedback</a></li>
<li><a href="mailto:contact-at-comfortablynumbered-dot-appspotmail-dot-com">
<span class="octicon octicon-mail-read"></span>
Email me</a></li>
<li><a href="http://creativecommons.org/licenses/by-nc/3.0/deed.en_US">
<span class="octicon octicon-law"></span>
CC BY-NC 3.0</a></li>
<li><a href="appreciation.html">
<span class="octicon octicon-beer"></span>
Other</a></li>
</ul>
</div>
<!--
<span class="sc">ComfortablyNumbered</span> · Hardmath123 (2013) · <a href="feed.xml">RSS Feed</a>
·
<a href="/appreciation.html">
<span class="octicon octicon-beer"></span></a>
<a rel="license" href="http://creativecommons.org/licenses/by-nc/3.0/deed.en_US">
<img
alt="Creative Commons License"
src="http://i.creativecommons.org/l/by-nc/3.0/80x15.png"/>
</a>
-->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-46120535-1', 'hardmath123.github.io');
ga('require', 'displayfeatures');
ga('send', 'pageview');
</script>
</footer>
</body>
</html>