Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
3b4b7fc
checkpoint: revolutionize the blog
cowboyd Dec 6, 2024
c615f79
Add blog tags
elrickvm Dec 6, 2024
4b5b67f
Add blog assets
cowboyd Dec 9, 2024
6d88ac0
Migrate WCAG post
cowboyd Dec 9, 2024
a5777f5
Watch the `/blog` path
cowboyd Dec 9, 2024
8e30c7c
clean blog url
cowboyd Dec 9, 2024
c635909
migrate 2006-07-08-learning-javascript-from-the-command-line
cowboyd Dec 9, 2024
af82d4a
fix blog index link
cowboyd Dec 9, 2024
d7db332
migrate live styelsheets
cowboyd Dec 9, 2024
ecd288d
"Taming the Rhino"
cowboyd Dec 9, 2024
208efdb
pair programming
cowboyd Dec 9, 2024
5f76767
fixup cleanup
cowboyd Dec 10, 2024
edb1ac8
fixup 2008-06-05-patiently-waiting-for-javafx-script
cowboyd Dec 10, 2024
7432191
fixup post on Ruby global variables
cowboyd Dec 10, 2024
c8525c0
fix RYE post
cowboyd Dec 10, 2024
d30965c
accessing javascript objects from ruby
cowboyd Dec 10, 2024
9d7d17b
Honoring the command line
cowboyd Dec 10, 2024
72d2954
ruby jenkins
cowboyd Dec 10, 2024
862d7ca
ruby racer is not thread safe
cowboyd Dec 10, 2024
e9a29c9
Bring in jenkins posts from 2011-2012
cowboyd Dec 10, 2024
f13f33a
ruby racer rides again
cowboyd Dec 10, 2024
d9130f2
Bring in ember real talk blog
cowboyd Dec 10, 2024
669ef6b
Ember and the future of the web
cowboyd Dec 10, 2024
48f60fd
programming in the wild west
cowboyd Dec 10, 2024
1d39df5
emberx select update
cowboyd Dec 10, 2024
cec7f9b
functional templating in ember
cowboyd Dec 10, 2024
342adc4
Reactive modelling in Ember
cowboyd Dec 10, 2024
99f33e5
Insider track
cowboyd Dec 10, 2024
5206178
global accessibility awarenes day
cowboyd Dec 10, 2024
67968e7
so you finished a bootcamp
cowboyd Dec 10, 2024
3941898
accessibilit why it matters
cowboyd Dec 10, 2024
2eaa4e0
conjoined triangles of senior development
cowboyd Dec 10, 2024
388baeb
ruby dcamp experienc
cowboyd Dec 10, 2024
2c5ae36
Infinite scroll in react native
cowboyd Dec 10, 2024
fe18562
react native chillest monkey
cowboyd Dec 10, 2024
ab406cd
javascript decorators
cowboyd Dec 10, 2024
847c3ff
CI and IOT
cowboyd Dec 10, 2024
761b639
how healthy is your build
cowboyd Dec 10, 2024
f4a2ed4
quickly build components with storybook
cowboyd Dec 10, 2024
d716691
math is just another framework
cowboyd Dec 10, 2024
f287729
connect slack channel to gitter
cowboyd Dec 10, 2024
c0d2763
big testing in react
cowboyd Dec 10, 2024
cc53eb0
async function functor
cowboyd Dec 10, 2024
c135944
Make latest, recent, and all blog posts available
cowboyd Dec 11, 2024
345b160
Announcing Effection v3
cowboyd Dec 11, 2024
6040e6b
Backstage inner source
cowboyd Dec 11, 2024
70d6576
backstage linting
cowboyd Dec 11, 2024
43e5a58
Deno is the best tool to publish to NPM
cowboyd Dec 11, 2024
63ff0af
seven ways to a single glass pane
cowboyd Dec 11, 2024
7515f28
dynmaci github actions
cowboyd Dec 11, 2024
6bac8e3
ingestion testing backstage part 2
cowboyd Dec 11, 2024
e4ff775
Deno is blazing fast for humans
cowboyd Dec 11, 2024
92b4d99
what is backstage
cowboyd Dec 11, 2024
dcc1537
backstage entity provider
cowboyd Dec 11, 2024
ee9b6fb
backstage ingestion testing
cowboyd Dec 11, 2024
5799403
plugin interactors
cowboyd Dec 11, 2024
cf48ad2
Announcing graphgen
cowboyd Dec 11, 2024
66b9383
backstage components
cowboyd Dec 11, 2024
a106af0
semver or calver
cowboyd Dec 11, 2024
368a7ff
what is DX?
cowboyd Dec 11, 2024
b7ddcbf
backstage vscode containers
cowboyd Dec 11, 2024
3ec7ecc
auth0 simulator
cowboyd Dec 11, 2024
9d78630
effection when async await is not enough
cowboyd Dec 11, 2024
295edf8
interactors ally
cowboyd Dec 11, 2024
0e9f918
avoid cloud churn with backstage
cowboyd Dec 11, 2024
56508ec
helping designers and developres with storybook
cowboyd Dec 11, 2024
9dc8c8f
there and back again
cowboyd Dec 11, 2024
4327cfb
kubernetes dip your toes in
cowboyd Dec 11, 2024
0b0c4d3
default branch names
cowboyd Dec 11, 2024
e30ce0e
mirage serializers
cowboyd Dec 11, 2024
c952d96
decouple teams through simulation
cowboyd Dec 11, 2024
e70f172
bigtest interactors
cowboyd Dec 11, 2024
8b1e940
pull request deep dive
cowboyd Dec 11, 2024
b906766
triple threat to testing reliability
cowboyd Dec 11, 2024
08fdbd2
good pull request description
cowboyd Dec 11, 2024
9ee6a87
triple threat to testing part 1 speed
cowboyd Dec 11, 2024
042b28f
bluetooth simulation case study
cowboyd Dec 11, 2024
c5ed255
family tree with microstates
cowboyd Dec 11, 2024
17ac7d5
Use append instead of object assign
cowboyd Dec 11, 2024
6475abc
kubernetes for the kubernewbie
cowboyd Dec 11, 2024
210516c
jsconf 2018 recap
cowboyd Dec 11, 2024
9c1cf28
Make sure blog is loaded as a directory
cowboyd Dec 12, 2024
ebcda82
Put every blog post in its own completely self-contained directory
cowboyd Dec 12, 2024
e0b9737
Put every blog post in its own completely self-contained directory
cowboyd Dec 12, 2024
f792602
Add get posts by tag route
cowboyd Dec 12, 2024
53dea2d
cleanup organization
cowboyd Dec 12, 2024
4a89da3
fixup internal section links
cowboyd Dec 13, 2024
319faba
Add styles to blog index
elrickvm Dec 20, 2024
c3122d8
Decrease font size on list blog items
elrickvm Dec 20, 2024
d9aa4f7
Adjust Latest Blog Image Index Styles
elrickvm Dec 23, 2024
3c50d94
Move Blog Title to top and image underneath
elrickvm Dec 23, 2024
1687e7b
Adjust blog font size
elrickvm Dec 23, 2024
8dd6e6f
Organize blog post list into three columns
elrickvm Jan 24, 2025
7f1f696
Fix image spacing
elrickvm Jan 24, 2025
5a5be2e
Remove console.logs
elrickvm Jan 24, 2025
7d6574e
Fix missing images
elrickvm Jan 24, 2025
464e039
Increase font size and weight of titles
elrickvm Jan 24, 2025
85b1d7f
Remove console.log
elrickvm Jan 24, 2025
424380b
Add Author Images to all post
elrickvm Jan 27, 2025
2e0a980
Refactor: Extract reusable author logic and component
elrickvm Jan 27, 2025
e3e0938
Remove unused code
elrickvm Jan 27, 2025
cebcaf1
Add author Images to Individual Blog Post Route
elrickvm Jan 27, 2025
4f9fed4
Refactor: Centralize author image logic and configuration
elrickvm Jan 27, 2025
25ca614
Upgrade revolution
cowboyd Jan 27, 2025
1b150f0
Fix image for conjoined triangles post
cowboyd Jan 28, 2025
a72ba00
Fix image alignment and spacing
elrickvm Jan 28, 2025
48912b6
Refactor: Remove unused code for author images
elrickvm Jan 28, 2025
393d64d
Fix tag image scaling
elrickvm Jan 28, 2025
e61fc05
Merge branch 'revolutionize-blog' of github.com:thefrontside/frontsid…
elrickvm Jan 28, 2025
b244b50
Update Labels on post index
elrickvm Jan 28, 2025
cc10bf1
Add border
elrickvm Jan 28, 2025
4d3f26a
Get rid of the "recent three" section
cowboyd Jan 28, 2025
5f0a997
Fix tags that have spaces in them.
cowboyd Jan 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Binary file added assets/img/authors/charles.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/authors/elrick.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/authors/jacob.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/authors/jeffrey.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/authors/jorge.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/authors/min.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/authors/paul.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/authors/rachelle.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/authors/taras.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
492 changes: 492 additions & 0 deletions assets/prism-atom-one-dark.css

