forked from steveklabnik/blog
/
atom.xml
3506 lines (2817 loc) · 200 KB
/
atom.xml
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Steve's Blog</title>
<link href="http://blog.steveklabnik.com/atom.xml" rel="self"/>
<link href="http://steveklabnik.com/"/>
<updated>2011-07-03T17:47:21-04:00</updated>
<id>http://steveklabnik.com/</id>
<author>
<name>Steve Klabnik</name>
<email>steve@steveklabnik.com</email>
</author>
<entry>
<title>Nobody Understands REST or HTTP</title>
<link href="http://blog.steveklabnik.com/2011/07/03/nobody-understands-rest-or-http.html"/>
<updated>2011-07-03T00:00:00-04:00</updated>
<id>http://blog.steveklabnik.com/2011/07/03/nobody-understands-rest-or-http</id>
<content type="html"><p>The more that I've learned about web development, the more that I've
come to appreciate the thoroughness and thoughtfulness of the authors of
the HTTP RFC and Roy Fielding's dissertation. It seems like the answers
to most problems come down to "There's a section of the spec for that."
Now, obviously, they're not infallible, and I'm not saying that there's
zero room for improvement. But it really disappoints me when people
don't understand the way that a given issue is supposed to be solved,
and so they make up a partial solution that solves their given case but
doesn't jive well with the way that everything else works. There are
valid criticisms of the specs, but they have to come from an informed
place about what the spec says in the first place.</p>
<p>Let's talk about a few cases where either REST or HTTP (which is clearly
RESTful in its design) solves a common web development problem.</p>
<h3>I need to design my API</h3>
<p>This one is a bit more general, but the others build off of it, so bear
with me.</p>
<p>The core idea of REST is right there in the name: "Representational
State Transfer" It's about transferring representations of the state...
of resources. Okay, so one part isn't in the name. But still, let's
break this down.</p>
<h4>Resources</h4>
<p>From <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_2_1_1">Fielding's dissertation</a>:</p>
<blockquote><p>The key abstraction of information in REST is a resource. Any information
that can be named can be a resource: a document or image, a temporal service
(e.g. "today's weather in Los Angeles"), a collection of other resources, a
non-virtual object (e.g. a person), and so on. In other words, any concept that
might be the target of an author's hypertext reference must fit within the
definition of a resource. A resource is a conceptual mapping to a set of
entities, not the entity that corresponds to the mapping at any particular
point in time.</p></blockquote>
<p>When we interact with a RESTful system, we're interacting with a set of
resources. Clients request resources from the server in a variety of
ways. But the key thing here is that resources are <em>nouns</em>. So a RESTful
API consists of a set of URIs that map entities in your system to
endpoints, and then you use HTTP itself for the verbs. If your URLs have
action words in them, you're doing it wrong. Let's look at an example of
this, from the early days of Rails. When Rails first started messing
around with REST, the URLs looked like this:</p>
<pre><code>/posts/show/1
</code></pre>
<p>If you you use Rails today, you'll note that the corresponding URL is
this:</p>
<pre><code>/posts/1
</code></pre>
<p>Why? Well, it's because the 'show' is unnecessary; you're performing a
GET request, and that demonstrates that you want to show that resource.
It doesn't need to be in the URL.</p>
<h4>A digression about actions</h4>
<p>Sometimes, you need to perform some sort of action, though. Verbs are
useful. So how's this fit in? Let's consider the example of transferring
money from one Account to another. You might decided to build a URI like
this:</p>
<pre><code>POST /accounts/1/transfer/500.00/to/2
</code></pre>
<p>to transfer $500 from Account 1 to Account 2. But this is wrong! What
you really need to do is consider the nouns. You're not transferring
money, you're creating a Transaction resource:</p>
<pre><code>POST /transactions HTTP/1.1
Host: &lt;snip, and all other headers&gt;
from=1&amp;to=2&amp;amount=500.00
</code></pre>
<p>Got it? So then, it returns the URI for your new Transaction:</p>
<pre><code>HTTP/1.1 201 OK
Date: Sun, 3 Jul 2011 23:59:59 GMT
Content-Type: application/json
Content-Length: 12345
Location: http://foo.com/transactions/1
{"transaction":{"id":1,"uri":"/transactions/1"}}
</code></pre>
<p>Whoah, <a href="http://timelessrepo.com/haters-gonna-hateoas">HATEOS</a>! Anyway,
so now we can GET our Transaction:</p>
<pre><code>GET /transactions/1 HTTP/1.1
Accept: application/json
</code></pre>
<p>and the response:</p>
<pre><code>HTTP/1.1 blah blah blah
{"id":1,"status":"in-progress"}
</code></pre>
<p>So we know it's working. We can continue to poll the URI and see when
our transaction is finished, or if it failed, or whatever. Easy! But
it's about manipulating those nouns.</p>
<h4>Representations</h4>
<p>You'll notice a pair of headers in the above HTTP requests and
responses: Accept and Content-Type. These describe the different
'representation' of any given resource. From <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_2_1_2">Fielding</a>:</p>
<blockquote><p>REST components perform actions on a resource by using a representation to
capture the current or intended state of that resource and transferring that
representation between components. A representation is a sequence of bytes,
plus representation metadata to describe those bytes. Other commonly used but
less precise names for a representation include: document, file, and HTTP
message entity, instance, or variant.</p>
<p>A representation consists of data, metadata describing the data, and, on
occasion, metadata to describe the metadata (usually for the purpose of
verifying message integrity).</p></blockquote>
<p>So <code>/accounts/1</code> represents a resource. But it doesn't include the form
that the resource takes. That's what these two headers are for.</p>
<p>This is also why adding <code>.html</code> to the end of your URLs is kinda silly.
If I request <code>/accounts/1.html</code> with an <code>Accept</code> header of
<code>applicaion/json</code>, then I'll get JSON. The <code>Content-Type</code> header is the
server telling us what kind of representation it's sending back as well.
The important thing, though, is that a given resource can have many
different representations. Ideally, there should be one unambiguous
source of information in a system, and you can get different
representations using <code>Accept</code>.</p>
<h4>State and Transfer</h4>
<p>This is more about the way HTTP is designed, so I'll just keep this
short: Requests are designed to be stateless, and the server holds all
of the state for its resources. This is important for caching and a few
other things, but it's sort of out of the scope of this post.</p>
<p>Okay. With all of that out of the way, let's talk about some more
specific problems that REST/HTTP solve.</p>
<h3>I want my API to be versioned</h3>
<p>The first thing that people do when they want a versioned API is to
shove a /v1/ in the URL. <em><em>THIS IS BAD!!!!!1</em></em>. <code>Accept</code> solves this
problem. What you're really asking for is "I'd like the version two
representation of this resource." So use accept!</p>
<p>Here's an example:</p>
<pre><code>GET /accounts/1 HTTP/1.1
Accept: application/vnd.steveklabnik-v2+json
</code></pre>
<p>You'll notice a few things: we have a + in our MIME type, and before it
is a bunch of junk that wasn't there before. It breaks down into three
things: <code>vnd</code>, my name, and <code>v2</code>. You can guess what v2 means, but what
about <code>vnd</code>. It's a <a href="http://tools.ietf.org/html/rfc4288#section-3.2">Vendor MIME Type</a>.
After all, we don't really want just any old JSON, we want my specific
form of JSON. This lets us still have our one URL to represent our
resource, yet version everything appropriately.</p>
<p>I got a comment from <a href="http://avdi.org/">Avdi Grimm</a> about this, too:</p>
<blockquote><p>Here's an article you might find interesting: <a href="http://www.informit.com/articles/article.aspx?p=1566460">http://www.informit.com/articles/article.aspx?p=1566460</a></p>
<p>The author points out that MIMETypes can have parameters, which means you can actually have a mimetype that looks like this:</p>
<pre><code>vnd.example-com.foo+json; version=1.0
</code></pre>
<p>Sadly, Rails does not (yet) understand this format.</p></blockquote>
<h3>I'd like my content to be displayed in multiple langauges</h3>
<p>This is related, but a little different. What about pages in different
languages? Again, we have a question of representation, not one of
content. /en/whatever is not appropriate here. Turns out, <a href="http://tools.ietf.org/html/rfc2616#section-14.4">there's a
header for that: Accept-Language</a>.
Respect the headers, and everything works out.</p>
<h3>I'd like my content to have a mobile view</h3>
<p>Sounds like I'm beating a dead horse, but again: it's a representation
question. In this case, you'd like to vary the response by the
User-Agent: give one that's mobile-friendly. There's a whole list of
<a href="http://www.w3.org/TR/mobile-bp/">mobile best practices</a> that the w3c
recommends, but the short of it is this: the User-Agent should let you
know that you're dealing with a mobile device. For example, here's the
first iPhone UA:</p>
<pre><code>Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3
</code></pre>
<p>Whatever you do, for the love of users, please don't detect these
headers, then redirect your users to m.whatever.com. One of my local
news websites does this, and it means that every time I try to follow a
link from Twitter in my mobile browser, I don't see their article, I see
their homepage. It's infuriating.</p>
<h3>I'd like to hide some of my content</h3>
<p>Every once in a while, you see a story like this: <a href="http://www.boingboing.net/2010/10/25/local-newspaper-boas.html">Local paper boasts
ultimate passive-agressive paywall policy</a>.
Now, I find paywalls distasteful, but this is not the way to do it.
There are technological means to limit content on the web: making users
be logged-in to read things, for example.</p>
<p>When this was discussed on Hacker News, <a href="http://news.ycombinator.com/item?id=1834075">here's</a>
what I had to say:</p>
<p>nkurz:</p>
<blockquote><p>I presume if I had an unattended roadside vegetable stand with a cash-box, that I'd be able to prosecute someone who took vegetables without paying, certainly if they also made off with the cash-box. Why is this different on the web? And if a written prohibition has no legal standing, why do so many companies pay lawyers to write click-through "terms of service" agreements?</p></blockquote>
<p>me:</p>
<blockquote><blockquote><p>Why is this different on the web?</p></blockquote>
<p>Let's go through what happens when I visit a web site. I type a URL in my bar, and hit enter. My web browser makes a request via http to a server, and the server inspects the request, determines if I should see the content or not, and returns either a 200 if I am allowed, and a 403 if I'm not. So, by viewing their pages, I'm literally asking permission, and being allowed.</p>
<p>It sounds to me like a misconfiguration of their server; it's not doing what they want it to.</p></blockquote>
<h3>I'd like to do some crazy ajax, yet have permalinks</h3>
<p>This is an example of where the spec is obviously deficient, and so
something had to be done.</p>
<p>As the web grew, AJAXy 'web applications' started to become more and
more the norm. And so applications wanted to provide deep-linking
capabilities to users, but there's a problem: they couldn't manipulate
the URL with Javascript without causing a redirect. They <em>could</em>
manipulate the anchor, though. You know, that part after the #. So,
Google came up with a convention: <a href="http://code.google.com/web/ajaxcrawling/docs/getting-started.html">Ajax Fragments</a>.
This fixed the problem in the short term, but then the spec got fixed in
the long term: <a href="http://dev.w3.org/html5/spec-author-view/history.html">pushState</a>.
This lets you still provide a nice deep URL to your users, but not have
that awkward #!.</p>
<p>In this case, there was a legitimate technical issue with the spec, and
so it's valid to invent something. But then the standard improved, and
so people should stop using #! as HTML5 gains browser support.</p>
<h3>In conclusion</h3>
<p>Seriously, most of the problems that you're solving are social, not
technical. The web is decades old at this point, most people have
considered these kinds of problems in the past. That doesn't mean that
they always have the right answer, but they usually do have an answer,
and it'd behoove you to know what it is before you invent something on
your own.</p>
</content>
</entry>
<entry>
<title>Single text, many masters</title>
<link href="http://blog.steveklabnik.com/2011/05/21/single-text-many-masters.html"/>
<updated>2011-05-21T00:00:00-04:00</updated>
<id>http://blog.steveklabnik.com/2011/05/21/single-text-many-masters</id>
<content type="html"><p>Hey everyone. Here's a draft of an essay I've been working on. I'd love
to hear your feedback.</p>
<p>The word 'engineering' has a deep connection to the word 'trade-offs' in
my mind. Most engineering decisions come down to evaluating a few
differing alternatives, and often multiple factors end up being
negatively correlated. You can make something stronger, but then it will
be heavier. It can be made faster, but then it's significantly more
expensive. A good engineer is able to take all of these factors into
account, and design a system such that it maximizes its effectiveness
across the sum of all of the relevant constraints. No matter if you consider
the act of writing software an art, science, or engineering, its indisputable
that designing complex software systems is identical in this respect. There are
dozens of different metrics that system architects take into consideration while
crafting a plan of attack, but but there's a deeper question of balance
here that's significantly different than these more traditional
engineering issues.</p>
<p>Text, in the form of source code, presents unique challenges of
composition. These difficulties all stem from the same root: source code is a
singular text, but must be intelligible to multiple, simultaneous
audiences. More traditional forms of authorship still take audience into
consideration, of course, but the decision to engage a diverse group of
people is the choice of the writer. While mass appeal may be
something that certain authors strive to attain, it's not an inherent
property of their chosen form of expression. Source code, while text,
inhabits a multiplicity of forms, and software developers are confronted
with this inherent multi-faceted complexity when composing any
particular software work. Some of these forms suit certain audiences
better than others, and so it falls to the programmer to manage which
form they are currently working in, consider which audience they are
attempting to write for, and arrange all of these forms amongst one
another in such a way that any particular audience is able to navigate
and extract the proper information from the source without confusion.</p>
<p>In this post, I'll expand on the concept of audiences for code, and in a
future post, I'll explore the simultaneous forms that code takes.</p>
<h2>The multitude of audiences</h2>
<h3>The default audience: the computer</h3>
<blockquote><p>Science is what we understand well enough to explain to a computer. Art
is everything else we do.</p>
<ul>
<li>Don Knuth</li>
</ul>
</blockquote>
<p>This may seem obvious, but the when considering the question of "Who are
programs written for?", many would say "The computer. Duh." In many
ways, a computer is the primary reader of a particular piece of source
code. The code that's given to a computer will be executed billions of
times per second, repeated, recalculated, and re-interpreted over and
over and over again.</p>
<p>The computer's native understanding of software comes from machine
code. Machine code are the binary numbers that the CPU loads into memory
and processes directly. For example, here's a line of machine code for
an x86 machine that puts the value '97' into the AL register, graciously
stolen <a href="http://en.wikipedia.org/wiki/Assembly_language#Assembly_language">from
Wikipedia</a>:</p>
<pre><code>10110000 01100001
</code></pre>
<p>While most would consider this unintelligible, computers were actually
programmed this way at one time. My uncle actually did this by flipping
switches to set the binary and pushed a button to store it in memory.
Unfortunately, what's good for the computer isn't good for the human
programmer. This is why assembly language was created. Assembly language
has a 1 to 1 mapping to machine code, but is much easier for humans to
understand. Here's that same line in assembly:</p>
<pre><code>MOV AL, 61h ; Load AL with 97 decimal (61 hex)
</code></pre>
<p>The <code>MOV</code> corresponds with <code>10110</code>, <code>AL</code> maps to <code>000</code>, and 61 hex is
<code>01100001</code>. <code>MOV</code> is short for 'move,' though, and this mnemonic is just
a bit easier to understand than <code>10110</code>. This is the most basic example
of a compositional trade-off. It's not a true trade-off, because they
map perfectly to one another, but it illustrates the difference between
composing in a language that the computer understands and one that's
more natural for the programmer. Another important concept comes into
play, that of <em>compilation</em>. Virtually every work of composition created
in software is automatically translated to another form before it is
executed. We'll address this concept more fully when we discuss form
later.</p>
<p>If that's where assembly stopped, it would remain a 1 to 1 mapping.
However, virtually every assembly language also offers macros, and this
moves the code further away from the machine and destroys the
synchrony of the two forms. Here's an example:</p>
<pre><code>MOV EAX, [EBX]
</code></pre>
<p>The <code>[]</code> characters change the meaning of <code>EBX</code>, rather than be the
value stored in that particular register, they imply that the value is a
memory address, and we want to move the contents of that address to
<code>EAX</code>. The generated machine code could now be processed into multiple
valid assembly forms, and so the transformation is only perfect in one
direction, even if it's possible to 'decompile' it into one of those
possible encodings. This is considered to be an acceptable trade-off for
human readability; we very rarely want to turn machine code back into
assembly.</p>
<p>There's also a jump between higher level languages, as well. Here's the
assembly statements that adds 2 and 3 together:</p>
<pre><code>MOV EAX, 2
ADD EAX, 3
</code></pre>
<p><code>ADD</code>, of course, is the statement that adds a number to the register
that's given. Now <code>EAX</code> has the value 5. Here's the same code, but in C:</p>
<pre><code>int x = 2;
x = x + 3;
</code></pre>
<p>Pretty simple. You can see how the C is much easier to understand; we
say what type <code>x</code> is (an integer), and it's a bit more explicit. <code>x</code> is
equal to <code>x</code> + three. However, since the C is divorced from the machine,
and is written for the person, we can change our compiler to make
assembly code that works on a different kind of processor architecture.
If we were to compile the above C for x86_64, a 64 bit version of x86,
we might get some assembly that'd look like this:</p>
<pre><code>MOVL RAX, 2
ADDL RAX, 3
</code></pre>
<p>While this code looks similar to the above, it is quite different. This
uses the native 64 bit types, rather than the 32 bit types above. The
other important thing is that by writing code that's divorced from the
machine, and written for people, we're able to translate it into the
code for multiple machines. If we had written the assembly above, when
moving to another architecture, it would have required a total re-write.
And while this particular sample looks very similar, a more complex
piece of code will be significantly divergent, but I don't want to go
into the details of two kinds of assembly code. Because we can define
the languages for humans, and the language of computers is somewhat
beholden to the physical machine itself, it's significantly easier to do
the translation from C to the two kinds of machines, rather than trying
to translate from one machine to another. What we lose in this kind of
translation, though, is efficiency. Code that was hand-crafted for each
machine would be more performant, and better represent each individual
platform.</p>
<p>Even though we may choose to use a language that's more understandable
to people, it still has to be understood by the computer in some form.
This translation will introduce some amount of penalty, and so it's
important that this gets taken into consideration. Sometimes, code must
be written in a way that's not easy for a person to read, because it's
easier for the computer to be efficient with a more opaque
implementation.</p>
<h3>The reflexive audience: the programmer himself</h3>
<blockquote><p>Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by
definition, not smart enough to debug it.</p>
<ul>
<li>Brian Kernighan</li>
</ul>
</blockquote>
<p>Everyone who writes code has experienced this at some time or another.
You write a whole bunch of code, and then a few months goes by, and you
take a look at it, and it's absolutely unintelligible. This happens
because at the time of inception, the author of a particular piece of
code has an incredibly close relationship to it. As it was just written,
the code is obvious to the author. They're in the proper mindset to
understand the intention that was drawn upon to necessitate bringing
those lines into the world, and so no extra explanation is necessary. As
time goes on, however, the author becomes more close to the third
audience, other programmers. It's important for coders to recognize this
fact, and take preventative steps to ameliorate this confusion.</p>
<p>Even though the author will approach the position of the other audience
eventually, this audience is distinct because there is a certain level
of explanation that sits between undocumented, inexpressive code and
code that's well explained, and this is the position most code is in. An
explanation that's helpful to those who understand the code, but not to
those who don't is better than nothing. This sort of code may be overly
contextual, and could use some added information to improve its clarity.</p>
<h3>The other audience: colleagues and coworkers</h3>
<blockquote><p>Always code as if the guy who ends up maintaining your code is a violent
psychopath who knows where you live.</p>
<ul>
<li>Martin Golding</li>
</ul>
</blockquote>
<p>As I touched on earlier, there's a similarity between the 'other'
audience and the reflexive. The primary distinction is drawn around the
proximity to the source. The other does not have the advantage of having
authored the code, and therefore doesn't have the native's understanding
of the underlying logical organization of the source. This disadvantage
can be overcome via composing in such a manner that the meaning is
emergent from the design. Even if it's too complex to be obvious, good
documentation can address this particular deficiency.</p>
<p>Ultimately, much of software design is about modeling. Software that
solves a particular problem should emulate the nature of the challenge
it's attempting to address. If this can be achieved, it's significantly
easier for those who understand the problem to figure out how the
software works. Therefore, good design can help improve the
effectiveness of a given piece of source to communicate its intent.
Along a similar vector, if the design is similar to code that solves a
particular issue, it's easier to understand. As an example, a friend
recently asked for feedback about an interface that he'd designed. It
loaded a save game file for StarCraft 2. This is what he came up with:</p>
<pre><code>replay_file = File.new("spec/fixtures/1v1-game1.sc2replay")
@replay = SC2Refinery::Parser.parse(replay_file)
</code></pre>
<p>However, Ruby already has several kinds of code in its standard library
that loads some information from disk and parses it into some kind of
data structure that you can use in your program. The JSON, YAML, and
Marshall classes already use a set of methods to import and export data,
and they're named <code>load</code> and <code>dump</code>, and they're part of the class
directly. Also, in this case, the user of the code shouldn't need to
deal with the creation of a file, since it's unreasonable to assume that
a game replay would come from any other source. Therefore, after some
discussion, he adopted the following interface instead:</p>
<pre><code>@replay = SC2Refinery.load("spec/fixtures/1v1-game1.sc2replay")
</code></pre>
<p>This is much nicer to use, and is much simpler. While it may not seem
like a whole lot, when rules like this are applied across an entire
codebase, they can significantly increase understanding. Multiple
reductions of mental overhead add up quickly.</p>
<p>My new favorite trick for adding a little bit of modeling that
significantly reduces overhead for the user is the Presenter Pattern.
Jeff Casimir demonstrated this very clearly in his presentation at
RailsConf 2011, "<a href="http://dl.dropbox.com/u/69001/Fat%20Models%20Aren%27t%20Enough%20-%20RailsConf.pdf">Fat Models Aren't
Enough</a>".
Here's a slightly modified example. Imagine that we have a system that
manages students, and we'd like to display a report card for them. We
might start with some code that looks like this:</p>
<pre><code>student = Student.find(options[:student_id])
term = Term.find(options[:term_id])
report_type = ReportType.find(options[:report_type])
puts "#{student.last_name}, #{student.first_name}"
puts "#{report_type.report_title} for #{term.start_date} to #{term.end_date}"
student.courses.each do |course|
course_report = student.report_data_for_course(course)
puts course_report.to_s
end
</code></pre>
<p>Honestly, until this past week, this is the exact code that I would have
written. But it turns out that we can do better. Basically, we're
displaying some information that comes from a combination of three
different objects. If we think about it some more, we're really trying
to display a report card. So let's make an object that represents the
card, and delegates to its sub-objects. It will then know how to display
itself.</p>
<pre><code>class ReportCard
delegate :start_date, :end_date, :to =&gt; :term
delegate :first_name, :last_name, :courses, :report_data_for_course, :to =&gt; :student
delegate :report_title, :to =&gt; :report_type
def initialize(params)
@student = Student.find params[:student_id]
@term = Term.find params[:term_id]
@report_type = ReportType.find params[:report_type_id]
end
def student_name
[last_name, first_name].join(", ")
end
def title
"#{report_title} for #{start_date} to #{end_date}"
end
def course_reports
out = ""
courses.each do |course|
out += report_data_for_course(course)
end
out
end
end
</code></pre>
<p>Now, this is a lot of code. However, as you can see, it's all focused on
composing the information and exposing an interface that makes sense for
a report card. Using it is super easy:</p>
<pre><code>report = ReportCard.new(options)
puts report.student_name
puts report.title
puts report.course_reports
</code></pre>
<p>Bam! It's incredibly obvious. This code is much more clear than before.
We'll see if I'm still as hot on this pattern as I am now in a few
months, but I feel the extra object adds a significant amount of
clarity.</p>
<p>If the model is too hard to create, or if additional clarity is needed,
documentation in the form of comments can also help to improve the
understanding of the 'other' audience. Comments can be a difficult form
of prose to write, because they need to be written at the correct level
of abstraction. If they simply repeat what the code does, they're
useless, and if they're too high-level, certain details and semantics
may not be made clear.</p>
<p>Individual bits of code can also be made more clear by developing a
narrative within any particular method that's being written. Telling a
story with code may not be something you've considered before, but it's
really about maintaining a proper flow in the actions your code is
taking. For example, if there's a bunch of error handling strewn about
inside of a method, it's less clear than bunching all of the error
handling near the end. Most code should be an act in three parts: input,
processing, and output. If these three parts are mixed together, it can
appear much more complicated.</p>
<h3>The forgotten audience: end-users</h3>
<blockquote><p>If I asked my customers what they wanted, they'd have told me, "A
faster horse."</p>
<ul>
<li>Henry Ford</li>
</ul>
</blockquote>
<p>In the end, all software is used by someone. Use-value is the driving
force of virtually all code. Code that doesn't do anything may be making
some kind of important philosophical statement, but isn't really the
sort that I'm talking about.</p>
<p>The introduction of a user imposes significant restrictions upon the way
that code is composed. End-users do not need to understand the code
itself, but they do need to be able to understand its external
interfaces. These needs place an imposition on the way that the code
needs to be written, because it <em>must</em> address this issue of interface.
Sometimes, interface requirements can create a burden on the internal
implementation. Needing to support certain behaviors and forms can
create complexity for an implementor.</p>
<p>Documentation created for end users must be completely different than
that which is created for those inspecting the code itself. Most
end-users will not be literate in the arts of software development, and
so approach the software object in an entirely different way than those
who write code do. Yet, the same semantics must be passed on to them,
but at a higher level. There's a strong movement within the community to
start designing software with this kind of end-user documentation in
mind, called <a href="http://tom.preston-werner.com/2010/08/23/readme-driven-development.html">README driven development</a>.
There are advantages to thinking on this level when beginning, but a
nice effect of doing it first is that you can ensure it gets done. A
surprising amount of software has poor documentation for its users,
because it's created after the software is finished, and at that time
there's intense pressure to ship it out the door. Writing down
information for the end user first ensures that it's done properly, that
all development works in accordance with the documentation, and that all
of the use-cases for an end-user have been thought of and are being
addressed.</p>
</content>
</entry>
<entry>
<title>The next iteration of my blog</title>
<link href="http://blog.steveklabnik.com/2011/05/12/the-next-iteration-of-my-blog.html"/>
<updated>2011-05-12T00:00:00-04:00</updated>
<id>http://blog.steveklabnik.com/2011/05/12/the-next-iteration-of-my-blog</id>
<content type="html"><p>Well well well, some things never change. Long ago, I hosted my own
blog, and here we are again. I've moved everything over to Jekyll, if
that means anything to you. You can now <a href="https://github.com/steveklabnik/blog">look at my blog on
GitHub</a>. Big thanks to <a href="http://www.jstorimer.com/2009/12/29/jekyll-on-heroku.html">this
article</a> for
lots of help and pointers with final deployment stuff, and <a href="http://mikeferrier.ca/2011/04/29/blogging-with-jekyll-haml-sass-and-jammit/">this one</a> for haml and sass and stuff. Yay!</p>
<h2>New-ish beginnings</h2>
<p>So why'd I do this? Well, this is just part of moving more towards
hosting all of my own services, and not relying on services that others
provide. This isn't some sort of argument over individualism vs.
collectivism, it's more about <a href="http://nomoresharecropping.org/">No More Sharecropping</a>.</p>
<p>I'm still relying on people for hosting, of course. Nobody is 100%
removed, but with my own backup of everything, I'm in total control
here. It's really minimal work to keep this going, and only a few hours
of setup to move everything over.</p>
<h2>A small change in focus, too</h2>
<p>I'm also going to stop bitching about politics so often, and try to be
more constructive in general. I have a lot to say about this new
humanities angle that my life has taken as of late. Hence, I've changed
the title of my blog. And you can expect more posts along those lines.
More about books, more about art and code, less whining. One may think
I'm maturing or something...</p>
</content>
</entry>
<entry>
<title>Contributing to Ruby's Documentation</title>
<link href="http://blog.steveklabnik.com/2011/05/10/contributing-to-ruby-s-documentation.html"/>
<updated>2011-05-10T00:00:00-04:00</updated>
<id>http://blog.steveklabnik.com/2011/05/10/contributing-to-ruby-s-documentation</id>
<content type="html"><p>Ruby 1.9.3 is coming out soon! <a href="http://blog.segment7.net/2011/05/09/ruby-1-9-3-documentation-challenge">drbrain has challenged the Ruby community to
improve its documentation</a>, but some people were asking about how to do so.
So I made a video!</p>
<p>Some small errata: drbrain has informed me that he should edit the Changelog,
not me. So don't do that. :)</p>
<iframe src="http://player.vimeo.com/video/23522731?title=0&amp;byline=0&amp;portrait=0" width="400" height="300" frameborder="0"></iframe>
<p><a href="http://vimeo.com/23522731">How to contribute to Ruby's documentation.</a> from <a href="http://vimeo.com/steveklabnik">Steve Klabnik</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
<p>If you don't want to watch me talk about it, here's the same info, in text:</p>
<p>Getting the Ruby source is pretty easy. You can find it on GitHub, here:
<a href="http://github.com/ruby/ruby">http://github.com/ruby/ruby</a> . Click the "fork" button and clone down your
own fork:</p>
<pre><code>$ git clone git@github.com:YOURUSERNAME/ruby.git
</code></pre>
<p>After that's done, type <code>cd ruby</code> and add the main project as an upstream. This will
let you keep up-to-date with the latest changes:</p>
<pre><code>$ git remote add upstream https://github.com/ruby/ruby.git
$ git fetch upstream
</code></pre>
<p>Okay! Now that you're all set up, poke around and find something that needs
documented. I like to just look through the source, but you can also look
<a href="http://segment7.net/projects/ruby/documentation_coverage.txt">here</a> for a list of things that have no docs. Documentation is written in
rdoc, and I'd check the recent commits that drbrain has been making to guide
you in style. <a href="https://github.com/ruby/ruby/commit/071a678a156dde974d8e470b659c89cb02b07b3b">This commit</a>, for example, is a pretty good template. You
can also check out the formatting guides <a href="http://rdoc.rubyforge.org/RDoc/Markup.html">here</a>. There's also <a href="http://rdoc.rubyforge.org/RDoc/Parser/Ruby.html">this</a>
which explains some directives for .rb files and <a href="http://rdoc.rubyforge.org/RDoc/Parser/C.html">this</a> which handles
directives for .c files.</p>
<p>Now that you've made a change to the documentation, you can regenerate the
docs by using rdoc. First, grab the latest version from rubygems:</p>
<p> $ gem install rdoc</p>
<p>Always best to have the latest tools. Now do this to generate the docs:</p>
<pre><code>$ rdoc --o tmpdoc lib/rss*
</code></pre>
<p>I'm passing it in an output directory with op, since the doc directory is not
an rdoc directory. rdoc will complain and refuse to overwrite those files,
which is a good thing. I'm also passing in a pattern of what to compile
documentation for, compiling all of it takes a few minutes! In this case, I
chose to document the rss library.</p>
<p>Now you have a website in rdocout. Open up its index.html, and poke around for
what you've changed. If it all looks good, you're ready to make a patch!</p>
<pre><code>$ rm -r rdocout
$ git add .
$ git commit -m "adding documentation for $SOMETHING"
</code></pre>
<p>Now, you have two options here. One is to simply push the change up to GitHub,
and make a pull request.</p>
<pre><code>$ git push origin
</code></pre>
<p>... aaand pull request. The core Ruby development doesn't really happen on
GitHub though, and so your patch may take a while to get included. If you
really want to do it right, submit a patch to RedMine. We'll use git to make
this patch:</p>
<pre><code>$ git format-patch HEAD~1
</code></pre>
<p>This says "make a patch out of the last commit." It'll tell you a file name,
it should start with 000.</p>
<p>Now, sign up for the Ruby RedMine <a href="http://redmine.ruby-lang.org/account/register">here</a>. Once you've clicked the
confirmation email, <a href="http://redmine.ruby-lang.org/projects/ruby-19/issues/new">open a new ticket</a>, and assign it to Eric Hodel,
category DOC, and give it your Ruby version, even though it's not a big deal
here. Click 'choose file' and pick your patch, then 'create and continue' and
BAM! You're done!</p>
<p>Let's all pitch in and make this the best documented Ruby release ever! In
writing documentation, you might even find some things that you'd like to help
improve. ;)</p>
</content>
</entry>
<entry>
<title>The first week of rstat.us: Users, Press, Scaling, oh my!</title>
<link href="http://blog.steveklabnik.com/2011/03/30/the-first-week-of-rstat-us-users-press-scaling-oh-my.html"/>
<updated>2011-03-30T00:00:00-04:00</updated>
<id>http://blog.steveklabnik.com/2011/03/30/the-first-week-of-rstat-us-users-press-scaling-oh-my</id>
<content type="html"><p>Hey everyone. A lot of people have been asking me about <a href="http://rstat.us">rstat.us</a> lately,
so I figured I'd tell a little bit of the story as it's gone down so far.</p>
<h2>Stats</h2>
<p>First, here's some numbers:</p>
<ul>
<li>Users: 4553</li>
<li>Uniques: 25,000</li>
<li>Pageviews: 119,385</li>
<li>Pages/visit: 4.77</li>
<li>Statuses posted: 9387</li>
</ul>
<p>Here's some fun info: stats on statuses by language:</p>
<ul>
<li>german 118</li>
<li>russian 1355</li>
<li>none 97 &lt;- ha!</li>
<li>english 4836</li>
<li>spanish 1412</li>
<li>dutch 98</li>
<li>french 1155</li>
<li>portuguese 272</li>
<li>farsi 66</li>
<li>pinyin 1</li>
</ul>
<h2>Code</h2>
<p>Lines, by committer:</p>
<ul>
<li>28 AndrewVos</li>
<li>124 BRIMIL01</li>
<li>6 Blaine Cook</li>
<li>107 Brendan Taylor</li>
<li>924 Brian Miller</li>
<li>45 Caley Woods</li>
<li>162 Carol Nichols</li>
<li>20 Claudio Perez Gamayo</li>
<li>1347 Dominic Dagradi</li>
<li>4 James Larkby-Lahet</li>
<li>99 Jorge H. Cuadrado</li>
<li>258 Kat Hagan</li>
<li>10 Lauren Voswinkel</li>
<li>143 LindseyB</li>
<li>16 MenTaLguY</li>
<li>3 Michael Stevens</li>
<li>3 Murilo Santana</li>
<li>10 Nate Good</li>
<li>1 Peter Aronoff</li>
<li>24 Shebanian</li>
<li>44 Stephen Paul Weber</li>
<li>1409 Steve Klabnik</li>
<li>8 Tony Arcieri</li>
<li>478 Zachary Scott</li>
<li>104 burningTyger</li>
<li>28 james cook</li>
<li>56 kat</li>
<li>200 wilkie</li>
<li>10 wolfwood</li>
</ul>
<p>Also, wilkie has a lot more code in the 3 gems that we build off of, for our
ostatus implementation.</p>
<p>That makes for 29 unique committers. These stats were generated by git-blame.</p>
<p>Just over 200 pull requests</p>
<p>872 commits</p>
<h2>The deal with Heroku</h2>
<p>Crazy! Such good stuff. I'm really excited as to how it's going, but there
were a few rocky points along the way as well. Some people saw me tweeting in
frustration with Heroku, so here's the skinny:</p>
<p>On Sunday, for some reason, our 3 line app.js file, as well as our
favicon.ico, started to take 60 seconds to respond. This meant that a dyno was
getting tied up, and since Heroku changed the way their mesh works, they kept
routing requests to these screwed up dynos. This caused a rash of 500 errors,
and I frantically filed a support ticket. This was the first time I'd had a
paid app on Heroku, and they've always been fantastic. The Hackety Hack site
was on the free account, and performed beautifully, with similar traffic.</p>
<p>What it boils down to is this, though: Heroku took about 22 hours to respond
to my support ticket, in any way. Not like "we're looking at it, but it's
Sunday, so it'll take a while." Crickets. Meanwhile, the errors kept
happening. Eventually, I heard something from them, where they pretty much
said 'I see other errors, try fixing those.' with no response on the actual
root cause. I got an email from a Level2 person who promised to investigate
and escalate, but by now, I still haven't heard.</p>
<p>I also had a smaller issue with MongoHQ. To their credit, I heard back Sunday
night, and the issue with them was an annoyance, not a showstopper. I ended up
hearing from the CEO, who ended up following up with me multiple times, and in
a pretty timely fashion.</p>
<p>So, we moved our hosting away from Heroku and onto Duostack. Now, full
disclosure: I'm friends with the guys from DuoStack. That said, they took care
of me. I found a small bug in their platform when deploying the app, but
everything's gone really well. Bunches of users have commented on how fast the
site is now, and I've been really happy with it so far. We'll see how it goes.</p>
<h2>The Future</h2>
<p>Anyway, here's what's next for <a href="http://rstat.us">rstat.us</a>: The biggest thing is getting to
100% ostatus compliance. We spent lots of time this week getting screwed over
by a bug in Google's hub implementation, but now that it's all taken care of
now. While we work on that, we're also getting ready to deploy a statusnet
compliant API, so people can use statusnet clients on mobile and desktop. This
is huge for me, as I'm really missing notifications.</p>
<p>Other than that, just keep using it! Tell your friends! If you code, come join
us on the IRC (#rstatus on freenode), and help file bugs and patch them!</p>
</content>
</entry>
<entry>
<title>Announcing rstat.us</title>
<link href="http://blog.steveklabnik.com/2011/03/23/announcing-rstat-us.html"/>
<updated>2011-03-23T00:00:00-04:00</updated>
<id>http://blog.steveklabnik.com/2011/03/23/announcing-rstat-us</id>
<content type="html"><p>Whew.</p>
<p>If you've been <a href="http://twitter.com/steveklabnik">following me on Twitter</a> at all lately, you'll know that
I've been working hard on a new project lately. Tonight, even though it's
late, I'm finally getting it out there. Please welcome <a href="http://rstat.us/">http://rstat.us/</a>
to the world! (as soon as the DNS updates. ;) )</p>
<p><a href="http://rstat.us">rstat.us</a> is a micro-blogging service, just like Twitter. There's one big
difference, though: it is distributed. Oh, and it's 100% open source. So two
things. It's also integrated with Facebook and Twitter, so you can just log in
with either of those accounts, and it'll syndicate your posts. Well, just to
Twitter right now, but we're getting there.</p>
<p>Here's the other cool thing: Want to own your data? You can actually <a href="http://github.com/hotsh/rstat.us">get the
code</a> and run a copy yourself! But you won't get left out: you can follow
anyone else that uses the <a href="http://ostatus.org/">ostatus</a> protocol, like <a href="http://identi.ca/">http://identi.ca/</a>,
and it'll Just Work. You just have to grab the URL to their feed, put it in,
and it's all good! But you probably shouldn't do that yet. We're still working
on some features.</p>
<p><a href="http://rstat.us">rstat.us</a> is still very much alpha quality. 7 or 8 of my best friends and
I have been fighting off sleep, food, and tests for the last two weeks to put
this together. Please <a href="http://rstat.us/">give it a try</a> and let me know what you think, tell
me if you can break it, or anything else that's particularly interesting. If
you're the coding type, please check out the <a href="http://github.com/hotsh/rstat.us/wiki">wiki</a> for a big old list of
stuff we'd like to do.</p>
<p>Oh, and of course, you should <a href="http://rstat.us/users/steveklabnik">follow me on rstat.us</a>.</p>
</content>
</entry>
<entry>
<title>Did you hear? I'm Ruby Mendicant University's first Visiting Teacher</title>
<link href="http://blog.steveklabnik.com/2011/03/18/did-you-hear-i-m-ruby-mendicant-university-s-first-visiting-teacher.html"/>
<updated>2011-03-18T00:00:00-04:00</updated>
<id>http://blog.steveklabnik.com/2011/03/18/did-you-hear-i-m-ruby-mendicant-university-s-first-visiting-teacher</id>
<content type="html"><p>I've heard <a href="http://university.rubymendicant.com/">Ruby Mendicant University</a> (also known as RMU, not to confuse
you Robert Morris alums!) described as "the best kept secret of the Ruby
community." High praise, indeed. If you haven't heard about RMU before, check
out this presentation by Andrew Cox: </p>
<p>TL;DR: RMU is a free, online 'unversity' from Gregory Brown, author of 'Ruby
Best Practices.' You enter an intermediate Rubyist, and you exit an expert. </p>
<p>Anyway, RMU recently announced that <a href="http://university.rubymendicant.com/changelog/visiting-teacher-2011-t2-steve-klabnik">I'll be their first visiting teacher</a>.
Basically, I'll be hanging out, giving advice, and just generally being even
more accessible to RMU students than I already am. Greg and I have talked a
lot about education, Ruby, and a lot of other things... between Hackety's
'nothing to intermediate' and RMU's 'intermediate to expert' approaches to
learning, anyone wanting to get up to speed with Ruby should have no shortage
of resources at their disposal.</p>
<p>If you're feeling like you've got the hang of Ruby, but want to take it to the
next level, <a href="http://university.rubymendicant.com/admissions">applications are open</a>! Hopefully I'll see you there.</p>
</content>
</entry>
<entry>
<title>I'm quitting Hacker News</title>
<link href="http://blog.steveklabnik.com/2011/03/03/i-m-quitting-hacker-news.html"/>
<updated>2011-03-03T00:00:00-05:00</updated>
<id>http://blog.steveklabnik.com/2011/03/03/i-m-quitting-hacker-news</id>
<content type="html"><p>I've been thinking about this post for a while.</p>
<p>I freaking love Hacker News. It's my favorite place on the Internet. It's
incredibly valuable. I have learned so much from my time there. With that
said, I feel like it's taken up too much of my time.</p>
<p>I'm trying to accomplish things. I got accepted to grad school. I'm trying to