<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Martin Probst</title>
<link href="https://probst.io/blog/feed.xml" rel="self"/>
<link href="https://probst.io/"/>
<id>https://probst.io/</id>
<updated>2026-02-06T03:54:48+00:00</updated>
<author><name>Martin Probst</name></author>
<entry>
<title>AI wrote the compiler, the test suites planned it</title>
<link href="https://probst.io/blog/2026/02/06/ai-wrote-the-compiler-the-test-suites-planned-it/"/>
<id>https://probst.io/blog/2026/02/06/ai-wrote-the-compiler-the-test-suites-planned-it/</id>
<published>2026-02-06T03:54:48+00:00</published>
<updated>2026-02-06T03:54:48+00:00</updated>
<content type="html">&lt;p&gt;Anthropic recently described how a team of Claude agents &lt;a href=&quot;https://www.anthropic.com/engineering/building-c-compiler&quot;&gt;built a C compiler&lt;/a&gt;, presented as a project where they handed the task to the agents and then mostly stepped back: about 100,000 lines of Rust that can build a bootable Linux kernel and pass 99% of most compiler test suites, including GCC&amp;#39;s torture tests.&lt;/p&gt;
&lt;p&gt;But: the agents had access to extremely detailed and comprehensive test suites and execution harnesses, both written by humans, with the harness built specifically for the AI to consume. And they got a working compiler, but no commercial-grade product.&lt;/p&gt;
&lt;p&gt;This is still quite the achievement, don&amp;#39;t get me wrong.&lt;/p&gt;
&lt;p&gt;But I&amp;#39;d expect the test suites to go a long way not just in validating the result, but also in structuring the task. The AI didn&amp;#39;t solve &amp;quot;how do I compile Linux&amp;quot;, but &amp;quot;there&amp;#39;s a test with this description, part of the built-ins suite, to correctly handle GCC&amp;#39;s &lt;code&gt;__attribute__((constructor))&lt;/code&gt; declaration attribute; get the compiler to emit this specific assembly for this input&amp;quot;.&lt;/p&gt;
&lt;p&gt;That is, some of the input wasn&amp;#39;t just what to do, but also how to structure the compiler, how to break the overall goal down into jobs, and how precisely to validate them.&lt;/p&gt;
&lt;p&gt;I think the &amp;quot;mostly walked away&amp;quot; framing could have been more honest about that. I guess &amp;quot;we got Claude to follow along these test suites, until finally getting Linux to compile&amp;quot; is a bit less impressive, though.&lt;/p&gt;
</content>
</entry>
<entry>
<title>Deployment frequency is not a goal</title>
<link href="https://probst.io/blog/2025/09/13/deployment-frequency-is-not-a-goal/"/>
<id>https://probst.io/blog/2025/09/13/deployment-frequency-is-not-a-goal/</id>
<published>2025-09-13T10:11:41+00:00</published>
<updated>2025-09-13T10:11:41+00:00</updated>
<content type="html">&lt;p&gt;Developer productivity efforts like to measure software delivery with the &lt;a href=&quot;https://dora.dev/guides/dora-metrics/&quot;&gt;DORA metrics&lt;/a&gt;, among them deployment frequency and lead time for changes. These metrics are real and useful, but what&amp;#39;s annoying is the common use of deployment frequency as a goal metric.&lt;/p&gt;
&lt;p&gt;Deployment frequency has a hard cut-off, beyond which more frequent deployments aren&amp;#39;t useful, or are even harmful. Monthly releases are a problem. Weekly - or even daily - deployments are fine, as long as they are automated or low toil. Releasing every push is harmful.&lt;/p&gt;
&lt;p&gt;It&amp;#39;s just not beneficial to anyone to deploy every five minutes. It doesn&amp;#39;t meaningfully accelerate delivery (no customer ever wanted that button all of five minutes earlier!). And it&amp;#39;s really harmful for production stability, as it becomes increasingly difficult to attribute breakages to particular releases.&lt;/p&gt;
&lt;p&gt;I&amp;#39;d argue similarly for lead time to production. For a significant product, you want a careful and measured rollout across dev, QA, and then individual canary stages and production clusters. You cannot do meaningful canarying in five minutes, so a shorter lead time to production will be strictly worse (assuming you don&amp;#39;t waste time on manual QA).&lt;/p&gt;
</content>
</entry>
<entry>
<title>Why Go's garbage collector isn't generational</title>
<link href="https://probst.io/blog/2020/02/05/why-gos-garbage-collector-isnt-generational/"/>
<id>https://probst.io/blog/2020/02/05/why-gos-garbage-collector-isnt-generational/</id>
<published>2020-02-05T13:06:50+00:00</published>
<updated>2020-02-05T13:06:50+00:00</updated>
<content type="html">&lt;p&gt;&lt;em&gt;Originally posted as a &lt;a href=&quot;https://news.ycombinator.com/item?id=22246379&quot;&gt;comment on Hacker News&lt;/a&gt; on &lt;a href=&quot;https://blog.discordapp.com/why-discord-is-switching-from-go-to-rust-a190bbca2b1f&quot;&gt;Why Discord is switching from Go to Rust&lt;/a&gt;. Another commenter explained Discord&amp;#39;s garbage collection problems like this:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The problem is that garbage collectors are optimized for applications that mostly have short-lived objects, and a small amount of long-lived objects.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think it&amp;#39;s not quite that.&lt;/p&gt;
&lt;p&gt;Applications typically have a much larger old generation than young generation, i.e. many more long-lived objects than short-lived objects. So GCs do get optimized to process large heaps of old objects quickly and efficiently, e.g. with concurrent mark/sweep.&lt;/p&gt;
&lt;p&gt;However, there is an additional observation: once an application has reached steady state, most newly allocated objects die young (think: the data associated with processing a single HTTP request or user interaction in a UI).&lt;/p&gt;
&lt;p&gt;So as an additional optimization, GCs often split their heap into a young and an old generation, where garbage collecting the young generation earlier/more frequently overall reduces the amount of garbage collection done (and offsets the effort required to move objects around).&lt;/p&gt;
&lt;p&gt;In the case of Go, though, the programming language allows &amp;quot;internal pointers&amp;quot;, i.e. pointers to members of objects. This makes it much harder (or much more costly) to implement a generational, moving garbage collector, so Go doesn&amp;#39;t actually have a young/old generation split, nor the additional optimization for young objects.&lt;/p&gt;
</content>
</entry>
<entry>
<title>Opportunistic fixing vs. long-term planning</title>
<link href="https://probst.io/blog/2018/09/13/opportunistic-fixing-vs-long-term-planning/"/>
<id>https://probst.io/blog/2018/09/13/opportunistic-fixing-vs-long-term-planning/</id>
<published>2018-09-13T08:59:09+00:00</published>
<updated>2018-09-13T08:59:09+00:00</updated>
<content type="html">&lt;p&gt;&lt;em&gt;Originally posted as a &lt;a href=&quot;https://news.ycombinator.com/item?id=17977087&quot;&gt;comment on Hacker News&lt;/a&gt; on &lt;a href=&quot;https://hhvm.com/blog/2018/09/12/end-of-php-support-future-of-hack.html&quot;&gt;Ending PHP Support, and the Future of Hack&lt;/a&gt;, the announcement that Facebook&amp;#39;s HHVM would drop PHP support and focus on Hack, Facebook&amp;#39;s own language derived from PHP.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It&amp;#39;s interesting to see HHVM drop PHP support, particularly if you look at it from an organizational decision-making standpoint. Hypothetically, because I&amp;#39;m not involved in any of this, but still:&lt;/p&gt;
&lt;p&gt;Facebook was initially implemented using PHP, and you can read this process as continued iteration based on this very early decision. From the outside, Facebook seems to have always taken what they had, taken the problems they currently had, and made the most incremental change they could to fix whatever problem they had. From PHP to HHVM to Hack to dropping PHP support, they continued iterating on whatever code base and development chain they currently had.&lt;/p&gt;
&lt;p&gt;If you take a step back, though, Facebook is gradually moving to a different programming environment, from a dynamic language with very loose semantics to a statically typed system with (from code I&amp;#39;ve seen in e.g. Phabricator) a very different programming style than run-of-the-mill PHP. While iterating incrementally, they still ended up forking PHP and moving to a different language.&lt;/p&gt;
&lt;p&gt;The approach is quite different from e.g. Twitter, though, who started off using Ruby on Rails, and then moved everything to an entirely different toolchain (Scala) when they found Rails couldn&amp;#39;t keep up with their problem set.&lt;/p&gt;
&lt;p&gt;This difference in approaches isn&amp;#39;t quite the same as the good old &amp;quot;rewrite vs. refactor&amp;quot; dichotomy. Twitter&amp;#39;s change was certainly incremental too, moving individual services to Scala bit by bit and setting them live incrementally, instead of a &amp;quot;big bang&amp;quot; rewrite where everything moves to Scala one day.&lt;/p&gt;
&lt;p&gt;I think the main difference is planning horizon: do you opportunistically fix whatever is broken right now, or do you make a long-term plan for what you want your future platform to be, and then set out to get there?&lt;/p&gt;
&lt;p&gt;Opportunistic fixing has the advantage that you can be pretty certain you&amp;#39;re fixing the right problem, and don&amp;#39;t invest in YAGNI features. On the other hand, you risk ending up in local optima. Pouring a lot of effort into PHP makes sense if you plan to continue using it - but if you end up forking the language anyway, you lose a lot of the advantages of a shared ecosystem (and arguably damage the existing ecosystem in the process through fragmentation).&lt;/p&gt;
&lt;p&gt;You could equally well imagine Facebook picking a different future tech stack five years ago, be it Rust or Go or whatever, and adding the features they miss from PHP to it. I think it&amp;#39;s an interesting thought experiment where that&amp;#39;d have taken them. I have no idea if taking that path would have been better for any of {Facebook, PHP, target language X, world}.&lt;/p&gt;
</content>
</entry>
<entry>
<title>Why a different language can't replace JavaScript</title>
<link href="https://probst.io/blog/2018/09/02/why-a-different-language-cant-replace-javascript/"/>
<id>https://probst.io/blog/2018/09/02/why-a-different-language-cant-replace-javascript/</id>
<published>2018-09-02T13:27:34+00:00</published>
<updated>2018-09-02T13:27:34+00:00</updated>
<content type="html">&lt;p&gt;&lt;em&gt;Originally posted as a &lt;a href=&quot;https://news.ycombinator.com/item?id=17896925&quot;&gt;comment on Hacker News&lt;/a&gt; on Evan Martin&amp;#39;s post &lt;a href=&quot;http://neugierig.org/software/blog/2018/09/typescript-at-google.html&quot;&gt;TypeScript at Google&lt;/a&gt;. At the time, Evan and I were working on TypeScript at Google together, and this describes the thinking behind our approach. The comment replied to this passage from the post:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The first tempting option is to just abandon this ruined planet and settle a new one that doesn&amp;#39;t even involve JavaScript. If only we invested more in GWT (a Google project that compiles Java to JavaScript) or Dart (a Google project that compiles a new language to JavaScript) or WASM or [insert your favorite language here — Clojure? Haxe? Elm?] we wouldn&amp;#39;t need to worry about JavaScript at all!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I thought about this for quite a while when we started on TypeScript at Google. I&amp;#39;ve convinced myself that using a different language cannot solve the problem that we&amp;#39;re looking at.&lt;/p&gt;
&lt;p&gt;The argument goes like this: if you use a different language than JavaScript for front end development, you&amp;#39;re (hopefully) doing it for a reason. That is, you (a) want the other language&amp;#39;s semantics (e.g. bounds checks on array accesses, runtime types, method dispatch, you name it), or you (b) might want the programming language&amp;#39;s ecosystem: editors, IDEs, etc., but most importantly libraries and frameworks. Most likely, you&amp;#39;re looking for a combination of (a) and (b).&lt;/p&gt;
&lt;p&gt;The problem with (a) is that the more different the runtime semantics of your programming language are, the more emulation code you need. Emulation code is costly in code size, performance, interop with JS, and often understandability (at some point you will need to debug the output, believe me).&lt;/p&gt;
&lt;p&gt;The problem with (b) is that you typically opt into a large ecosystem that was originally written for a very different environment. This was a big issue with GWT: people would pull in Java libraries, but those libraries, amazing as many are, were not written for the web or with code size in mind. This meant using a common library like Guava required a lot of engineering effort to keep code size in check. This also applies to WASM, possibly even more so.&lt;/p&gt;
&lt;p&gt;These mechanisms work together to make it very hard to hit the sweet spot between performance, developer experience, and interoperability. And ironically, the better you get at the goals you&amp;#39;re aiming for (different semantics, different ecosystem), the farther you get away from a working solution.&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t think it&amp;#39;s impossible to achieve a transpile-to-JS language that works really well with enough investment, but keeping in mind the other reasons Evan lists (mind share, existing code base), incrementally improving JavaScript where needed is IMHO the much more promising approach.&lt;/p&gt;
</content>
</entry>
<entry>
<title>Software techniques are tradeoffs, not beliefs</title>
<link href="https://probst.io/blog/2018/07/01/software-techniques-are-tradeoffs-not-beliefs/"/>
<id>https://probst.io/blog/2018/07/01/software-techniques-are-tradeoffs-not-beliefs/</id>
<published>2018-07-01T21:45:55+00:00</published>
<updated>2018-07-01T21:45:55+00:00</updated>
<content type="html">&lt;p&gt;&lt;em&gt;Originally posted as a &lt;a href=&quot;https://news.ycombinator.com/item?id=17437802&quot;&gt;comment on Hacker News&lt;/a&gt; in a discussion of &lt;a href=&quot;http://www.math.columbia.edu/~woit/wordpress/?p=10314&quot;&gt;Lost in Math&lt;/a&gt;. Another commenter argued that software development isn&amp;#39;t really engineering: we can measure little about it, and debates about &amp;quot;clean&amp;quot; or &amp;quot;beautiful&amp;quot; code come down to subjective positions, fanatically defended by &amp;quot;true believers&amp;quot;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;True believers are a problem indeed - people who seem to think software development is about applying firmly held beliefs out of context can really screw things up royally.&lt;/p&gt;
&lt;p&gt;That being said, by now software engineering has a large set of techniques with reasonably well-understood properties, and we can absolutely reason through whether a technique is useful to solve a particular problem.&lt;/p&gt;
&lt;p&gt;For example, polymorphism is a useful technique to invert the locality of implementation details, making it easier to extend software in a distributed way. Its advantage is its drawback: it makes control flow harder to follow, and generally makes the software more difficult to understand, precisely due to the distributed extensibility.&lt;/p&gt;
&lt;p&gt;Similarly, mocking is a technique to reduce testing &amp;quot;surface&amp;quot; by removing dependencies on specific components from a test. It&amp;#39;s a great tool to make tests easier to write, improve test performance, and avoid ambient test dependencies and associated complexity. On the other hand, it reduces test depth by ignoring potentially important interactions, and often leads to overly brittle, hard-to-maintain tests that add little value in actually testing the software.&lt;/p&gt;
&lt;p&gt;It&amp;#39;s easy to go on. None of these techniques are silver bullets or axioms to be followed religiously; they are specific solutions to specific problems. They aren&amp;#39;t necessarily measurable in an analog fashion, such as the load-bearing capability of a steel beam; they are often more binary (quite fitting, given the domain). But you can judge whether they are useful to solve a specific problem.&lt;/p&gt;
&lt;p&gt;That is, I don&amp;#39;t follow the &amp;quot;it&amp;#39;s all just opinion&amp;quot; kind of software engineering defeatism. Yes, there&amp;#39;s a ton of extremely questionable evangelism, often spread with huge pomp and circumstance by people with limited insight. But that&amp;#39;s really just that: limited insight.&lt;/p&gt;
</content>
</entry>
<entry>
<title>Why vendoring every dependency doesn't scale</title>
<link href="https://probst.io/blog/2015/07/10/why-vendoring-every-dependency-doesnt-scale/"/>
<id>https://probst.io/blog/2015/07/10/why-vendoring-every-dependency-doesnt-scale/</id>
<published>2015-07-10T09:15:47+00:00</published>
<updated>2015-07-10T09:15:47+00:00</updated>
<content type="html">&lt;p&gt;&lt;em&gt;Originally posted as a &lt;a href=&quot;https://news.ycombinator.com/item?id=9862972&quot;&gt;comment on Hacker News&lt;/a&gt; on &lt;a href=&quot;https://medium.com/@freeformz/go-1-5-s-vendor-experiment-fd3e830f52c3&quot;&gt;Go 1.5&amp;#39;s vendor/ experiment&lt;/a&gt;. Go 1.5 added experimental support for &lt;code&gt;vendor/&lt;/code&gt; directories, in which a package keeps its own copies of the packages it depends on.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Go&amp;#39;s vendoring is similar to node_modules + npm, in essence.&lt;/p&gt;
&lt;p&gt;Having used node and npm on both small (~200 transitive deps) and large (~1000 transitive deps) projects, I think this is an approach that&amp;#39;s conceptually not a good idea (outside of possible implementation issues with npm).&lt;/p&gt;
&lt;p&gt;With vendoring, you end up with a &lt;em&gt;very&lt;/em&gt; large tree of transitive vendored dependencies. You have no idea of, or control over, what&amp;#39;s in it, and what versions of what packages are in it.&lt;/p&gt;
&lt;p&gt;Nearly all of the time, the two allegedly incompatible versions of a library that you install separately turn out to be 2.0.13 and 2.0.14, and you only get two because, well, somebody hasn&amp;#39;t upgraded yet.&lt;/p&gt;
&lt;p&gt;This might seem trivial, but in the end you have a project tree where every dependency gets installed separately for everything that depends on it, so you end up with something like O(number of deps * number of deps) installed libraries, which obviously doesn&amp;#39;t scale.&lt;/p&gt;
&lt;p&gt;You also end up with the versioning problem. Imagine there&amp;#39;s an important reason to upgrade some package P, e.g. a security issue. Now you have to hunt down every single project in your transitive dependencies that depends on it, and ask them to upgrade or fork.&lt;/p&gt;
&lt;p&gt;You also still have version issues. If you transitively depend on the same library C in versions Cv1 and Cv2, and you want to pass an object/data structure/... from Cv1 to Cv2 through some path, you open yourself up to all kinds of hilarious version mismatches and failures.&lt;/p&gt;
&lt;p&gt;This isn&amp;#39;t new - e.g. Eclipse/OSGi did the same thing with separated class loaders, and it was a mess.&lt;/p&gt;
&lt;p&gt;I think flattening your dependency/vendor tree to only ever have one version of library C, and hoping/testing for minor version mismatches to work out, is the most viable thing to do.&lt;/p&gt;
</content>
</entry>
<entry>
<title>clang-format is available via npm</title>
<link href="https://probst.io/blog/2015/04/11/clang-format-is-available-via-npm/"/>
<id>https://probst.io/blog/2015/04/11/clang-format-is-available-via-npm/</id>
<published>2015-04-11T19:24:34.097742+00:00</published>
<updated>2015-04-11T19:24:34.097876+00:00</updated>
<content type="html">&lt;p&gt;Thanks to the effort of my colleague Alex Eagle (mostly), &lt;code&gt;clang-format&lt;/code&gt; is now available via &lt;a href=&quot;http://npmjs.com&quot;&gt;npm&lt;/a&gt;. You can install it via &lt;code&gt;npm install -g clang-format&lt;/code&gt;, and then just use the &lt;code&gt;clang-format&lt;/code&gt; command normally. Binaries are available for Mac OS X and Linux, both 64 bit.&lt;/p&gt;
&lt;p&gt;Beyond JavaScript, &lt;code&gt;clang-format&lt;/code&gt; now does a pretty decent job at formatting &lt;a href=&quot;http://typescriptlang.org&quot;&gt;TypeScript&lt;/a&gt;, too, including support for classes, interfaces, generics, and of course type annotations. While TypeScript comes with a simple indenter, that doesn&amp;#39;t really support full formatting - e.g. it won&amp;#39;t wrap overlong lines, doesn&amp;#39;t align function parameters, etc. This is of course highly subjective, but I think clang-format does a better job, and it&amp;#39;s nice to be able to use the same formatter across more or less all your languages (C++, Java, JS, TypeScript).&lt;/p&gt;
&lt;p&gt;See my &lt;a href=&quot;http://probst.io/blog/2015/01/15/clang-format-for-javascript/&quot;&gt;clang-format for JavaScript&lt;/a&gt; for more details on how to use it.&lt;/p&gt;
</content>
</entry>
<entry>
<title>clang-format for JavaScript</title>
<link href="https://probst.io/blog/2015/01/15/clang-format-for-javascript/"/>
<id>https://probst.io/blog/2015/01/15/clang-format-for-javascript/</id>
<published>2015-01-15T16:24:54.985878+00:00</published>
<updated>2015-01-15T17:26:26.876581+00:00</updated>
<content type="html">&lt;p&gt;&lt;a href=&quot;http://clang.llvm.org/docs/ClangFormat.html&quot;&gt;clang-format&lt;/a&gt; is a very neat code formatter developed as part of the Clang project by my colleague Daniel Jasper here at Google. It&amp;#39;s so good that many projects have decided to just completely rely on &lt;code&gt;clang-format&lt;/code&gt; and never indent code manually nor use a linter. &lt;code&gt;clang-format&lt;/code&gt; is reasonably well known in the C++ community by now, but it&amp;#39;s much less well known that it also works for a bunch of other vaguely ALGOL-shaped programming languages. I&amp;#39;ve been working a bit with Daniel to make sure it works on JavaScript, which sorely lacks a robust formatter.&lt;/p&gt;
&lt;p&gt;Two days ago &lt;a href=&quot;https://github.com/Homebrew/homebrew/commit/08e363cd65a20f27cc2980a9f75c2db1f7c11723&quot;&gt;my pull request&lt;/a&gt; to &lt;a href=&quot;http://brew.sh/&quot;&gt;Homebrew&lt;/a&gt; was accepted (yay!), so you can now easily install &lt;code&gt;clang-format&lt;/code&gt; on any Mac and enjoy awesome code formatting.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;a href=&quot;http://brew.sh/&quot;&gt;homebrew&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;brew install clang-format&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;There&amp;#39;s no step three&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now when you run &lt;code&gt;clang-format -style=Google somefile.js&lt;/code&gt;, it&amp;#39;ll automatically spit a nicely indented version back at you. For example this terrible mess:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;function Foo() {
     this.bar =
    function() {this.doX(); this.doY();
  for (var x =
0; x &amp;lt; 12; x++) { if (this.z) 
    new 
 Foo(). callWithArgs   (
        {arg1: &amp;#39;hello&amp;#39;,
arg2: &amp;#39;world&amp;#39;});}
    };          this.baz = 123;
           this.bam = {some: &amp;#39;object literal&amp;#39;, including: function() { calls(); }, asdSomeMoreKeysToWrap: 123};
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With one keypress turns into this nicely indented piece:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;function Foo() {
  this.bar = function() {
    this.doX();
    this.doY();
    for (var x = 0; x &amp;lt; 12; x++) {
      if (this.z) new Foo().callWithArgs({arg1: &amp;#39;hello&amp;#39;, arg2: &amp;#39;world&amp;#39;});
    }
  };
  this.baz = 123;
  this.bam = {
    some: &amp;#39;object literal&amp;#39;,
    including: function() { calls(); },
    asdSomeMoreKeysToWrap: 123
  };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I really like it - it takes a lot of the tedium out of writing code, and its indentation is really beautiful - usually much nicer than what I would bother with on a typical day.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;clang-format&lt;/code&gt; already has integration with many editors, e.g. &lt;a href=&quot;http://clang.llvm.org/docs/ClangFormat.html#vim-integration&quot;&gt;vim&lt;/a&gt;, or &lt;a href=&quot;https://packagecontrol.io/packages/Clang%20Format&quot;&gt;Sublime Text&lt;/a&gt;, and the command line is straight forwad to use.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=8893620&quot;&gt;Discuss on HN&lt;/a&gt;&lt;/p&gt;
</content>
</entry>
<entry>
<title>Go on App Engine and GoSublime (golang, code completion)</title>
<link href="https://probst.io/blog/2014/05/26/go-on-app-engine-and-gosublime/"/>
<id>https://probst.io/blog/2014/05/26/go-on-app-engine-and-gosublime/</id>
<published>2014-05-26T19:54:46.090525+00:00</published>
<updated>2014-06-17T18:45:17.592646+00:00</updated>
<content type="html">&lt;p&gt;I&amp;#39;m re-writing this blog using Go on App Engine, just for the fun. It took me quite a while to wrap my head around the available tool options, and get them set up correctly.&lt;/p&gt;
&lt;p&gt;It turns out &lt;a href=&quot;https://www.sublimetext.com&quot;&gt;Sublime Text&lt;/a&gt; (my favorite text editor as of late) has a really nice plugin called &lt;a href=&quot;https://github.com/DisposaBoy/GoSublime&quot;&gt;GoSublime&lt;/a&gt; that provides various Go tools, including auto-completion through &lt;a href=&quot;https://github.com/nsf/gocode&quot;&gt;go code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sadly it also turns out that GoSublime is a bit fickle to get to work with &lt;a href=&quot;https://developers.google.com/appengine/docs/go/&quot;&gt;App Engine&amp;#39;s Go libraries&lt;/a&gt;, possibly because of a &lt;a href=&quot;https://github.com/DisposaBoy/GoSublime/issues/535&quot;&gt;bug&lt;/a&gt;. I think at this time, it&amp;#39;s not possible to have multiple Go workspaces with GoSublime that use different &lt;code&gt;GOROOT&lt;/code&gt; paths (e.g. plain go + App Engine go).&lt;/p&gt;
&lt;p&gt;But at least it&amp;#39;s possible to get consistent code completion and other GoSublime features working, with these global configuration settings in &lt;code&gt;Preferences &amp;gt; Package Settings &amp;gt; GoSublime &amp;gt; Settings - User&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;{
  &amp;quot;installsuffix&amp;quot;: &amp;quot;appengine&amp;quot;,
  &amp;quot;env&amp;quot;: {
    // Your GOPATH for App Engine projects, e.g.
    &amp;quot;GOPATH&amp;quot;: &amp;quot;/Users/martin/goae&amp;quot;,
    // Your GOROOT, e.g.
    &amp;quot;GOROOT&amp;quot;: &amp;quot;/usr/local/Cellar/go-app-engine-64/1.9.5/share/go-app-engine-64/goroot&amp;quot;
  },
  // ... any other settings you have ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The source code running this puny blog is available at &lt;a href=&quot;http://github.com/mprobst/blog&quot;&gt;http://github.com/mprobst/blog&lt;/a&gt; by the way. It has zero features and is the first thing I ever wrote in Go, so probably not a good idea to take as an example for much.&lt;/p&gt;
</content>
</entry>
<entry>
<title>Blog on AppEngine, Java, Jersey / JAX-RS</title>
<link href="https://probst.io/blog/2012/03/07/Blog-on-AppEngine-Java-Jersey-JAX-RS/"/>
<id>https://probst.io/blog/2012/03/07/Blog-on-AppEngine-Java-Jersey-JAX-RS/</id>
<published>2012-03-07T21:02:22.574000+00:00</published>
<updated>2012-03-07T21:48:02.082000+00:00</updated>
<content type="html">&lt;p&gt;Continuing the theme that I mostly use  this blog to experiment with software, not so much for writing an actual blog, I moved over the software from Django/Python to Java, both running on &lt;a href=&quot;http://code.google.com/appengine/&quot;&gt;AppEngine&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Django Out&lt;/h3&gt;&lt;p&gt;First of all, I&amp;#39;ll have to admit that I&amp;#39;m not a Python programmer. I can program in the language, but I don&amp;#39;t feel at home. I&amp;#39;ve never really used it long enough at a time to grow familiar with the APIs and the pythonic way of doing things. I still struggle to remember the basic string manipulation APIs and such. I&amp;#39;ve always felt that Python is a nice, clean language (except for the constant &amp;quot;self.&amp;quot; that is), I&amp;#39;ve just never gotten around to use it enough.&lt;/p&gt;
&lt;p&gt;That being said, coming from Rails, &lt;a href=&quot;https://www.djangoproject.com/&quot;&gt;Django&lt;/a&gt; is a big step back, and &lt;a href='http://www.allbuttonspressed.com/projects/django-nonrel'&gt;Django nonrel&lt;/a&gt;, the patch to make Django run on AppEngine, is worse. Django itself lacks a lot of things taken for granted in Rails, and Django non-rel is not only cumbersome to install, it also lacks many of the compelling features of Django (e.g. the automated administration backend).&lt;/p&gt;
&lt;p&gt;So I didn&amp;#39;t really see a compelling reason to stay with Django, and as I wanted to move away anyway, I could go back to Java as well. I also wanted to play around with a couple of Java technology pieces that seem nice.&lt;/p&gt;
&lt;h3&gt;Jersey In&lt;/h3&gt;&lt;p&gt;I&amp;#39;ve used Jersey from time to time before. It&amp;#39;s a web framework that revolves mostly around HTTP. Jersey (and JAX-RS) is not trying to abstract HTTP away, it&amp;#39;s trying to model HTTP well and give a good framework to program on the web, which resounds with me a lot.  It&amp;#39;s geared towards writing RESTful APIs more than towards writing actual dynamic web sites, so a bit of setup/customization is required, but nothing too bad.&lt;/p&gt;
&lt;p&gt;Jersey of course only gives you the basic web interaction layer, i.e. the controller. I&amp;#39;m using &lt;a href=&quot;http://code.google.com/p/objectify-appengine/&quot;&gt;Objectify&lt;/a&gt; to persist Plain Old Java Objects (POJOs) for the (trivial) models, &lt;a href=&quot;https://developers.google.com/closure/templates/&quot;&gt;Closure Templates&lt;/a&gt; to render views, and &lt;a href=&quot;http://code.google.com/p/google-gson/&quot;&gt;Gson&lt;/a&gt; to convert model objects into JSON like data structures for the views (Closure doesn&amp;#39;t support accessing POJOs directly so that it can support Java and JavaScript from the same templates).&lt;/p&gt;
&lt;h3&gt;Validation&lt;/h3&gt;&lt;p&gt;I haven&amp;#39;t really found any compelling library for validation. &lt;a href=&quot;http://jcp.org/en/jsr/detail?id=303&quot;&gt;JSR 303&lt;/a&gt;&amp;#39;s model driven approach through annotations seems nice, &lt;a href=&quot;http://static.springsource.org/spring/docs/current/spring-framework-reference/html/validation.html&quot;&gt;Spring Validation&lt;/a&gt; is more of a (quite trivial?) utility library, and I&amp;#39;m not going to touch &lt;a href=&quot;http://commons.apache.org/validator/&quot;&gt;Apache Commons Validator&lt;/a&gt; and its XML configuration with a 10 foot pole. I ended up just rolling something similar to Spring&amp;#39;s support library on my own; after all it&amp;#39;s only a trivial blog.&lt;/p&gt;
&lt;h3&gt;Form Support&lt;/h3&gt;&lt;p&gt;The other thing missing from a productive toolkit is converting from submitted form data to objects (application/x-www-url-encoded, not multipart/form-data). Spring MVC offers something like that with its Command or Form objects, but that seems not very useful if not combined with all the rest of Spring. Given that we have an excellent library for JSON-&amp;gt;POJO conversion with Gson, maybe it&amp;#39;d just be a naming convention for form fields that allows translating them to JSON (a bit like Objectify translates Datastore&amp;#39;s simple maps to objects). Again, not really needed for a blog.&lt;/p&gt;
&lt;h3&gt;Webstack&lt;/h3&gt;&lt;p&gt;Overall I&amp;#39;m quite happy with it. If you don&amp;#39;t opt into Java&amp;#39;s traditional AbstractViewHandlerControllerFactory patterns (Spring, I&amp;#39;m looking at you) you can end up with pretty productive environments. None of the components I use are overly ceremonial, nothing needs &amp;quot;configuration&amp;quot;, and no XML involved in any form, you can even (mostly) get around web.xml and appengine-web.xml :-) I do realize that all of this is complete overkill for a tiny blog, as is writing your own blog in the first place. On the other hand, I kind of enjoy putting these pieces together and writing something on AppEngine, and I&amp;#39;m always interested in seeing how hard it is or how easy it should be to build certain things.&lt;/p&gt;
&lt;p&gt;It&amp;#39;s always hard to get started from nothing, and I suspect this might be interesting for others. I&amp;#39;ll write a couple of blog posts about the different parts of the system, including putting it together using Guice.&lt;/p&gt;
</content>
</entry>
<entry>
<title>Exporting from iPhoto to Picasa Web</title>
<link href="https://probst.io/blog/2012/01/14/exporting-from-iphoto-to-picasa-web/"/>
<id>https://probst.io/blog/2012/01/14/exporting-from-iphoto-to-picasa-web/</id>
<published>2012-01-14T11:16:41.905000+00:00</published>
<updated>2012-01-15T01:39:24.120000+00:00</updated>
<content type="html">&lt;p&gt;I have a significant collection of photos on my home machine, all stored in iPhoto. I back them up to an external hard drive, using time machine, and copy them to a second machine using rsync every now and then. However all of that is within my apartment. That&amp;#39;s not only somewhat dangerous (think fire, burglary, ... - at least if you&amp;#39;re paranoid enough), it also means I cannot access the photos from anywhere.&lt;/p&gt;
&lt;p&gt;So my current weekend project is to upload them to Picasa Web. I actually like iPhoto, and I don&amp;#39;t really want to switch to Picasa to manage my photos, so I have to get the pictures out of iPhoto into Picasa Web.&lt;/p&gt;
&lt;p&gt;Google has two tools for that, a standalone uploader, and an export plugin for iPhoto (that curiously lives in a completely different place of the UI than iPhoto&amp;#39;s other export plugins ...). Both are available in a single download &lt;a href=&quot;http://picasa.google.com/mac_tools.html&quot;&gt;here&lt;/a&gt;. Neither of them does what I want though - the standalone uploader doesn&amp;#39;t understand iPhoto or its albums at all, and the iPhoto plugin is a manual process. You select individual albums and upload them. That&amp;#39;s probably useful if you want to export a single album, but not for a complete export. I need a background task that automatically does the uploading, preferably a restartable one.&lt;/p&gt;
&lt;p&gt;Background process, automated? Command line to the rescue! :-)&lt;/p&gt;
&lt;p&gt;It turns out there&amp;#39;s a very straightforward iPhoto export tool that also supports incremental exports, &lt;a href=&quot;https://github.com/BMorearty/exportiphoto&quot;&gt;exportiphoto on Github&lt;/a&gt;. Downloading that and running &lt;code&gt;exportiphoto -d &quot;$HOME/Pictures/iPhoto Library&quot; $HOME/tmp/iphotoexport&lt;/code&gt; worked like a charm (-d to suppress dates prepended to the event name). Some ~5 of my pictures were referenced in the album metadata but inexplicably missing on the hard disk, I simply deleted them.&lt;/p&gt;
&lt;p&gt;This leaves you with a directory structure of &amp;quot;$event/$picture&amp;quot; in tmp/iphotoexport for each of your events (unrelated: why is this not a built-in feature of iPhoto?). Now for the uploading part - uploading to Picasa is surprisingly easy using the &lt;a href=&quot;http://code.google.com/p/googlecl/&quot;&gt;Google command line&lt;/a&gt;. It requires the &lt;a href=&quot;http://code.google.com/apis/gdata/docs/client-libraries.html&quot;&gt;Google client libraries&lt;/a&gt;, but both are available in Python&amp;#39;s easy_install repository, so simply running &lt;code&gt;sudo easy_install googlecl&lt;/code&gt; gives you all you need. Creating an album from a set of pictures is as simple as &lt;code&gt;google picasa create &quot;My Album&quot; my_album/* --date=2012-01-03&lt;/code&gt;. We can get the date for the album from the minimum last modified time of all exported files in the album using some ruby trickery, the dates of the pictures themselves are taken from the photo metadata. The command line uses OAuth 2 to log you in, which is a bit spooky - it pops up a browser in which you give the permissions, and then proceeds on the command line. Nice to see OAuth working so well, I really have to find some time and understand that.&lt;/p&gt;
&lt;p&gt;So TL;DR:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl https://raw.github.com/BMorearty/exportiphoto/master/exportiphoto.py &amp;gt; exportiphoto.py
sudo easy_install googlecl

python exportiphoto.py &amp;quot;Pictures/iPhoto Library&amp;quot; &amp;quot;tmp/iphotoexport&amp;quot;
cd tmp/iphotoexport

for album in *; do
  echo Uploading $album...
  min_last_modified=`ruby -e &amp;#39;require &amp;quot;time&amp;quot;; puts Dir[ARGV[0] + &amp;quot;/*&amp;quot;].map { |x| File.mtime(x) }.min.strftime(&amp;quot;%F&amp;quot;)&amp;#39; &amp;quot;$album&amp;quot;`
  google picasa create &amp;quot;$album&amp;quot; $album/* --date=$min_last_modified
done
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As for the incremental, resumable part, I still have no idea. I&amp;#39;ll poke around with the Google command line and see if I can get last modified timestamps or something similar out of it.&lt;/p&gt;
</content>
</entry>
<entry>
<title>Lion's Address Book and Calendar</title>
<link href="https://probst.io/blog/2011/12/10/lion-s-address-book-and-calendar/"/>
<id>https://probst.io/blog/2011/12/10/lion-s-address-book-and-calendar/</id>
<published>2011-12-10T10:45:29.136000+00:00</published>
<updated>2011-12-10T10:45:29.136000+00:00</updated>
<content type="html">&lt;p&gt;After using them for a couple of months, I&amp;#39;m more and more annoyed by Mac OS Lion&amp;#39;s productivity apps, the address book and calendar. At first, I was a bit surprised by the gratuitous real world analogies (ripping of sheets in calendar, the pseudo notebook style in address book), but thought hey, whatever.&lt;/p&gt;
&lt;p&gt;The more I use it, the more annoyed I am. For example, navigating between dates in calendar is a disaster. The controls are hidden on the top right, far away from the pill buttons that control the timespan shown, which are much more prominent but most of the time not what you actually want to use. The &amp;quot;rip off&amp;quot; animation when navigating back and forth between months not only doesn&amp;#39;t make sense, it just takes a long time and disorients users. The main user interactions for me, &amp;quot;what&amp;#39;s happening this week&amp;quot; and &amp;quot;plan next month&amp;quot; are unnecessarily cumbersome. Google&amp;#39;s calendar really does a way better job there, with navigation elements in the top left, the whole month overview, and a much better attention flow from top left to bottom right.&lt;/p&gt;
&lt;p&gt;The page flipping in Address Book has the same issue. It doesn&amp;#39;t make sense (the same content appears on the front and back of the same physical page, the book only has three pages), it&amp;#39;s full UI change is disorienting, and it makes it impossible to interact with groups and contacts efficiently.&lt;/p&gt;
&lt;p&gt;I wonder what this is all about. Apple clearly should know better. And surprisingly, as Google (and IMHO much of the web) moves to cleaner, more minimalist UI design, Apple goes into the direct opposite direction, with real world analogies that don&amp;#39;t work, and just plain bad UI design. Are they loosing their mojo in desktop UI apps?&lt;/p&gt;
</content>
</entry>
<entry>
<title>Subsetting a language is a red herring</title>
<link href="https://probst.io/blog/2011/02/23/subsetting-a-language-is-a-red-herring/"/>
<id>https://probst.io/blog/2011/02/23/subsetting-a-language-is-a-red-herring/</id>
<published>2011-02-23T15:14:24+00:00</published>
<updated>2011-02-23T15:14:24+00:00</updated>
<content type="html">&lt;p&gt;&lt;em&gt;Originally posted as a &lt;a href=&quot;https://news.ycombinator.com/item?id=2254298&quot;&gt;comment on Hacker News&lt;/a&gt; on &lt;a href=&quot;http://alarmingdevelopment.org/?p=562&quot;&gt;Switching to Plan J&lt;/a&gt;, a post about moving from Scala back to Java. Earlier in the thread, the discussion had turned to a language&amp;#39;s &amp;quot;complexity budget&amp;quot;: languages have only so much room for concepts before their interactions become unpredictable and too much to keep in mind at once. The comment replied to another commenter, who wrote:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Scala can be used strictly as a &amp;quot;better Java&amp;quot; without using any of the advanced type features or idioms if that is what you want. […]&lt;/p&gt;
&lt;p&gt;I offer the hypothesis that when using any new and &amp;quot;large&amp;quot; language on a real life project you have to work with a subset. This is not a bad thing and &amp;quot;subset&amp;quot; is not a dirty word […]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think the &amp;quot;subsetting the language&amp;quot; approach is a red herring. Yes, you can decide you&amp;#39;ll only use features X, Y, and Z. Many people do that in similarly complex languages like C++.&lt;/p&gt;
&lt;p&gt;But the programmers will, one way or the other, get exposed to the features you considered esoteric, be it through libraries, or sample code, or whatever. And then they have a piece of code in the language they use for daily work that they don&amp;#39;t understand and can&amp;#39;t debug, and they&amp;#39;re alienated by strange compiler errors - not good.&lt;/p&gt;
&lt;p&gt;It&amp;#39;s IMHO also quite hard to come up with the subset you like. I mean, programmers like to have endless discussions about completely irrelevant topics, like brace placement; wait and see the discussions about actual language features to (not) use! Most features are in themselves completely reasonable, so it&amp;#39;s hard to make a cut here.&lt;/p&gt;
&lt;p&gt;I also think the &amp;quot;mediocre programmer&amp;quot; argument is a red herring. Not that there aren&amp;#39;t mediocre programmers who will have trouble understanding certain language features at all - there certainly are.&lt;/p&gt;
&lt;p&gt;But I&amp;#39;d wager that even for very good programmers, having many complex language features (that interact!) in a code base will be problematic. Of course you can understand what&amp;#39;s going on with some effort on your side, but the problem is the effort. Programming languages are IMHO a bit like user interfaces in this regard: &amp;quot;don&amp;#39;t make me think&amp;quot;. Having code in a code base that&amp;#39;s complex and/or hard to understand is a really, really bad thing. People will shy away from reading and modifying it, and over time it&amp;#39;ll grow into an unmaintained monstrosity.&lt;/p&gt;
&lt;p&gt;Again, this is about the complexity budget. Original Java code was dead easy to understand; now, with generics, it&amp;#39;s a bit harder (but overall I think generics are less bad than you hear all the time). That was, and still is, one of the really killer Java features. Not only for mediocre programmers, but for general readability, and thus usability of the language.&lt;/p&gt;
</content>
</entry>
<entry>
<title>Blog on Google App Engine</title>
<link href="https://probst.io/blog/2011/02/04/blog-on-google-app-engine/"/>
<id>https://probst.io/blog/2011/02/04/blog-on-google-app-engine/</id>
<published>2011-02-04T13:56:58.891000+00:00</published>
<updated>2011-07-01T09:10:32.420000+00:00</updated>
<content type="html">&lt;p&gt;Over the last couple of days, I took up another recreational programming project: I ported this blog to &lt;a href=&quot;http://appengine.google.com&quot;&gt;Google App Engine&lt;/a&gt;, using Python and &lt;a href=&quot;http://www.allbuttonspressed.com/projects/django-nonrel&quot;&gt;django-nonrel&lt;/a&gt;. Partially this is of course preparation for my next job, but App Engine also looks like a good solution for a personal blog. You can run your own code, hosting is free for small projects, and you don&amp;#39;t have to worry about most system administration minutiae.&lt;/p&gt;
&lt;p&gt;Whenever I look at a new web framework, I estimate how much work it would be to create a weblog in it - I think weblogs are sort of the hello world of web applications. If a weblog isn&amp;#39;t easy to implement, then something about the framework is a bit fishy.&lt;/p&gt;
&lt;p&gt;Porting my blog from Ruby on Rails to App Engine was a bit more work than I originally expected, but I think it&amp;#39;s not necessarily the platform&amp;#39;s fault. After all, I tried to learn Python, App Engine, and Django all at once, with the added bonus of using a non-mainline, patched version of Django. Also, like I guess most software engineers, I consistently underestimate the work associated with more or less anything. I mean, writing out articles from a database, how hard could it be, right?&lt;/p&gt;
&lt;p&gt;In the end, I spent 4 or 5 days on this, mostly browsing through the Django documentation to find out how things are done over here, and cursing that in Python all the standard library functions have The Wrong Name&amp;trade; (when coming from Java and Ruby). Some things are still a bit hacky (I insisted on putting the required libraries in a subfolder, for which I had to patch django-nonrel...).&lt;/p&gt;
&lt;p&gt;It&amp;#39;s also been a bit of a pain putting the individual pieces together. The individual App Engine APIs are explained properly, but the built-in &amp;quot;webapp&amp;quot; framework is clearly lacking, so you have to pick up something like django-nonrel. Getting that to work nicely with App Engine however requires quite some reading and fiddling around. Not sure how that looks on the Java side of App Engine, but for the Python framework, the batteries are definitely not included. Python is a nice language though, and I already love using the datastore instead of a relational database. The framework also has a lot of nifty features, like the bulkloader system, or the XMPP support.&lt;/p&gt;
&lt;h3&gt;Rails vs Django&lt;/h3&gt;&lt;p&gt;Compared to Rails, Django seems to be influenced by the Python spirit of doing things correctly. Rails is &amp;quot;anything that works and looks cool is ok&amp;quot;, Django seems to be searching for the right way to do things a bit more. For example, Django has another level of indirection with separate classes handling forms, where Rails just uses the model classes directly. Both works, Rails a bit less verbose, Django is a bit stricter. It&amp;#39;s probably easier to customize Django&amp;#39;s form handling through the added level of abstraction, and obviously easier to get different behaviour in different places. Rails on the other hand wins with simplicity and a clear &amp;quot;this is the way to do things&amp;quot;.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m not sure which approach I like better. Rails is clearly easier to pick up, and solving the simple, expected problems is probably easier.&lt;/p&gt;
&lt;p&gt;Another thing one notices is that Rails has a lot more mindshare, a lot more features, documentation, plugins, etc. I&amp;#39;m sure there is something comparable to Ruby&amp;#39;s XML builder, AJAX handlers, etc., but I couldn&amp;#39;t find an easy way to do that. Django is also missing a bunch of features you take for granted in Rails, like migrations, RESTful handlers, easy support for content types and so on. Django users can certainly get all of that, but need to put in more effort.&lt;/p&gt;
&lt;p&gt;I wonder how these things are done internally at Google. I guess I&amp;#39;ll see in a month ;-)&lt;/p&gt;
&lt;h3&gt;Features!&lt;/h3&gt;&lt;p&gt;While being at it, I added some nice features: I finally put a proper anti-spam solution together (the one before didn&amp;#39;t require a CAPTCHA, but was a bit flaky - I suspect it had a bunch of false positives, and it effectively disallowed talking about Viagra ;-)). When someone leaves a comment, a chat bot now informs me about it using Jabber. And for authentication I can rely on Google Accounts through the User service.&lt;/p&gt;
&lt;p&gt;What&amp;#39;s still missing is support for pingbacks and trackbacks. Both specs are somewhat annoying (trackback with its pseudo RDF-embedding in articles, pingback with its XML-RPC requirement). Before doing that, I&amp;#39;d like to put at least some rudimentary testing system together; at the moment, this is all just a hack without any quality control whatsoever.&lt;/p&gt;
&lt;p&gt;I guess I should get back to posting a bit more often on this blog to set off the investment. Currently I feel I wrote more code for the blogging system than text on the blog itself - somewhat like having an oldtimer car where you spend more time lying under the car than sitting inside of it.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;PS:&lt;/b&gt; excuses to the feed subscribers, I had to change the permalinks for entries once again, so your readers probably marked all old entries as new... I promise this will be the very last time! Until I migrate everything to my new domain probst.io, that is ;-)&lt;/p&gt;
</content>
</entry>
<entry>
<title>Google += Martin</title>
<link href="https://probst.io/blog/2011/02/01/google-martin/"/>
<id>https://probst.io/blog/2011/02/01/google-martin/</id>
<published>2011-02-01T15:00:47.205000+00:00</published>
<updated>2011-02-01T15:00:47.205000+00:00</updated>
<content type="html">&lt;p&gt;As I&amp;#39;ve already announced quite some time ago &lt;a href=&quot;http://twitter.com/martin_probst/status/15046726880591872&quot;&gt;on Twitter&lt;/a&gt;, I will be joining Google as a Software Engineer, starting 1st of March in Munich.&lt;/p&gt;
&lt;p&gt;Leaving EMC/X-Hive has not been an easy decision. I joined X-Hive in April 2005, and working there has in many aspects shaped my life. I&amp;#39;ve been very lucky to end up at such a liberal, easy going company, with great colleagues. I was able to do wonderful things (working on the core of an excellent product, in a very international team, business trips to both Americas, participating in the W3C XQuery Working Group, working with a diverse set of technologies...) which I guess wouldn&amp;#39;t have been easy at other companies. Some of the greatest things about X-Hive are the relaxed attitude, the &amp;quot;bottom-up&amp;quot; organization, the freedom for engineers to make their own calls, and the diligence and care for product quality. X-Hive feels very much like family.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ll be missing the company lunch at the big kitchen table, the snarky discussions, the Dutch (and Brazilian! and Czech! and Russian! and French! and Belgian!) humour. I might even be missing the Dutch food, with some exceptions (I&amp;#39;m looking at you, frikandel).&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t exactly know what I&amp;#39;ll be doing at Google yet, but I&amp;#39;m sure it will be interesting. It might sound cliché, but I&amp;#39;m looking forward to new challenges, learning new technologies, and a new team.&lt;/p&gt;
</content>
</entry>
<entry>
<title>HTML5 vs the W3C?</title>
<link href="https://probst.io/blog/2010/11/04/html5-vs-the-w3c/"/>
<id>https://probst.io/blog/2010/11/04/html5-vs-the-w3c/</id>
<published>2010-11-04T11:37:44+00:00</published>
<updated>2011-01-31T16:35:17.166000+00:00</updated>
<content type="html">&lt;p&gt;I agree with Michael Kay&amp;#39;s annoyance about the browser vendors unilateralism, expressed &lt;a href=&quot;http://saxonica.blogharbor.com/blog/_archives/2010/11/4/4671786.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However I think this has a bit of history. The browser vendors started their own thing after the W3C first went off with XHTML into a direction that created lots of problems for browser vendors for no return, and then completely grinded to a halt due to the W3C&amp;#39;s process being gambled and prone to blockading.&lt;/p&gt;
&lt;p&gt;So first we had one side ignoring the other side&amp;#39;s concerns, and now we largely have it the other way around, with a lot more open conflicts.&lt;/p&gt;
&lt;p&gt;I&amp;#39;d hope we can get over the artificial conflicts that are created here, and get both sides to acknowledge the other&amp;#39;s legitimate concerns. It doesn&amp;#39;t quite look like that&amp;#39;s going to happen soon, though.&lt;/p&gt;
</content>
</entry>
<entry>
<title>Division of Labour</title>
<link href="https://probst.io/blog/2010/04/29/division-of-labour/"/>
<id>https://probst.io/blog/2010/04/29/division-of-labour/</id>
<published>2010-04-29T13:59:04+00:00</published>
<updated>2010-04-29T13:59:04+00:00</updated>
<content type="html">&lt;p&gt;Weird: everyone who has worked in small companies/startups and large companies knows that you spend a lot more time in large companies on overhead. That can be all sorts of things, like buying a piece of software, taking time off, etc.&lt;/p&gt;
&lt;p&gt;The strange thing is that in theory, one would think that a large organisation is structured better and caters to many more people, thus has a better division of labour, and thus the overhead for individuals goes down.&lt;/p&gt;
&lt;p&gt;But it&amp;#39;s exactly opposite. In a startup, you spend time on things that might not be your exact role, like administrating a web server when you are strictly speaking a developer. But that actually contributes to the company&amp;#39;s success. And even if you count that time as overhead, I still feel I had less overhead in smaller organisations.&lt;/p&gt;
&lt;p&gt;I wonder if this is just for software companies and bureau type workers, as opposed to assembly line workers. Still seems like a weird failure; economies of scale would suggest the opposite effect.&lt;/p&gt;
</content>
</entry>
<entry>
<title>Reducing XPath</title>
<link href="https://probst.io/blog/2010/01/05/reducing-xpath/"/>
<id>https://probst.io/blog/2010/01/05/reducing-xpath/</id>
<published>2010-01-05T14:43:51+00:00</published>
<updated>2010-01-05T14:43:51+00:00</updated>
<content type="html">&lt;p&gt;Michael Kay writes on his blog: &lt;a href=&quot;http://saxonica.blogharbor.com/blog/_archives/2010/1/5/4420740.html&quot;&gt;&amp;quot;Could XPath have been better&amp;quot;&lt;/a&gt;, suggesting XPath would have been a nicer language without all the little inconsistencies. Instead, he&amp;#39;d rather map more or less everything to built in functions and their application to sequences, including the axes, predicates, and so on.&lt;/p&gt;
&lt;p&gt;This very much sounds like an implementors pipe dream: remove all the annoying inconsistencies and make it easier to create fast implementations.&lt;/p&gt;
&lt;p&gt;If you are done replacing all implicit syntax with function calls, I think you might find that you have written a LISP interpreter with built in functions (some with funny or punctuation names) for DOM navigation. Not that that would be a bad thing.&lt;/p&gt;
&lt;p&gt;Though this makes one wonder what the actual proposed value of XPath is, once you reduced it to a LISP dialect. Probably the restricted expressiveness and from that the ability of analyzing the function applications to produce a clever execution strategy.&lt;/p&gt;
&lt;p&gt;This always reminds me of Erik Meijer and his presentation on LINQ at VLDB 2005 (?), where he demonstrated how LINQ effectively maps certain function applications (selection, projection) to different repositories. I still like the approach: provide a somewhat unified syntax, hand over an Abstract Syntax Tree at run time to the data source/repository, and let that find a good way of executing the query. Integrating the query language into the programming language very much reduces the pain for users, and creates a uniform interface for many different data sources.&lt;/p&gt;
&lt;p&gt;This is of course limited to the .NET platform and effectively SQL only, afaik, and I have never actually used LINQ, so I have no idea how good it works out in practice. I might imagine that tool support (profiling! indexes!) can be difficult.&lt;/p&gt;
</content>
</entry>
<entry>
<title>Generating Eclipse build files with XQuery</title>
<link href="https://probst.io/blog/2009/11/16/generating-eclipse-build-files-with-xquery/"/>
<id>https://probst.io/blog/2009/11/16/generating-eclipse-build-files-with-xquery/</id>
<published>2009-11-16T20:27:38+00:00</published>
<updated>2009-11-16T20:27:38+00:00</updated>
<content type="html">&lt;p&gt;A friend of mine had a problem today. He was trying to make a huge Ant-based project usable from within Eclipse. The build file would manage dependencies through XML property files within about 30 subdirectories, each declaring which sub-projects need to be compiled before itself.&lt;/p&gt;
&lt;p&gt;Writing all those .project and .classpath files is a very tedious task, and clicking them together in Eclipse is even more tedious. XQuery to the rescue!&lt;/p&gt;
&lt;p&gt;I simply imported all the property files into xDB and ran this query:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import module namespace fw = &amp;#39;java:java.io.FileWriter&amp;#39;;
import module namespace xn = &amp;#39;java:com.xhive.dom.interfaces.XhiveNodeIf&amp;#39;;

for $project in /project
let $name := substring-before( substring-after(document-uri($project/root()), &amp;#39;/build/&amp;#39;), &amp;#39;/&amp;#39;)
where $name != &amp;#39;swami&amp;#39;
return
(:let $name := if ($name = &amp;#39;daogen&amp;#39;) then &amp;#39;DaoGenerator&amp;#39; else $name:)
let $dep-internal := tokenize($project/property[@name=&amp;#39;${module.name}.depend.internal&amp;#39;]/@value, &amp;#39;,&amp;#39;)
let $dep-common := tokenize($project/property[@name=&amp;#39;${module.name}.depend.internal&amp;#39;]/@value, &amp;#39;,&amp;#39;)[not(ends-with(., &amp;#39;.jar&amp;#39;))]
let $deps := (&amp;#39;libs&amp;#39;, distinct-values(($dep-internal, $dep-common)))
let $fw := fw:new(concat(&amp;#39;/Users/martin/tmp/build/&amp;#39;, $name, &amp;#39;/.classpath&amp;#39;))
let $pw := fw:new(concat(&amp;#39;/Users/martin/tmp/build/&amp;#39;, $name, &amp;#39;/.project&amp;#39;))
let $classpath :=
&amp;lt;classpath&amp;gt;
{ comment { $name } }
	&amp;lt;classpathentry kind=&amp;quot;src&amp;quot; path=&amp;quot;src&amp;quot;/&amp;gt;
	&amp;lt;classpathentry kind=&amp;quot;con&amp;quot; path=&amp;quot;org.eclipse.jdt.launching.JRE_CONTAINER&amp;quot;/&amp;gt;
{ for $dep in $deps return
	&amp;lt;classpathentry combineaccessrules=&amp;quot;false&amp;quot; kind=&amp;quot;src&amp;quot; path=&amp;quot;/SW {$dep}&amp;quot;/&amp;gt;
}
	&amp;lt;classpathentry kind=&amp;quot;output&amp;quot; path=&amp;quot;bin&amp;quot;/&amp;gt;
&amp;lt;/classpath&amp;gt;
let $project :=
&amp;lt;projectDescription&amp;gt;
	&amp;lt;name&amp;gt;SW {$name}&amp;lt;/name&amp;gt;
	&amp;lt;comment&amp;gt;&amp;lt;/comment&amp;gt;
	&amp;lt;projects&amp;gt;
	&amp;lt;/projects&amp;gt;
	&amp;lt;buildSpec&amp;gt;
		&amp;lt;buildCommand&amp;gt;
			&amp;lt;name&amp;gt;org.eclipse.jdt.core.javabuilder&amp;lt;/name&amp;gt;
			&amp;lt;arguments&amp;gt;
			&amp;lt;/arguments&amp;gt;
		&amp;lt;/buildCommand&amp;gt;
	&amp;lt;/buildSpec&amp;gt;
	&amp;lt;natures&amp;gt;
		&amp;lt;nature&amp;gt;org.eclipse.jdt.core.javanature&amp;lt;/nature&amp;gt;
	&amp;lt;/natures&amp;gt;
&amp;lt;/projectDescription&amp;gt;

return (
  fw:write($fw, xn:to-xml($classpath)),
  fw:write($pw, xn:to-xml($project)),
  fw:close($fw),
  fw:close($pw)
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What does this do? It iterates through all project descriptions, takes the project name from the document URI, takes out the dependency information (those are the tokenize calls), and create a .project and .classpath XML snippet for each sub-project.&lt;/p&gt;
&lt;p&gt;xDB does not include functions to write to the file system out of the box. We could create our own custom extension functions in Java and put them on the classpath, but there is a much easier way through the Java Module Import functionality.&lt;/p&gt;
&lt;p&gt;We simply import &lt;code&gt;java.io.FileWriter&lt;/code&gt;, create a FileWriter through the fw:new(...) calls for the right file location, serialize the XML snippets using xn:to-xml(...), and then make sure to close the file writers.&lt;/p&gt;
&lt;p&gt;We still needed to do some fixups in Eclipse (mainly adding .jar files to the build path and fixing some wrong circular dependencies), but this certainly saved us hours. The world is a much nicer place when you have effective XML tools at your hands :-)&lt;/p&gt;
</content>
</entry>
</feed>
