@@ 33,13 33,17 @@ You may also optionally configure it.
Dependencies
================================================================================
-- Ruby >= 1.8
+- Ruby >= 1.8 (for the Ruby version)
+- `Google Go <http://golang.org>`_ (for the Go version)
- Mercurial >= 1.6 (for versioning)
Usage
################################################################################
-The application follows a simple contract:
+Currently, the Ruby and Go versions differ in behavior. This will be fixed, to
+make the Ruby version behave like the Go version.
+
+The Ruby application follows this contract:
- Any object X may descend from any objects B0, B1, ..., Bn
- X inherits all attributes from all parents in a defined order
@@ 47,6 51,24 @@ The application follows a simple contrac
- X is versioned
- X must not be an ancestor of itself (a config forms a directed, acyclic graph)
- Inheritance is determined at creation time, not at run time
+
+The Go application follows this contract:
+
+- An object X may descend from another object Y. There is only a single
+ direct inheritance, but there may be multiple ancestors
+- The ancestor objects of X may or may not exist
+- X inherits all attributes from all parents
+- X may override any attribute inherited from a parent
+- X is versioned
+
+The Ruby version is entirely encapsulated in the file ``config.rb``; to run it,
+run ``ruby config.rb``, or ``ruby config.rb --help`` for usage instructions.
+
+The Go version must be compiled; run ``gomake`` to compile it -- the output is
+a native executable called ``conv``. Run this to run the server. Run ``conv
+--help`` for usage instructions. Run ``gomake functional`` for the functional
+test suite; run ``gotest`` to run the unit tests.
+
REST API
================================================================================
@@ 116,98 138,6 @@ repo_dir
The path to the version control executable (including the executable name
itself). Currently, only Mercurial is supported.
-
-
-An implementation note
-================================================================================
-
-The original version of this application was written in Ruby, a language that I
-was once extremely well-versed in, but which I haven't used for anything but
-one-off command-line scripts in a few years. It took me about 6 hours to write
-the thing.
-
-Out of curiosity, and since the project was so small, I decided to re-implement
-it in `Go <http://golang.org>`_. This was the second time I'd looked at Go
-syntax; the first was to fix a small benchmark program that was comparing Go to
-`Vala <http://live.gnome.org/Vala>`_, so it really was the first time I'd
-written any Go; I was utterly unfamiliar with the packages. This second version
-took me about 20 hours. That time includes unit tests and a couple of
-refactorings to improve segregation of responsibility; I guesstimate that if I
-performed the same refactoring and writing unit tests for the Ruby code, I could
-probably spend another 6-10 hours -- on the one hand, I know the shape of the
-modules/packages; on the other, writing unit tests always takes a lot of time.
-
-`Cloc <http://cloc.sourceforge.net>`_ tells us this:
-
----------------------------- -------------- ------------ ----------------- ----
-Language files blank comment code
-============================ ============== ============ ================= ====
-Go 7 104 43 482
-Ruby 1 59 55 326
----------------------------- -------------- ------------ ----------------- ----
-
-This excludes unit tests. So here's my (subjective) take on this:
-
-- I'm frankly amazed that the Go LOC is so close to the Ruby LOC (33%
- larger). If I refactored the Ruby code to be more well-structured and
- encapsulated (and unit-testable), that LOC delta would shrink even more.
-- The Ruby program is a single, executable-and-library file. This was
- intentional. I was able to break up the Go code into more files because the
- end artifact would also be a single executable.
-- The Go compiler is wicked, stupid fast. ``gomake`` is nice, in that it uses
- standard Makefiles but provides includes to greatly simplify the Makefiles.
-- The Go unit test package is anemic, providing only the bare minimum of
- functionality.
-- Go has such potential for mixing in, but the language spec disallows it (you
- can only define functions on structures that are within your own package).
-- Even if I were as knowledgeable about Go as I am about Ruby, I'd still have
- been able to whip the Ruby version out faster. On the other hand, the Go
- version is much safer, and I trust that program a *lot* more -- it is, after
- all, type-checked. I guarantee that no matter how much I look at the Ruby
- code, if it runs for any length of time I'll eventually encounter a typing
- error because of a bug in the code.
-- Go has an amazingly useful set of built-in libraries, without being package
- and class bloated (like, say, Java). Although, the crypto package is
- curiously huge.
-- http://golang.org/pkg FTW!
-- Doing system exec stuff is easier in Ruby, but not by a lot.
-
-All in all, Go surprises me; it's concise, easy, encourages good separation of
-concerns, is easy to read, and much more functional in feel than you'd expect
-from looking at the tutorial. At the same time, it has some unfortunate quirks:
-it's (currently) relatively slow for a compiled language, and builds large
-executables; some language constructs are just baffling in their constraints,
-such as ``range`` only being applicable to a small set of built-ins, rather than
-working on some well-defined interface; tail-call optimization is extremely
-limited, which is such a shame for a language as close to being a functional
-language as Go is; and the lack of ability to mix in to extra-package types is
-limiting.
-
-To the first point in my list of Go quirks, I have no doubt that this will
-change rapidly, and Go will catch up; it's a very young language, after all. As
-to the last point, the explanation put forth by the Go developers is, frankly,
-weak. It's the same argument Gosling made about not supporting multiple
-inheritance in Java, which basically boils down to "programmers are stupid, and
-this feature will confuse them." I don't buy it; I'd rather have extra-package
-mix-ins with limitations based on technical merit than none at all.
-
-I've learned that I vastly prefer the cost of slower development time to gain
-reliability and safety, as long as the cost isn't too high. Haskell is even
-safer, but it pushes the boundaries of how much pain I'm willing to endure
-trying to get code to pass through the type checker.
-
-Right now, I'm thinking Go's a keeper. It is more productive than C, more
-reliable than Ruby, easier than Haskell, is superior to Erlang in a whole host
-of ways I won't enumerate here (although, I do like the features that the OTP
-brings to the table, many of which are "killer" features unavailable in any
-other language, which keeps Erlang highly relevant), and is far better than Java
-in terms of simplicity, syntax, typing, threading, native compilation, and
-memory use. Each of these languages surpasses Go in their own ways, but I
-believe that Google has successfully found that sweet spot in a practical
-language that minimizes the annoying attributes and boiler-plate, and provides
-strong typing, resulting in a highly "writeable" language that compiles to
-native executables. We'll see how I feel with a few gross more hours under my
-belt.
Links
@@ 216,3 146,4 @@ Links
* `Project page <http://redmine.germane-software.com/projects/configserver/wiki/Home>`_
* `Status <http://redmine.germane-software.com/projects/configserver/wiki/Status>`_
* `Repository <http://hg.germane-software.com/ConfigServer/summary>`_
+* `Thoughts about Ruby and Go <http://goo.gl/S8IC9>`_