tag:blogger.com,1999:blog-76941531509542923292008-06-03T00:43:04.585-07:00Ori Peleg's Blogoriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.comBlogger13125tag:blogger.com,1999:blog-7694153150954292329.post-10524302678542028292008-05-22T10:20:00.001-07:002008-05-22T10:21:39.256-07:00Firebug 1.2b1 is out!<a href="http://www.getfirebug.com/blog/2008/05/22/firebug-12b1">http://www.getfirebug.com/blog/2008/05/22/firebug-12b1</a><br /><br />Yay!oriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.comtag:blogger.com,1999:blog-7694153150954292329.post-45148005568168713992008-04-30T11:37:00.000-07:002008-04-30T12:26:02.540-07:00Regular Expressions Are Fun<a href="http://miriampeleg.blogspot.com/">Miriam</a> and I were debugging a regular expression, and it was an educational experience.<br /><br />The platform is Java, and our problem is:<br /><ul><li>Input is a long string</li><li>We want to replace occurrences of "PRE[SEARCHSTRING]POST" with "PREreplacedPOST"</li><li>"PRE" and "POST" are patterns<br /></li><li>"[SEARCHSTRING]" is a string that contains a lot of special regex character like "[", "\", and "$".<br /></li></ul>We found <a href="http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html#quote%28java.lang.String%29"><span style="font-family:courier new;">java.util.regex.Pattern.quote</span></a> to help with the special characters in "[SEARCHSTRING]":<br /><br /><span style="font-family:courier new;">String quotedPattern = Pattern.quote(searchString);</span><br /><br />Now, how do we match "PRE" and "POST" without losing them? They disappear if we try:<br /><span style="font-family:courier new;">return input.replace("PRE" + quotedPattern + "POST", "replaced")</span>;<br /><br />After some fiddling we came up with:<br /><br /><span style="font-family:courier new;">return input.replaceAll("(PRE)" + quotedPattern + "(POST)", "$1replaced$2");</span><br /><br />This matches "PRE" and "POST", but <a href="http://java.sun.com/javase/6/docs/api/java/util/regex/Matcher.html#appendReplacement%28java.lang.StringBuffer,%20java.lang.String%29">references the captured subgroups</a> with "$1" and "$2" so they don't disappear.<br /><br />But we then tried the following instead:<br /><br /><span style="font-family:courier new;">return input.replaceAll("(?<=PRE)" + quotedPattern + "(?=POST)", "replaced");</span><br /><br />"(?=POST)" is a <a href="http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html#special">zero-width positive lookahead</a>, which is an incredibly cool technical name. It matches a pattern that <span style="font-style: italic;">does</span> appear ahead ("positive lookahead") but this pattern won't be regarded when checking what parts of the string matched the regular expression ("zero-width"). "(?<=PRE)" is, similarly, a zero-width positive lookbehind. There are also <span style="font-style: italic;">negative</span> lookaheads and lookbehinds that make sure the pattern <span style="font-style: italic;">doesn't</span> appear.<br /><br />Is there a more elegant way to do this?oriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.comtag:blogger.com,1999:blog-7694153150954292329.post-57523008854226609612008-04-23T14:47:00.000-07:002008-04-23T15:13:28.660-07:00Sorting time spans with jQuery TablesorterI've been working a little with Christian Bach's nifty <a href="http://tablesorter.com">Tablesorter</a> plugin for <a href="http://jquery.com">jQuery</a>, and I'd like to share some cool stuff I've learned.<br /><br />I wanted to sort a column of time spans formatted like this: "2 days 15:11:06". I wrote a <a href="http://tablesorter.com/docs/example-parsers.html">custom parser</a> and ended up with this:<br /><span style="font-family: monospace;"><pre>$.tablesorter.addParser({<br /> id: 'timespan',<br /> is: function(s) { return false; }, // don't auto detect<br /> format: function(s) { return s.replace(/\D/g,""); },<br /> type: 'numeric'<br />});</pre></span><br />And the usage:<br /><span style="font-family: monospace;"><pre>$("#mytable").tablesorter({<br /> headers : {<br /> 2 : 'timespan' // the 3rd column is a time span<br /> }<br />});</pre></span><br />All it's doing is removing all non-digits and asking for a numeric comparison. It should even work equally well for "0 days 02:30:00" and for "02:30:00", since leading zeros don't affect the sorting :-)oriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.comtag:blogger.com,1999:blog-7694153150954292329.post-11664447784410290002008-04-14T10:56:00.000-07:002008-04-14T11:22:06.175-07:00Dead-simple portable JavaScript logger<pre style="padding: 1em; backround-color: #E0E0E0; border: solid 1px #101010;">window.console = {<br /> log : function (message) {<br /> if ($('#logpane').length == 0)<br /> $('body').append("&lt;ul id='logpane'>&lt;/ul>");<br /> $("#logpane").append($("&lt;li>&lt;/li>").text(message));<br /> }<br />};</pre><br /><br />This requires <a href="http://jquery.com">jQuery</a>, and should work on any browser and on most pages.<br /><br />It intentionally uses the name '<code>console.log</code>', so it overrides logging to <a href="http://www.getfirebug.com/">Firebug</a>'s logger.<br /><br />To use it:<br /><pre style="padding: 1em; backround-color: #E0E0E0; border: solid 1px #101010;">&lt;script type="text/javascript"><br />console.log("foo");<br />console.log("bar");<br />&lt;script></pre><br />It's not very pretty - just appends a list of log messages at the bottom:<br /><ul><li>foo</li><li>bar</li></ul>oriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.comtag:blogger.com,1999:blog-7694153150954292329.post-42701074717304078272008-04-09T13:01:00.000-07:002008-04-09T13:05:49.365-07:00Firefox + View Source GoodnessThis is incredibly cool!<br /><br />In <code>about:config</code>:<br /><ul><br /><li>Set '<b><code>view_source.editor.external</code></b>' to <b><code>true</code></b> </li><br /><li>Set '<b><code>view_source.editor.path</code></b>' to ... whatever! In my case, '<b><code>...\gvim.exe</code></b>'</li><br /></ul><br /><br />Thanks <a href="http://briancarper.net/2007/05/09/firefox-vim/">Brian</a>!oriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.comtag:blogger.com,1999:blog-7694153150954292329.post-28041490466991924862008-03-12T01:11:00.000-07:002008-03-12T01:13:48.781-07:00Huh?This book title cracked me up :-)<br /><a href="http://www.amazon.com/exec/obidos/ASIN/0470037164/orpesbl-20"><blockquote><img src="http://images.amazon.com/images/P/0470037164.01.MZZZZZZZ.jpg" alt="Book Cover" /></blockquote></a>oriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.comtag:blogger.com,1999:blog-7694153150954292329.post-59800200086938647132008-03-09T13:36:00.000-07:002008-03-09T13:41:15.366-07:00"My Feet Hurt"If you want to get physically active, there's only one thing really stopping you:<br /><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/obdd31Q9PqA"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/obdd31Q9PqA" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object><br /><br />(Courtesy of <a href="http://liftlikeagirl.blogspot.com/">Lift Like A Girl</a>)oriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.comtag:blogger.com,1999:blog-7694153150954292329.post-5633688185046613572008-02-13T14:02:00.000-08:002008-02-13T15:50:03.527-08:00Who's afraid of dynamic typing?If you're afraid of dynamic typing, stop. Take some time to learn a good dynamically-typed language, then take some more time to learn how some people build big production systems with it, and how they manage to do it with less effort and <span style="font-style: italic;">increased safety and reliability</span> vs. equivalent implementations in popular statically-typed languages. Regardless of your conclusions, I can guarantee you'll increase your breadth as a developer and that your new insights will improve your effectiveness in any programming language.<br /><br />So why are people afraid of dynamic typing? Maybe it's the way most people approach dynamic languages:<br /><ol><li>skim through some tutorials</li><li>write some toy code</li><li>reach a final verdict about their applicability to large-scale development</li></ol>These verdicts are usually based on gut instinct and second-hand stories rather than on actual experience developing real systems with <span style="font-weight: bold;">guidance</span> on proper ways to use the language.<br /><br />I'll finish with a story: One time a good C++ developer got excited about a dynamic language. He used it extensively for scripting and was familiar with all of its features, and he convinced the necessary parties to develop a real upcoming system in this language. But when writing the system he threw every one of his development practices out the window and half-assed the whole thing, writing incredible spaghetti code, not testing, and cramming in as many language features as he could. The project was not a complete failure, but the "obvious" conclusion was that this language wasn't appropriate for these tasks, whereas <span style="font-style: italic;">my</span> conclusions are:<br /><ol><li>Be responsible. You may also use a dynamic language for scripting, but when you're building a real system you're not scripting.</li><li>Don't rely on static typing - it isn't there to rely on. You <span style="font-style: italic;">have</span> to unit-test.</li><li>Use your language's idioms and good shortcuts, avoid the evil ones. Seek experienced guidance on this issue.</li><li>Don't get in over your head - before applying a language feature in production, become familiar with it. Don't worry, it'll wait for you!<br /></li></ol>Some articles I love on the topic:<br /><ul><li><a href="http://dirtsimple.org/2004/12/python-is-not-java.html">Python Is Not Java</a>, by Phillip J. Eby. A great quote from it is:<br /><br /><blockquote><span style="font-style: italic;">"... if you've been using Java for a while and are new to Python, </span><b style="font-style: italic;">do not trust your instincts</b><span style="font-style: italic;">. Your instincts are tuned to Java, not Python."</span><br /></blockquote></li><li><a href="http://dirtsimple.org/2004/12/java-is-not-python-either.html">Java Is Not Python Either...</a>, also by PJE</li><li><a href="http://mindview.net/WebLog/log-0025">Strong Typing vs. Strong Testing</a>, by Bruce Eckel<br /></li></ul>oriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.comtag:blogger.com,1999:blog-7694153150954292329.post-49703693956860332622008-02-11T16:47:00.000-08:002008-02-11T17:00:12.470-08:00Boo and TiddlyWikiI'm now learning <a href="http://boo.codehaus.org/">Boo</a> (as part of learning <a href="http://castleproject.org/monorail/documentation/trunk/viewengines/brail/index.html">Brail)</a>. One of the most helpful Boo sites I've found is <a href="http://mysite.mweb.co.za/residents/sdonovan/boo-book.html">The Book of Boo</a> - and it's a <a href="http://www.tiddlywiki.com/">TiddlyWiki</a>, no less!oriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.comtag:blogger.com,1999:blog-7694153150954292329.post-3648758779866358082008-02-09T17:50:00.000-08:002008-02-11T13:42:00.881-08:00Inversion of Control and Dependency Injection for dummiesI'm a dummy.<br /><br />I've been hearing about IoC and DI for several years, but every time I tried to figure out what they were the explanation was either too complicated or so trivial it didn't make sense (i.e. what is it good for?)<br /><br /><br /><a href="http://dotnetslackers.com/articles/designpatterns/InversionOfControlAndDependencyInjectionWithCastleWindsorContainerPart1.aspx">Now I understand</a>. Thanks, <a href="http://dotnetslackers.com/community/blogs/simoneb/archive/2007/07/24/IoC-with-Windsor-Container-on-DotNetSlackers.aspx">Simone</a>! Even more accessible than <a href="http://martinfowler.com/articles/injection.html">Martin Fowler's explanation</a>, and that's saying a lot!<br /><br />Here's the way I get it:<br /><br /><b>I.</b> <b>IoC</b> happens when you use code that calls <i>your</i> code, such as whenever you use any framework. That means it's just a buzzword to fling at friends, but a really cool one. (Why do people insist on giving cool names to simple techniques? Oh well, <a href="http://www.amazon.com/exec/obidos/ASIN/007144811X/orpesbl-20">Eddie Bravo</a> does it too.)<br /><br /><b>II.</b> You often program against interfaces instead of specific implementations.<br /><br /><pre>interface Foo { ... }<br />interface Bar { ... }<br />class Alpha : implements Foo { ... }<br />class Beta : implements Bar { ... }<br />class Charlie {<br /> Charlie(Foo foo, Bar bar) { ... }<br />}<br /><br />Charlie c = new Charlie(new Alpha(), new Beta())</pre><br /><b>DI </b>happens when instead of choosing the concrete classes yourself you let a repository, called a "container", handle it for you.<br /><pre>// register implementations for Foo and Bar (could<br />// be done in a config file)<br />container.register(Foo, Alpha)<br />container.register(Bar, Beta)<br /><br />// Create a Charlie - the container detects it<br />// needs Foo and Bar implementers for the constructor<br />// and chooses Alpha and Beta<br />Charlie c = container.createInstance<charlie>()</charlie></pre><br />When I needed to interchange different implementations I used to write it by hand, but no more - these containers are much better! Since they're general and easy to use, I have a feeling I'll be using them in cases I didn't bother with before.oriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.comtag:blogger.com,1999:blog-7694153150954292329.post-4766447745945211732008-02-09T13:44:00.001-08:002008-02-09T17:54:59.045-08:00Distributed version control<div xmlns='http://www.w3.org/1999/xhtml'><small>(I'm still <a href='http://oripel.blogspot.com/2007/12/distributed-version-control-and-git.html'>trying to figure out DVCS</a>)</small><br/><br/>I <span style='font-style: italic;'>love</span> version control. I started with CVS and moved to Subversion. I loved having <a href='http://www.amazon.com/exec/obidos/ASIN/0977616657/orpesbl-20'>Pragmatic Version Control using Subversion</a> when I was making the move. If you write software and you don't use version control, c'mon!<br/><br/>I don't know my way around distributed version control systems, though.<br/><br/>I became interested in distributed version control a few years ago when a <a href='http://kichik.net/'>good friend</a> recommended <a href='http://darcs.net/'>darcs</a>. I've played with it and other systems including <a href='http://www.selenic.com/mercurial/wiki/'>Mercurial</a> and <a href='http://bazaar-vcs.org/'>Bazaar</a>, and I've read a lot of blog posts and opinion pieces, but I've never actually wrapped my head around how to effectively use them in the contexts I'm used to. Maybe I'm just stuck in the wrong contexts.<br/><br/>If anyone's reading this and can help me, I'm all ears.<br/><br/>Linus's great tech talk on <a href='http://git.or.cz/'>git</a> made me feel I understand distributed version control a little better, but I still don't see the relevance. To make it clear, I'm not claiming my ignorance is a virtue. I guess I'm just slow on this.<br/><br/>I have been able to discern the following benefits:<br/><ul><li>No required master repository, all branches are equal</li><li>Trivial branching, easy merging (including cherry-picking)<br/></li><li>Can work offline</li><li>Performance for local work isn't affected by the network<br/></li></ul>Am I missing anything important?<br/><br/>What I find interesting is that most of these issues are irrelevant for the <span style='font-weight: bold;'>corporate</span> environments I'm used to, where everybody's working on a LAN, committing to a central trunk is fine (constant integration, and good unit tests prevent breakage), and the branching model is intentionally simple and reduces merging because in many cases merging will be hard regardless of the tools (think heavy refactoring).<br/><br/>More good links:<br/><ul><li><a href='http://www.codinghorror.com/blog/archives/000968.html'>Jeff Atwood on branches</a></li><li><a href='http://wincent.com/a/about/wincent/weblog/archives/2007/10/why_distributed.php'>Wincent Colaiuta explaining "Why Distributed Version Control"</a></li><li><a href='http://www.perforce.com/perforce/bestpractices.html'>Perforce's "Best Practices in SCM"</a> (a little long)<br/></li></ul></div>oriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.comtag:blogger.com,1999:blog-7694153150954292329.post-90386542757819170552007-12-08T11:43:00.000-08:002007-12-08T11:47:32.550-08:00Distributed version control and gitThere's a great tech talk by Linus Torvalds on <a href="http://git.or.cz/">git</a> and distributed version control in general. I'm trying to wrap my head around the topic, and this talk helped me quite a bit.<br /><br /><object height="355" width="425"><param name="movie" value="http://www.youtube.com/v/4XpnKHJAok8&amp;rel=1"><param name="wmode" value="transparent"><embed src="http://www.youtube.com/v/4XpnKHJAok8&amp;rel=1" type="application/x-shockwave-flash" wmode="transparent" height="355" width="425"></embed></object>oriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.comtag:blogger.com,1999:blog-7694153150954292329.post-61288842411007620672007-12-01T15:41:00.000-08:002007-12-01T16:25:37.048-08:00Cheap Turpentine<blockquote>"When art critics get together they talk about Form and Structure and Meaning. When artists get together they talk about where you can buy cheap turpentine."<br /><br />- Pablo Picasso, quoted in "<a href="http://www.amazon.com/exec/obidos/ASIN/0735619670/orpesbl-20">Code Complete</a>" by Steve McConnell<br /></blockquote><blockquote></blockquote>This quote nailed it for me. I still love philosophizing about software and technology, but I know it isn't <span style="font-style: italic;">real</span> so I don't take it too seriously.oriphttp://www.blogger.com/profile/00060140324205560525noreply@blogger.com