Large diffs are not rendered by default.

62 changes: 62 additions & 0 deletions blog/2006-07-08-learning-javascript-from-the-command-line/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: Learning Javascript from the Command Line
author: Charles Lowell
tags:
- javascript
---

<p>In the [Drunk and Retired Podcast](http://www.drunkandretired/podcast), [episode 59](http://www.drunkandretired.com/2006/07/08/drunkandretiredcom-podcast-episode-59-lightside-v-darkside-plus-learning-javascript-the-language-not-the-javascript-the-browser-scriptus/#comments) I spoke about learning your way around javascript the language independently from the browser, and how you can use the command line tools that come with the various javascript engines to interactively explore the javascript runtime.</p>

<p>When most folks think about javascript, they think about scripts that they embed into their web pages, but the truth is that it is a general-purpose programming language <em>that has absolutely nothing to do with HTML</em>. In fact, the javascript runtime is so orthogonal to other web browser functionality, that mozilla offers the javascript interpreter that it uses in Firefox and friends as a [completely separate download](http://www.mozilla.org/js/spidermonkey). It's available as both .deb or .rpm package, and just to show it: Here's the wonderful hello world program, as entered into the shell.</p>

```
cowboyd@subzero:~$ js
js> alert('hello world')
1: ReferenceError: alert is not defined
js>
```

<p>OK, so I boobie-trapped that example in an attempt to beat the point I've been making to death. It's an error because `alert()` isn't actually part of javascript. In the context with which we're familiar(DHTML), it's a function that's <em>defined by the browser</em>. Of course, it just so happens that every browser implements `alert()` to behave in almost exactly the same way, but the function itself has nothing to do with the javascript core. Implementing our own version of alert is simple enough though.</p>

```
js> var alert = function(message) { print(message)}
js> alert('hello world')
hello world
js>
```

<p>Personally, I love the command line because it let's you dig your fingers deep into the computer's brain and, by pushing its buttons directly, see what's going to work and what isn't. Every time I have a question about how the javascript interpreter is going to behave, I don't look up the spec, or write something into my programs that I'm not sure how it will work. Instead, I fire up my trusty interpreter to discover <em>empirically</em> how the system works. Need to know if a RegExp is going to match? Don't guess. Ask the interpreter.</p>
```
js> "foo".match(/bar/)
null
js> "foo".match(/oo/)
oo
js> "foo".match(/oo$/)
oo
js>
```
<p>Wonder what the built-in "constructor" property of an object is? The runtime can tell you. It's his business after all.</p>

```
js> function A() {}
js> var a = new A()
js> var o = new Object()
js> a.constructor

function A() {
}

js> o.constructor

function Object() {
[native code]
}

js> o.constructor == Object
true
js> a.constructor == A
true
js>
```

<p>Sure, you could write an in-browser script to do all this and throw output at yourself in the form of alerts, but the beauty of the javascript command line is that you can collapse the whole edit-save-reload-alert scripting cycle into a single step; type in the next line and see what happens. It's that super-tight feedback which let's you learn that much faster.</p>
71 changes: 71 additions & 0 deletions blog/2006-07-15-live-stylesheets/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
title: Live Stylesheets
author: Charles Lowell
tags:
- dhtml
- javascript
---

<p>Even after working with DTML for over a year, I'm still constantly astounded by how <em>dynamic it actually is</em>. The most important thing to keep in the back of your head as a DHTML programmer is that the same mechanisms used by the browser to build an HTML document at load time are available to your in-page scripts. So, really, the static loading of your pages when you access a url is just the HTML parser invoking the same methods on the same objects that are available to your javascript code.</p>

<p>Take this static HTML code:</p>

```html
<html>
<body><div id="foo">This is my div</div></body>
</html>

```

<p>The same result can be achieved dynamically:</p>
```html
<html>
<body onload="addFoo()">
<script type="text/javascript">
function addFoo() {
var foo = document.createElement('div')
foo.id = "foo"
var fooContent = document.createTextNode("This is my div")
foo.appendChild(fooContent)
document.body.appendChild(foo)
}
</script>
</body>
</html>
```

<p>Nothing mind-blowing there; indeed, this technique is the cornerstone of DHTML. But it takes awhile to let it sink in to the point where using it is one of your first strategies to solving a problem. Specifically, you can use it not only to dynamically change layout-related HTML elements (span, div, ul, table, et al...), but also to create/modify <em>behavioral elements</em>(link, script, meta, etc...)</p>

<p>That said, I was recently trying to create a CSS stylesheet at runtime, and enable it so that its rules would be active in the page. At first, I was trying to use the <a href="http://www.w3.org/TR/DOM-Level-2-Style/ecma-script-binding.html">W3C DOM CSS interface</a>, the idea being to create a stylesheet object, add a bunch of rules to it corresponding to the rules that I wanted, and then put it into the stylesheets array. Unfortunately, doing this in a cross-platform way is <a href="http://www.quirksmode.org/dom/w3c_css.html">borderline impossible</a>. After pounding my head against that for awhile and getting nowhere, I figured, "why not just create the whole thing as a top-level html element, and let the browser just take it away from there?" The basic strategy is this: create a <code>style</code> DOM Element dynamically, add text content to it representing the actual stylesheet, and then pop it into the HTML DOM. With a few caveats, it works like a charm. The browser parses the text as CSS, and links in into the live cascade.</p>

<p>I mentioned caveats.. well, of course there are the obligatory cross-browser compatibility issues to be aware of:</p>

<ul>
<li>In Internet Explorer, you can't just append a Text Node to a Style element, you have to use some trickery to get it to work.</li>
<li>KHTML &amp; Safari do not honor <code>style</code> elements that are not contained in the HEAD element of the document.</li>
<li>While IE and Mozilla always create a HEAD element for you if one doesn't exist, Opera and KHTML do not.</li>
<li>While Opera will honor a dynamically created HEAD element, KHTML will not. (That's a bug in KHTML as far as I'm concerned as it violates the DHTML principle that I've been talking about.)</li>
</ul>

<p>All in all, they're nothing to worry about and do not stand in the way of the fundamental technique. I've created a demo page showing this code in action. As a nice side effect, it works as quick way of playing around with CSS properties and how they effect the styling of elements.</p>

> ⚠️ NOTE: The demo site has been lost to posterity, but we can assure you that it was really, really cool.
> We apologize for any inconvenience this may have caused.
>
> --The Management

<p>Here is the source snippet implementing the technique I've described here:</p>

```javascript
var style = document.createElement('style')
style.setAttribute('type', 'text/css')

var cssText = $('cssText').value
if (style.styleSheet) { //IE only
style.styleSheet.cssText = cssText
} else {
//for some reason this fails in IE.
var text = document.createTextNode(cssText)
style.appendChild(text)
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: Taming the Rhino
author: Charles Lowell
tags:
- javascript
---

<p>I recently [described](learning-javascript-from-the-command-line) how to use the one of the [freely available shells](http://www.mozilla.org/js/) as a great way to explore your javascript runtime. There are two implementations of the javascript interpreter sponsored by the Mozilla project, [Spider Monkey](http://www.mozilla.org/js/spidermonkey) an interpreter implemented in C, and [Rhino](http://www.mozilla.org/rhino/), an interpreter implemented in Java. With respect to the javascript runtime itself, these two implementations are almost identical, and so what works in one, will generally work in the other. They diverge, however, when it comes to embedding objects and functions that are implemented in a language other than javascript. Naturally, Spidermonkey is better suited for embedding objects implemented in C, while Rhino excels at embedding objects implemented in Java.</p>

<p>What exactly is "embedding" an object implemented in Java? If you don't know what this means already, I could try to describe it to you, but why not show it live and in the flesh with the Rhino command line? That's the exploratory technique that I find so valuable.</p>

```
cowboyd@subzero:~$ java -classpath js.jar org.mozilla.javascript.tools.shell.Main
Rhino 1.5 release 5 2004 03 25
js> var javaString = new java.lang.String("Hello World")
js> javaString.hashCode()
-862545276
js> javaString.startsWith("Hello")
true
js> javaString.startsWith("World")
false
js> var jsString = new String("Hello World")
js> jsString.startsWith("Hello")
js: "<stdin>", line 5: uncaught JavaScript exception: TypeError: startsWith is not a function. (<stdin>; line 5)
js>
```

As you can see, javaString is a reference to an actual `java.lang.String` object, and has access to all the methods of that class, many of which are not contained in the native javascript `String`.

Embedding goes two ways. Not only can you instantiate and use java objects from javascript, but you can also pass in javascript objects as parameters to java methods. You can even extend objects and implement interfaces in javascript! Once again, the command line shows this in action. In this example, we'll implement the `java.lang.Runnable` interface in javascript

```
cowboyd@subzero:~$ java -classpath js.jar org.mozilla.javascript.tools.shell.Main
Rhino 1.5 release 5 2004 03 25
js> var impl = new Object()
js> impl.run = function() {print("Yeah that's right, you better run!")}

function () {
print("Yeah that's right, you better run!");
}

js> var runnable = new java.lang.Runnable(impl)
js> var thread = new java.lang.Thread(runnable)
js> thread.run()
Yeah that's right, you better run!
js>
```

<p>This is all well and good, but that's quite a bit of code to get right the first time! Chances are, if you're just starting out with the Rhino command line, you're not going to have as much luck, especially if you're using it as a tool to learn javascript in the first place, and unfortunately, this is where Rhino comes up <em>way</em> short. Rather than have a forgiving [CLI](http://en.wikipedia.org/wiki/Command_line_interface), Rhino punishes you for every syntactic and semantic error that you make by not collecting command history. Even worse, hitting the up and down arrows result in bizarre character literals output directly to the prompt. You can't even correct a mistake that you've made in the current line you're typing without backspacing all the way to the error, and then re-typing from that point on.</p>

<p>In this example, I'd like to arrow-left so that I can correct my misspelling of "java.lang"</p>

cowboyd@subzero:~$ java -classpath js.jar org.mozilla.javascript.tools.shell.Main
Rhino 1.5 release 5 2004 03 25
js> var r = new java.lng.Runnable(^[[D^[[D^[[D^[[D

<p><strong>Ugh!</strong> Or what happens if the shell didn't take my last command because it was slightly bogus? I'd like to retrieve the command with the up-arrow, edit it a little bit in-place and then try again because after all, it was only <em>slightly</em> bogus. Watch me try and recover from this minor syntax error...</p>

```
cowboyd@subzero:~$ java -classpath /usr/share/java/js.jar org.mozilla.javascript.tools.shell.Main
Rhino 1.5 release 5 2004 03 25
js> var f = function() {print("oops I forgot to close these parens"}
js: "<stdin>", line 29: missing ) after argument list
js: var f = function() {print("oops I forgot to close these parens"}
js: ...............................................................^
js: "<stdin>", line 29: missing } after function body
js: var f = function() {print("oops I forgot to close these parens"}
js: ...............................................................^
js: "<stdin>", line 29: Compilation produced 2 syntax errors.
js>
js> //I know. Up-arrow to the rescue!
js> ^[[A^[[A^[[A^[[A^[[A^[[A //drat, foiled again!
```

<p>These problems are in particularly nasty contraposition to the technique of exploration via the shell which I advocate because the the cost for failure is so expensive. Indeed, what is so wonderful about most modern shells is that the cost for a syntax error is so small. For some reason, the implementors of the Rhino CLI decided to implement their shell with the typical functionality circa 1962.</p>

<p>It's not a problem for me though, thanks to one of my favorite unsung java libraries, [JLine](http://jline.sourceforge.net/). JLine hits a super sweet spot in that it takes somewhere around 0 effort to add loads of standard functionality to your command line interfaces. It seems that no one in the java world bothers with a decent CLI; tragic in my opinion, but probably because it's considered well-understood, non-trivial and therefore tedious. With JLine, building that CLI comes at around 0 cost. What's really cool about JLine is that a program doesn't even need to be written with it. It can transparently intercept the console input for <em>any</em> java program and seamlessly splice on any and all functionality you'd expect from a hot shell: in-place editing, command history, you name it. In a word: <em>perfect</em> for a beast like Rhino.</p>

```
cowboyd@subzero:~$ java -classpath js.jar:jline.jar jline.ConsoleRunner org.mozilla.javascript.tools.shell.Main
Rhino 1.5 release 5 2004 03 25
js> prnt("oops let me try that again")
js: "<stdin>", line 1: uncaught JavaScript exception: ReferenceError: "prnt" is not defined. (<stdin>; line 1)
js> print("oops let me try that again")
oops let me try that again
js> //trust me, that was easy. Just like it should have been in the first place.
js>
```

<p>JLine truly is a healing salve for your chafing CLI woes. Did I mention that it's cross-platform?</p>

<p>While the barrier to entry is extremely low, the path to upgrade is but a mild upward slope. If you do end up wanting nice extras such as TAB-completion or custom key bindings, it has a simple configuration mechanism, and [Java API](http://jline.sourceforge.net/apidocs/index.html) to make the pain of writing custom code as minimal as possible. But that's another bedtime story altogether.</p>

<p>I hope you enjoy JLine with Rhino, or with any other impolite java command lines you may use!</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
title: Trans-Global Pair Programming
author: Charles Lowell
tags:
- proskillz
---

<p>The Frontside Software is a three person company with "offices" in Michigan, Finland, Massachusetts, and New Jersey. We're don't see each other every day, and we're rarely in the same room, but we still do a significant portion of our development work in pairs. Despite many other competing setups, we still do this with the not-so-new, not-so-exciting, yet extremely flexible and reliable [VNC](http://www.realvnc.com/what.html) combined with a voip product like [skype](http://skype.com).</p>

<h3>How it works</h3>
<p>One of us (the driver) runs a vnc server which transmits everything that is rendered on his display to one or more vnc clients (passengers) being run by the other half of the pair. That way, the client can see everything that goes on while the driver is coding, including his code editor, his web browser, his terminal windows, etc... Meanwhile, you've got real-time audio so that you can talk about the work you're doing as you're doing it.</p>

<h3>Is there something better?</h3>
<p>Not yet. We've seen some new collaborative coding tools like [SubEthaEdit](http://www.codingmonkeys.de/subethaedit/) and [Gobby](https://gobby.0x539.de/trac/) come down with some very slick features. Specifically, the updating and syncing of editor state between the two machines is very fast, and effectively coordinates multiple people editing the same document, with as few clashes as possible. The way in which they do this is impressive, but after having given it several abortive attempts as a real solution for remote pair programming, we went back to good old VNC. Here's why:</p>
<ol>
<li><strong>Lack of editing features:</strong> The collaborative editors of today are good at one thing: editing text collaboratively. The problem is that when you're pair-programming, you're not editing text, you're editing code, and code is only a simple sequence of text to a computer. There are lots of editors these days that leverage the semantically rich structure of the documents on which they operate like TextMate, Emacs, Eclipse.... everybody has a favorite, and because your collaborative editor is not your favorite, that means it sucks ;-)</li>
<li><strong>Lack of environment:</strong> Of course, there are a scant few collaborative editing plug-ins for existing IDEs which would seem to address this problem, but adding on another layer, development is about more than just coding. It's about browsing documentation, running servers, invoking build scripts from the command line, and about a million other tiny tasks. In effect, your <em>actual</em> IDE is not just one application, it's your whole computer, and if the only thing being shared is a single app, then it cuts your pair out of a lot of important context. With VNC, everybody sees what's going on all the time. They can see not only the code, but also the running program.</li>
<li><strong>Editing the same document at the same time isn't really helpful anyway</strong>: If you've done much pair-programming, then you realize that the real value doesn't come from having two sets of fingers on the keyboard at the same time. In fact quite the opposite: Both participants are following the thread of development, but one of them is freed entirely from the act of coding so that they can think about high-level architectural issues, or lookup api docs, or google for resources --all in parallel. Having both people pounding on the keyboard actually hinders this dynamic.</li>
<li><strong>VNC is cross platform</strong>: This is a biggie. There are vnc clients and servers for Windows, OSX, and Linux (we code on all three), and they all interoperate with each other. That's a pretty hard feature to top, especially for single-platform apps like SubEthaEdit and Gobby which run on OSX and Linux respectively.</li>
</ol>

<p>About the only drawback to pair programming with VNC is that there can be some fairly significant lag (between 1-4 seconds) depending on network load on either end, but even so, when it comes to <em>actually</em> developing collaboratively, VNC and Skype are our daily tools of choice.</p>

<h3>VNC Clients/servers</h3>
<ul>
<li><strong>OSX client</strong>: [Chicken of the VNC](https://sourceforge.net/projects/cotvnc/)
</li><li><strong>OSX server</strong>: [Vine Server](http://www.redstonesoftware.com/products/vine/server/vineosx/)</li>
<li><strong>Windows/Linux client/server</strong>: [http://www.tightvnc.com/download.html](http://www.tightvnc.com/download.html)</li>
</ul>
Loading
Loading