<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8128258</id><updated>2011-11-03T14:13:41.603+02:00</updated><title type='text'>Max's blog v0.2.1</title><subtitle type='html'>Mastering programming and blogging.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>56</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8128258.post-113146974054825988</id><published>2005-11-08T19:06:00.000+02:00</published><updated>2005-11-08T19:09:00.556+02:00</updated><title type='text'>The blog has moved</title><content type='html'>I decided to stop using Blogger and moved to a dedicated hosting for blogging. Please check it out on &lt;a href="http://max.textdriven.com"&gt;max.textdriven.com&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-113146974054825988?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/113146974054825988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=113146974054825988' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/113146974054825988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/113146974054825988'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/11/blog-has-moved.html' title='The blog has moved'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-112425395967349964</id><published>2005-08-17T07:32:00.000+03:00</published><updated>2005-08-17T07:45:59.680+03:00</updated><title type='text'>Python programmer for sale</title><content type='html'>This's been a hot summer for me but now it ends, along with my contract work.&lt;br /&gt;&lt;br /&gt;So if you need a (hopefully) good programmer, skilled in UNIX development, Python and Java platforms, agile methods and traditional engineering, please &lt;a href="mailto:ischenko@gmail.com"&gt;contact me&lt;/a&gt;. I'm &lt;a href="http://ischenko.blogspot.com/2004/10/hire-me.html"&gt;interested&lt;/a&gt; in both short-term and long-term contract work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-112425395967349964?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/112425395967349964/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=112425395967349964' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/112425395967349964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/112425395967349964'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/08/python-programmer-for-sale.html' title='Python programmer for sale'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-111824692045463159</id><published>2005-06-08T19:08:00.000+03:00</published><updated>2006-08-22T11:29:11.450+03:00</updated><title type='text'>pre-built mock classes?</title><content type='html'>&lt;div class=Section1&gt;  &lt;p class=MsoPlainText&gt;&lt;font size=2 face="Lucida Sans Unicode"&gt;&lt;span lang=EN-US style='font-size:10.0pt'&gt;There is a (relatively) widely used technique in unit testing, called mock objects. There is even a &lt;a href="http://pmock.sourceforge.net/"&gt;pMock&lt;/a&gt; library which provides a Mock class for a Python environment.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class=MsoPlainText&gt;&lt;font size=2 face="Lucida Sans Unicode"&gt;&lt;span lang=EN-US style='font-size:10.0pt'&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class=MsoPlainText&gt;&lt;font size=2 face="Lucida Sans Unicode"&gt;&lt;span lang=EN-US style='font-size:10.0pt'&gt;Given the &amp;quot;duck typing&amp;quot; nature of the Python itself, it's pretty trivial to build mocks without using any pre-built libraries. What is less trivial and potentially more worthwhile is to have a library of &amp;#8220;stock&amp;#8221; mock objects.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class=MsoPlainText&gt;&lt;font size=2 face="Lucida Sans Unicode"&gt;&lt;span lang=EN-US style='font-size:10.0pt'&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class=MsoPlainText&gt;&lt;font size=2 face="Lucida Sans Unicode"&gt;&lt;span lang=EN-US style='font-size:10.0pt'&gt;For instance, I found myself re-implementing ConnectionStub class again and again for different projects. And there is no shortage of other good candidates as well: socket, web request/response, thread objects, etc. Someone on a Python mailing list &lt;a href="http://mail.python.org/pipermail/python-list/2004-November/249441.html"&gt;asks&lt;/a&gt; whether anyone implemented a mock filesystem interface, for example.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class=MsoPlainText&gt;&lt;font size=2 face="Lucida Sans Unicode"&gt;&lt;span lang=EN-US style='font-size:10.0pt'&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class=MsoPlainText&gt;&lt;font size=2 face="Lucida Sans Unicode"&gt;&lt;span lang=EN-US style='font-size:10.0pt'&gt;Having a library of such mock classes, realizing widely-used and &amp;#8220;heavy&amp;#8221; interfaces may be a good idea.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class=MsoPlainText&gt;&lt;font size=2 face="Lucida Sans Unicode"&gt;&lt;span lang=EN-US style='font-size:10.0pt'&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class=MsoPlainText&gt;&lt;font size=2 face="Lucida Sans Unicode"&gt;&lt;span lang=EN-US style='font-size:10.0pt'&gt;The only real problem I can think of is whether it&amp;#8217;s possible to make these mocks generic enough. Mocks often contain some (application-specific) hard-coded rules and data to realize desired behavior. For instance, socket mock may fail when user attempts to write a &amp;#8220;foobar&amp;#8221; string &amp;#8211; and unit test will use this to check how code handle these kind of errors. These rules may be generalized but it may lead to mock classes becoming unwieldy.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class=MsoPlainText&gt;&lt;font size=2 face="Lucida Sans Unicode"&gt;&lt;span lang=EN-US style='font-size:10.0pt'&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class=MsoPlainText&gt;&lt;font size=2 face="Lucida Sans Unicode"&gt;&lt;span lang=EN-US style='font-size:10.0pt'&gt;Even keeping this problem in mind, it&amp;#8217;s still a reasonable idea for a library, but obviously I&amp;#8217;m biased.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class=MsoPlainText&gt;&lt;font size=2 face="Lucida Sans Unicode"&gt;&lt;span lang=EN-US style='font-size:10.0pt'&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class=MsoPlainText&gt;&lt;font size=2 face="Lucida Sans Unicode"&gt;&lt;span lang=EN-US style='font-size:10.0pt'&gt;What do &lt;b&gt;&lt;span style='font-weight:bold'&gt;you&lt;/span&gt;&lt;/b&gt; think?&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-111824692045463159?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/111824692045463159/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=111824692045463159' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/111824692045463159'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/111824692045463159'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/06/pre-built-mock-classes.html' title='pre-built mock classes?'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-111477266564285379</id><published>2005-04-29T14:02:00.000+03:00</published><updated>2005-04-29T14:04:25.643+03:00</updated><title type='text'>Non-obstrusive configuration</title><content type='html'>When writing an application the author has to think about wiring and configuration issues which often contradicts with fine-grained approach used during building it. These issues depends heavily both upon the design of the code itself (how much state does it have, how it is strutured) and the nature of the library (application) in question.&lt;br /&gt;&lt;br /&gt;To clarify: an application consists of a number of functions/classes/modules each of them having (usually) a defined and well-understood scope and set of responsibilities. So far so simple - this is just good engineering practice. To get a coherent whole you need to wire it all together, configuring the parts along the way (network ports, passwords and other runtime options). And this is where it get messier.&lt;br /&gt;&lt;br /&gt;How to achieve ease of wiring/configuration while not compromising on system's design on the same time?&lt;br /&gt;&lt;br /&gt;I have run into these problems myself a number of times and almost every time has to come with some novel approach. Partly this is to be expected as different requirements calls for different solutions. Still, my own naiveness (experience level) has to play some role as well, as I may have missed some patterns obvious to a more experience programmer.&lt;br /&gt;&lt;br /&gt;One of the biggest problems I had is that most of these solutions are obtrusive: once installed they tend to spread thru the code like viruses which hurts maintainability (if you ever change your mind and try a different approach) and code reuse.&lt;br /&gt;&lt;br /&gt;The rule of thumb I've learnt so far is to try to split the application into two parts: core (a "library" in a traditional sense) and, um, application itself. While this does not solve the problem, at least it puts it within well-defined boundaries. OTOH, when this "application" gets incorporated into something still bigger you have to overhaul it again which is no good. Even without incorporating, the "library" part sometimes became smaller than the "application" part, which spoils the whole idea.&lt;br /&gt;&lt;br /&gt;To put at least some meat into this post, I'd like to mention &lt;a href="http://www.pycontainer.glt.pl/"&gt;PyContainer&lt;/a&gt; library of Rafal Sniezynski, which is a Python implementation of "Inversion of Control" (IoC for short) idea. IoC in general and various implementations (called "containers") is a hot topic in Java community.&lt;br /&gt;&lt;br /&gt;On the surface, this is exactly what I'm looking for: container manages wiring and configuration of its object according to given set of rules. But I can't tell for sure until I try. What I like most is the perceived level of obtrusiveness (lack of): components that go within container have no idea they are within "something" and thus can be developed, unit-tested and reused freely. Only part of the application that uses the container has to deal with it - and my only concern is to make it as small as possible.&lt;br /&gt;&lt;br /&gt;P.S.: Re-reading my post I realized that problems I'm talking about may not be so obvious and/or so painful to the readers as they were to me. What was your experience? Do you share my frustration?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-111477266564285379?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/111477266564285379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=111477266564285379' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/111477266564285379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/111477266564285379'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/04/non-obstrusive-configuration.html' title='Non-obstrusive configuration'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-111218801569692802</id><published>2005-03-30T16:05:00.001+03:00</published><updated>2005-03-30T20:46:43.790+03:00</updated><title type='text'>A problem with Python</title><content type='html'>Ian Bicking &lt;a href="http://blog.ianbicking.org/why-web-programming-matters-most.html"&gt;wrote&lt;/a&gt; a passionate post where he encourages community to put more efforts into Python-for-web-application domain.&lt;br /&gt;&lt;br /&gt;I have another complain about the Python (both for language itself and tools and libraries around it). Here it is: &lt;i&gt;Python cannot fully utilize hardware resources&lt;/i&gt;. You see, I have several [web] programs running on my machine, some in Java and some in Python. Some of these are the apps I'm writing and debugging myself, some are third-party.&lt;br /&gt;&lt;br /&gt;When I'm working on Java app, I have some serious stuff loaded: Eclipse IDE, Tomcat web server, database server, Firefox with API documentation opened, etc. Basically, you need 1Gb of RAM to have it all work smoothly. And even then it takes 12 seconds to redeploy an application. And we all know Java technology has sophisticated JIT compilers which means execution speed is &lt;i&gt;much&lt;/i&gt; higher compared to Python.&lt;br /&gt;&lt;br /&gt;What do we see in Python? Instance of Vim editor, WebKit/Apache server, may be a Firefox running and a database. That's all. How much resources does it take? Nothing. How long does it take to redeploy a WebKit application? Nothing again. In fact, you could develop Python app on some archaic Celeron-666/256 Mb box and notice little difference with modern Athlon 2800+/1Gb. At least, that was my experience.&lt;br /&gt;&lt;br /&gt;What the heck?&lt;br /&gt;&lt;br /&gt;If the language can't make a serious load out of modern hardware it can't be nothing else then a toy language, right? Programming is hard and it must feel that way.&lt;br /&gt;&lt;br /&gt;Therefore, I ask the community to put more efforts to "grow" both the language and the tools. The day I see my python application deployed in a 12 seconds to a WSGI-backed WebKit I know: we have a serious, mature language. No, not a "language" - it'd be called a "platform" by then. Definitely.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-111218801569692802?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/111218801569692802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=111218801569692802' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/111218801569692802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/111218801569692802'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/03/problem-with-python_30.html' title='A problem with Python'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-111218815141791483</id><published>2005-03-30T16:05:00.000+03:00</published><updated>2005-03-30T16:09:11.420+03:00</updated><title type='text'>A problem with Python</title><content type='html'>Ian Bicking &lt;a href="http://blog.ianbicking.org/why-web-programming-matters-most.html"&gt;wrote&lt;/a&gt; a passionate post where he encourages community to put more efforts into Python-for-web-application domain.&lt;br /&gt;&lt;br /&gt;I have another complain about the Python (both for language itself and tools and libraries around it). Here it is: &lt;i&gt;Python cannot fully utilize hardware resources&lt;/i&gt;. You see, I have several [web] programs running on my machine, some in Java and some in Python. Some of these are the apps I'm writing and debugging myself, some are third-party.&lt;br /&gt;&lt;br /&gt;When I'm working on Java app, I have some serious stuff loaded: Eclipse IDE, Tomcat web server, database server, Firefox with API documentation opened, etc. Basically, you need 1Gb of RAM to have it all work smoothly. And even then it takes 12 seconds to redeploy an application. And we all know Java technology has sophisticated JIT compilers which means execution speed is &lt;i&gt;much&lt;/i&gt; higher compared to Python.&lt;br /&gt;&lt;br /&gt;What do we see in Python? Instance of Vim editor, WebKit/Apache server, may be a Firefox running, a shell. That's all. How much resources does it take? Nothing. How long does it take to redeploy a WebKit application? Nothing again. In fact, you could develop Python app on some archaic Celeron-666/256 Mb box and notice little difference with modern Athlon 2800+/1Gb. At least, that was my experience.&lt;br /&gt;&lt;br /&gt;What the heck?&lt;br /&gt;&lt;br /&gt;If the language can't make a serious load out of modern hardware it can't be nothing else then a toy language, right? Programming is hard and it must feel that way.&lt;br /&gt;&lt;br /&gt;Therefore, I ask the community to put more efforts to "grow" both the language and the tools. The day I see my python application deployed in a 12 seconds to a WSGI-backed WebKit I know: we have a serious, mature language. No, not a "language" - it'd be called a "platform" by then. Definitely.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-111218815141791483?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/111218815141791483/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=111218815141791483' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/111218815141791483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/111218815141791483'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/03/problem-with-python.html' title='A problem with Python'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-111176923242348392</id><published>2005-03-25T18:34:00.000+02:00</published><updated>2005-03-25T18:47:12.423+02:00</updated><title type='text'>webfixture revised</title><content type='html'>There was some interested in my &lt;a href="http://ischenko.blogspot.com/2004/09/testing-web-based-applications-with.html"&gt;webfixture&lt;/a&gt; project so I decided to bite the bullet and pulled it online. See &lt;a href="http://opensvn.csie.org/webfixture"&gt;repository&lt;/a&gt; and &lt;a href="https://opensvn.csie.org/traccgi/webfixture/trac.cgi/wiki/"&gt;project page&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-111176923242348392?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/111176923242348392/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=111176923242348392' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/111176923242348392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/111176923242348392'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/03/webfixture-revised.html' title='webfixture revised'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-111087509853982755</id><published>2005-03-15T10:21:00.000+02:00</published><updated>2005-03-15T10:24:58.543+02:00</updated><title type='text'>Software, process and people</title><content type='html'>A recent &lt;a href="http://pf.fastcompany.com/magazine/06/writestuff.html"&gt;article&lt;/a&gt; on FastCompany site tells a story about software engineers at NASA that write software for space modules and other such stuff. The story is entertaining and instructive but what I find naive is the idea that engineering approach used for this kind of projects at NASA could (and should!) be transferred to other kind of projects.&lt;br /&gt;&lt;br /&gt;First, who writes it?&lt;br /&gt;&lt;blockquote&gt;That's the culture: the on-board shuttle group produces grown-up software, and the way they do it is by being grown-ups. It may not be sexy, it may not be a coding ego- trip -- but it is the future of software.&lt;br /&gt;&lt;/blockquote&gt;It's a bit of a stretch, but I mostly agree here. To create a good software you need professionals. Software production is a complex activity and experience is a key. It doesn't really matter whether you look "sexy" or not and whether you have a spouse and kids. Of course, experience takes time and thus experienced programmers tend to be older and as such, may no longer care much about the "cool outfit" but care more about the family.&lt;br /&gt;&lt;br /&gt;Next question: "how do they write the right stuff"?&lt;br /&gt;&lt;blockquote&gt;The answer is, it's the process. The group's most important creation is not the perfect software they write -- it's the process they invented that writes the perfect software.&lt;br /&gt;&lt;/blockquote&gt;Yeah, I agree on this but I suspect for a different reason than original authors. Here is another quote which clarifies their reasoning:&lt;br /&gt;&lt;blockquote&gt;The most important things the shuttle group does -- carefully planning the software in advance, writing no code until the design is complete, making no changes without supporting blueprints, keeping a completely accurate record of the code -- are not expensive. The process isn't even rocket science. Its standard practice in almost every engineering discipline except software engineering.&lt;br /&gt;&lt;/blockquote&gt;I think they are putting the cart before the horse. They succeed not because of the process &lt;i&gt;per se&lt;/i&gt; but because the process was a good fit and probably was invented to match the kind of projects they are working on. And of course, no process would help if the execution is flawed. Attempting to copy the process to different project may lead to Cargo Cult Engineering, masterfully described by Steve McConnell in his &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0321193679/ref=nosim/maxischenblog-20"&gt;Professional Software Development&lt;/a&gt; book.&lt;br /&gt;&lt;br /&gt;Even more important and fundamental point - "expensiveness" of this kind of approach. The hard truth is that process above is not viable for a mainstream world of the software development. For a one, you can't really &lt;i&gt;fix&lt;/i&gt; the requirements. And those who think they can often find themselves out of business. And another one - the process must be cost-effective which means finite resources and trade-offs and compromises.&lt;br /&gt;&lt;br /&gt;I do believe we (industry) have a long way toward skillful software development and I'm looking for improvements that advances SWEBOK, but thinking that following NASA processes may give that to us is lame.&lt;br /&gt;&lt;br /&gt;Well, this post is probably somewhat lame itself, as I'm not an expert either. ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-111087509853982755?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/111087509853982755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=111087509853982755' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/111087509853982755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/111087509853982755'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/03/software-process-and-people.html' title='Software, process and people'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110958317206221918</id><published>2005-02-28T11:28:00.000+02:00</published><updated>2005-02-28T11:32:52.066+02:00</updated><title type='text'>Wikiphobia</title><content type='html'>Mr. Ed published another &lt;a href="http://www.hacknot.info/hacknot/action/showEntry?eid=71"&gt;article&lt;/a&gt; on his &lt;a href="http://hacknot.info/"&gt;hacknot.info&lt;/a&gt; site. This one is called Wikiphilia and tries to present Wikis as an inadequate tool for most (all?) application it has been put to. Or at least that is how I understood him. He writes controversial articles and (IMO, again) wrote nothing particularly convincing since a couple of earlier &lt;a href="http://www.hacknot.info/hacknot/action/showEntry?eid=54"&gt;good&lt;/a&gt; &lt;a href="http://www.hacknot.info/hacknot/action/showEntry?eid=48"&gt;ones&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The "wikiphilia illness" goes too far as well. While I agree that Wikis (like any other tool) can be misused or used to procrastinate I don't buy his general criticism. To me, it mostly sounds like a projection of his own (or made-up) phobias and behavioral models onto Wiki's users. A quote:&lt;br /&gt;&lt;blockquote&gt;Whilst anyone can add their opinion to a Wiki page, anyone can come along and remove it. Therefore it is vacuous to claim that a Wiki affords equal opportunity for all users to express their opinion, when it allows any user to suppress that opinion through simple deletion. To ensure that their contribution persists, a user has to watch over their content, re-inserting it after anyone else has deleted it. Some users resort to writing bots for this purpose.&lt;br /&gt;&lt;/blockquote&gt;I'd say this is highly atypical (and unethical) pattern that the user constantly reinserts his own statement which were deleted by the community (for a reason, I suppose). Or even write bots (sic!) for this purpose. Of course, a malicious one may do so but that's a different matter.&lt;br /&gt;&lt;br /&gt;I don't find it compelling to argue with the rest of the article, interested readers may read it themselves and made their own conclusions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110958317206221918?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110958317206221918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110958317206221918' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110958317206221918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110958317206221918'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/02/wikiphobia.html' title='Wikiphobia'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110958272099861776</id><published>2005-02-28T11:25:00.000+02:00</published><updated>2005-03-01T10:01:45.413+02:00</updated><title type='text'>Python Grimoire Wiki</title><content type='html'>&lt;p class="mobile-post"&gt;Just stumbled upon an impressive &lt;a href="http://the.taoofmac.com/static/grimoire.html"&gt;Python Grimoire &lt;/a&gt;document. Woudn't it be great to have this content available as a Wiki, to ease maintaining it and expanding into some kind of uber-knowledge base for pythonprogrammers? &lt;/p&gt;&lt;p class="mobile-post"&gt;I've been looking for this kind of repository since I've appreciated the &lt;a href="http://wiki.tcl.tk/"&gt;analogue&lt;/a&gt; in a Tcl world. It's just great and help tremendously.&lt;/p&gt;&lt;p class="mobile-post"&gt;Yes, I know about ActiveState's cookbook but this imho a different thing.&lt;/p&gt;&lt;span style="font-weight: bold;"&gt;update:&lt;/span&gt; Fix formatting issues and add missing link&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;update:&lt;/span&gt; There is an effort-in-progress to convert Grimoire to a Wiki. See &lt;a href="http://the.taoofmac.com/space/Python/Grimoire"&gt;this&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110958272099861776?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110958272099861776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110958272099861776' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110958272099861776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110958272099861776'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/02/python-grimoire-wiki.html' title='Python Grimoire Wiki'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110934423181903604</id><published>2005-02-25T16:55:00.000+02:00</published><updated>2005-02-25T17:10:31.826+02:00</updated><title type='text'>The good, the bad and the ugly</title><content type='html'>&lt;p&gt;&lt;b&gt;disclaimer:&lt;/b&gt; I &lt;i&gt;am&lt;/i&gt; living in a developing country and I &lt;i&gt;am&lt;/i&gt;  working for oversees customers so keep this in mind while reading the following.  This post is &lt;i&gt;not&lt;/i&gt; about advocating offshore development model either.&lt;/p&gt;  &lt;p align="left"&gt;A bit too often for my taste, I encounter on the Web the statement that  "third-world" developers are inferior to that of USA or, say, Germany.  Just to illustrate my point, here is a quote from a recent &lt;a href="http://discuss.joelonsoftware.com/default.asp?biz.5.71573.25"&gt; thread&lt;/a&gt; on  &lt;a href="http://discuss.joelonsoftware.com/"&gt; JoS&lt;/a&gt;  business forum:&lt;/p&gt;   &lt;blockquote&gt;I find (on average) that off-shore coders know one or two programming languages and how to implement things in them specifically. I find (on average) that on-shore coders [ that get disgusted with and leave RAC] are the kind that are multi-talented and flexible due to this.&lt;/blockquote&gt;   &lt;p&gt;I see little reason trying to fight this legend and it's sort of natural to  see this point of view emerging. It's convenient for those who feel resentful by  this trend and gives some kind of moral satisfaction. People in general are lazy  and our mind usually tries to absorb ideas in a way that doesn't alter an  existing picture of the world much. And so it sticks.&lt;/p&gt;   &lt;p&gt;Plus, there are always plenty of people who tell the horrors about how bad  the source code was that these "code monkeys" produce. And if it's not  bad then it must stolen from some GPL product googled off the web. Rendering the  developers not simply unprofessional but practically unlawful.&lt;/p&gt;   &lt;p align="left"&gt;And yes, there there are &lt;i&gt;indeed&lt;/i&gt; plenty of supportive  cases against the "code monkeys" so calling this a &lt;i&gt;legend&lt;/i&gt; is  probably a stretch. But a simplification it is. And yet, to throw in some anecdotic  kind of proof, the &lt;i&gt;worst&lt;/i&gt; code base I've dealt with was handled to us from  "on-shore" and the best programmers I have the luck to work with were  sitting next to me.&lt;/p&gt;   &lt;p&gt;To repeat, I'm not to defend offshore model in general. It &lt;i&gt;is&lt;/i&gt;  inefficient and currently viable only because of the peculiarities of the  world's economic and drastic changes that were made in the last 50 years. But  people are just that - people. There are cultural, historical, economical and  other differences, but they are minor and has little inherent impact on one's  professional abilities. Of course, these differences do impact the opportunities  one may have to realize himself.&lt;/p&gt;  &lt;p&gt;Amen.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110934423181903604?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110934423181903604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110934423181903604' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110934423181903604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110934423181903604'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/02/good-bad-and-ugly.html' title='The good, the bad and the ugly'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110925547924301238</id><published>2005-02-24T16:28:00.000+02:00</published><updated>2005-02-24T16:31:19.246+02:00</updated><title type='text'>Blog of the week</title><content type='html'>Added &lt;a href="http://www.pyrasun.com/mike/mt/"&gt;Mike Spille&lt;/a&gt; to my blogroll. A couple of highlighting posts: &lt;a href="http://www.theserverside.com/blogs/showblog.tss?id=Unitized"&gt;Don't Let Yourself Get Unitized&lt;/a&gt; and &lt;a href="http://www.pyrasun.com/mike/mt/archives/2004/12/23/22.37.00/index.html"&gt;Prevayler: There really must be one born every minute&lt;/a&gt;. Amazing reading.&lt;br /&gt;&lt;br /&gt;Unfortunately, his full-text feed is badly formatted, so end up subscribing to excerpts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110925547924301238?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110925547924301238/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110925547924301238' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110925547924301238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110925547924301238'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/02/blog-of-week.html' title='Blog of the week'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110899448508613911</id><published>2005-02-21T15:59:00.000+02:00</published><updated>2005-02-21T16:01:25.086+02:00</updated><title type='text'>announcing ua-devtalk</title><content type='html'>Just in case I've been reading by someone from Ukraine...&lt;br /&gt;&lt;br /&gt;I invite you to join a &lt;a href="http://groups-beta.google.com/group/ua-devtalk"&gt;ua-devtalk google group&lt;/a&gt;. It's an attempt to gather and organize ukrainian IT professionals community.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110899448508613911?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110899448508613911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110899448508613911' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110899448508613911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110899448508613911'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/02/announcing-ua-devtalk.html' title='announcing ua-devtalk'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110899372686178765</id><published>2005-02-21T15:43:00.000+02:00</published><updated>2005-03-04T19:03:57.143+02:00</updated><title type='text'>Project postmortem</title><content type='html'>As my &lt;a href="http://postman.com.ua/"&gt;project&lt;/a&gt; reached 1.0 milestone I decided to run a postmortem. This blog post contains some parts of the lengthy postmortem document I actually wrote. I excluded project details/conclusions to protect my IP (so to say ;-)) from potential competitors but kept sections which casual reader may find useful.&lt;br /&gt;&lt;br /&gt;Btw, if you're interested in postmortems in general, here are some links I found myself useful:&lt;br /&gt;&lt;ul&gt; &lt;li&gt;&lt;a href="http://www.dexterity.com/articles/postmortem.htm"&gt;Conducting a Project Postmortem&lt;/a&gt; by Steve Pavlina. Concise and up-to-the-point. I used it as a table of contents for my own postmortem.&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.gamesfromwithin.com/articles/0404/000019.html"&gt; Postmortems: Looking Back, Looking Ahead&lt;/a&gt;. More coupled to games development but still a very interesting reading.&lt;/li&gt; &lt;li&gt; Nice &lt;a href="http://www.dir.state.tx.us/eod/qa/download.htm"&gt;repository&lt;/a&gt; of all kind of project templates and guidelines, including &lt;a href="http://www.dir.state.tx.us/eod/qa/evaluate/shortfm.htm"&gt;post project review questionnaire&lt;/a&gt;.  &lt;/li&gt; &lt;/ul&gt;And a couple of seemingly interesting books (haven't had a chance to read them&lt;br /&gt;&lt;ul&gt; &lt;li&gt; &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0932633447/ref=nosim/maxischenblog-20"&gt;Project Retrospectives: A Handbook for Team Reviews&lt;/a&gt; by Norman L. Kerth&lt;/li&gt; &lt;li&gt; &lt;a href="http://www.amazon.com/exec/obidos/ASIN/1578202140/ref=nosim/maxischenblog-20"&gt;Postmortems from Game Developer: Insights from the Developers of Unreal Tournament, Black and White, Age of Empires, and Other Top-Selling Games&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;I'm still not sure whether I should have published this, but I'm driven mainly by curiosity - we'll see if this will lead to anything.&lt;br /&gt;&lt;br /&gt;So, let's end with the foreword, here it goes.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;h2&gt;List of known problems&lt;/h2&gt;Overall, there were a few bugs discovered during and after the deployment. Partly this is because the system is new, small, freshly developed and thus completely understood. Partly (hope so) because I adhered to test-heavy development process.&lt;br /&gt;&lt;ul&gt;&lt;a name="sqlobject_problem"&gt;&lt;/a&gt;&lt;li&gt;&lt;b&gt;Database connection stuck&lt;/b&gt;. This was most severe one: site was dysfunctional for several days before I noticed the problem. Luckily, quick fix was trivial - just have to restart an AppServer. The problem was with SQLObject's handling of db connections - if the db was restarted any further attempts to call a db operation lead to OperationalError exception. Unfortunately, I didn't (yet) find a solution to fix the root cause.&lt;/li&gt; &lt;li&gt;&lt;b&gt;HTML mangling in XSL transformations&lt;/b&gt;. Another problem (kind of annoyance, really) is related to two-step XSL transformation algorithm employed while rendering web pages. Second step was folding a pair of empty tags into single empty one, e.g. &amp;lt;p&amp;gt; &amp;lt;p&amp;gt; was folded into &amp;lt;p/&amp;gt;. This turned to be a big problem for some HTML tags as it caused the page to rendered incorrectly. The problematic tags I had to "fix" were &lt;code&gt;TEXTAREA&lt;/code&gt;, &lt;code&gt;TABLE&lt;/code&gt;, &lt;code&gt;TD&lt;/code&gt;.  I failed to fix the&lt;br /&gt;   root cause again, and ended with inserting non-breakable space symbol to prevent XSL for doing the fold.  &lt;/li&gt; &lt;/ul&gt;That's it for a list of known problems.&lt;br /&gt;&lt;h2&gt;What went right&lt;/h2&gt;Here is a list of thing that I think I done right or had the luck to have it right:&lt;br /&gt;&lt;ul&gt; &lt;li&gt;&lt;b&gt;Development platform/tools&lt;/b&gt;. I was already a rather experienced Python programmer and had used Apache/WebKit in several projects before. It didn't reveal any bad surprises during development and I feel this was a solid choice. The only new library I used for this project was SQLObject to handle object's persistence task. While I had some minor problems and one &lt;a href="http://www.blogger.com/post-create.g?blogID=8128258#sqlobject_problem"&gt;major one&lt;/a&gt; with it certainly was a net win for me and saved considerable amount of time.  &lt;/li&gt; &lt;li&gt;&lt;b&gt;Software quality&lt;/b&gt;. There were very few bugs discovered during and after the deployment. I attribute this (partly) to a test-heavy development process: the unit-test ratio coverage was at constantly at about 95%.&lt;/li&gt; &lt;li&gt;&lt;b&gt;Good architecture&lt;/b&gt;. The system is organized in a simple, solid and straightforward way, providing a good starting point for further evolution. All major interfaces with third-party code, such as db persistence, web application server, XML toolkits&lt;br /&gt;are properly abstracted. Of course, there are some skeletons buried here and there but overall I'm quite satisfied with it.&lt;/li&gt; &lt;li&gt;&lt;b&gt;Project management tool&lt;/b&gt;.  Following Joel &lt;a href="http://www.joelonsoftware.com/articles/fog0000000245.html"&gt;advice&lt;/a&gt;, I decided on Excel as my project management tool. It worked out nice. Not that it went without any friction, but good enough and with minimal overhead. I explored some other alternatives, such as: Microsoft Project, plain-text file with outline mode (in &lt;a href="http://vim.sourceforge.net/"&gt;Vim&lt;/a&gt;) or some Palm-based project tool. But in retrospection, Excel seems like a right choice.  &lt;/li&gt; &lt;li&gt;&lt;b&gt;Project management process&lt;/b&gt;. Being a business head / programming team in a single person meant I could judge very accurately what should be done next. In previous projects, lacking some important details from business context, we (a development team) often found ourselves spent a lot of time and efforts on things that were not,&lt;br /&gt;strictly speaking, very important or sometimes even needed at all. The ability to guide development from the business perspective was very satisfying. I didn't understood this at first but in the end really appreciated it. The trick is to not getting charmed by technical problems but to concentrate on users and their needs. &lt;/li&gt; &lt;li&gt;&lt;b&gt;Hosting provider&lt;/b&gt;. Being a web-project newbie, I had to figure out things like hosting, domain name registrations, etc. Luckily, my choice of &lt;a href="http://python-hosting.com/"&gt;hosting provider&lt;/a&gt; was solid and I have no problems with it.&lt;/li&gt; &lt;li&gt;&lt;b&gt;Credit card processing&lt;/b&gt;. Certainly it made little sense to shot for a full card-processing routing &lt;i&gt;on-site&lt;/i&gt; so I had to select a third-party vendor that would do this for me. I selected &lt;a href="http://2checkout.com/"&gt;2CheckOut&lt;/a&gt; and it was OK for me. At least, it had successfully processed a number of sales for me with relatively easy setup.&lt;/li&gt; &lt;/ul&gt;&lt;h2&gt;What went wrong&lt;/h2&gt;&lt;ul&gt; &lt;li&gt; &lt;b&gt;Business opportunity evaluation.&lt;/b&gt; It's quite possible that I shouldn't blame my lack of marketing skills for too much. There is a valid chance that the potential market is so small that no amount of marketing efforts would lead to a meaningful results. I had to think on project's feasibility harder. &lt;/li&gt; &lt;li&gt;&lt;b&gt;Grossly overengineered solution.&lt;/b&gt; An awful lot of time (initially) was spent on things I didn't really need (yes, that YAGNI again). A remarkable example been a sophisticated, XSL-based, multilingual site generator, which produced all site's static pages in all supported languages. I ended up with a fully dynamic site and moreover, uni-language. Hence the effort was an (almost) complete waste of time. In a retrospect, I could have reduced dev time in about 5 times and still deliver a functional solution. &lt;/li&gt; &lt;li&gt;&lt;b&gt;Marketing strategy.&lt;/b&gt; Well, I probably should say it was absent. Mind you, I have an idea but after it failed to bring expected results I&lt;br /&gt; felt short.&lt;/li&gt; &lt;li&gt;&lt;b&gt;Site design.&lt;/b&gt; Being a one-man project and lacking good design skills I ended up with a poorly-designed (even for my taste) site. Moreover, without proficiency in web frontpage technologies (like CSS) countless number of times I found myself in a situation where I &lt;i&gt;knew&lt;/i&gt; what I'd like the page to look like but don't know &lt;i&gt;how&lt;/i&gt; to implement this.&lt;/li&gt;  &lt;li&gt;&lt;b&gt;Credit card processing&lt;/b&gt;. I did mention this in a &lt;i&gt;what went right&lt;/i&gt; section and now I mention it here. While 2CheckOut worked OK for me it is not that great choice for several reasons, esp. compared with another one, like &lt;a href="http://ikobo.com/"&gt;iKobo&lt;/a&gt; (which I didn't know about at the time). The weak points of 2CheckOut for me were: up-front setup fee, relatively big per-transaction fee and very cumbersome and expensive way to transfer money from 2CheckOut account if you're outside USA/Canada (like me). &lt;/li&gt; &lt;/ul&gt;That's it.&lt;br /&gt;&lt;br /&gt;While I intended to list at least ten things I don't know what else should I mention. The above items were a real problems and other difficulties I had are minor in comparison.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110899372686178765?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110899372686178765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110899372686178765' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110899372686178765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110899372686178765'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/02/project-postmortem.html' title='Project postmortem'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110837558482728384</id><published>2005-02-14T12:05:00.000+02:00</published><updated>2005-02-14T12:06:24.830+02:00</updated><title type='text'>Concurrent Java books</title><content type='html'>Recently I has been involved in a Java project and decided to refresh my multithread-programming skills and, more importantly, to grok how it gets done in Java.&lt;br /&gt;&lt;br /&gt;I'm currently reading &lt;a href="http://www.amazon.com/exec/obidos/ASIN/047084437X/ref=nosim/maxischenblog"&gt;Concurrent and Real-Time Programming in Java&lt;/a&gt; by Andy Wellings. While the crux of the book is real-time system programming, it devotes about a third to the generally applicable concurrency topics and how they are exploited in Java. Plus, it even covers concurrency-related changes introduced in Java 1.5.&lt;br /&gt;&lt;br /&gt;This is nice, especially compared to the latest edition of the classic &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0201310090/ref=nosim/maxischenblog"&gt;Concurrent Programming in Java: Design Principles and Patterns&lt;/a&gt;, published in ... 1999! There are rumours that a third edition is underway, but until then this book could serve as a good, modern and concise introduction to concurrent programming in Java.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110837558482728384?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110837558482728384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110837558482728384' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110837558482728384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110837558482728384'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/02/concurrent-java-books.html' title='Concurrent Java books'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110837551247386600</id><published>2005-02-14T12:04:00.000+02:00</published><updated>2005-02-14T12:05:12.476+02:00</updated><title type='text'>A pressure for concurrency</title><content type='html'>Herb Sutter published an article called &lt;a href="http://www.gotw.ca/publications/concurrency-ddj.htm"&gt;The Free Lunch Is Over: A Fundamental Turn Toward Concurrency in Software&lt;/a&gt;. It's a fascinating reading in which he argues we (the programmers) are now facing the next major paradigm shift since introduction of object-oriented programming. The reason?&lt;br /&gt;&lt;blockquote&gt;  Applications will increasingly need to be concurrent if they want to fully exploit CPU throughput gains.&lt;br /&gt;&lt;/blockquote&gt;And this is caused by the new hardware trend towards multicore systems, in contrast with CPU clock speed wars we had till recently.&lt;br /&gt;&lt;br /&gt;IMO, a need for concurrent progaramming would impact mostly the "high" end of the programmers spectrum: system programming (OS, RDBMS, Web servers, game engines, etc.) and library authors. For many (most?) end-user application the execution speed is not crucial for a long time.&lt;br /&gt;&lt;br /&gt;PS: It will be interesting to watch out how tooling vendors react to this trend. For instance, CPython has an infamous GIL which looks like a real obstacle for Python programs on multicore systems.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110837551247386600?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110837551247386600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110837551247386600' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110837551247386600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110837551247386600'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/02/pressure-for-concurrency.html' title='A pressure for concurrency'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110810875810909672</id><published>2005-02-11T09:57:00.000+02:00</published><updated>2007-04-02T21:38:17.363+03:00</updated><title type='text'>Java may not be that bad after all</title><content type='html'>There is a popular belief (which I'm not going to argue with) that programmer's productivity in Java is "inferior" to that in more dynamic languages, like Python.&lt;br /&gt;&lt;br /&gt;That's OK but Python seems "inferior" to Java when it comes to innovations (in the environment, not in the language itself). There are countless (ok, shall I say &lt;i&gt;many&lt;/i&gt;?) python packages which started as a port of some Java library. Those that come to mind first: unittest and logging packages, which are now even part of the Python standard library. Other examples: PyContainer, PyFIT, Cheetah, you name it. To some degree, larger frameworks often borrow as well: WebKit (servlet, request/response architecture), pyworks (similar to webworks), probably others.&lt;br /&gt;&lt;br /&gt;Sometimes this pale imitations evolve into more pythonic things, sometimes it got replaced by built-from-scratch better alternatives (like, say, py.test). Of course, there are genuine python packages which shine even compared with the brightest Java counterparts (Twisted comes to mind first),  but these are comparatively few.&lt;br /&gt;&lt;br /&gt;The ideas' circulation between languages/platforms is a good thing and there is nothing wrong with it. Still, why Python-Java relationship are so asymmetric?  Is it just reflects the difference in size of the respective communities? Is it something else here? Or are my perception skewed?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110810875810909672?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110810875810909672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110810875810909672' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110810875810909672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110810875810909672'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/02/java-may-not-be-that-bad-after-all.html' title='Java may not be that bad after all'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110768965083160298</id><published>2005-02-06T13:32:00.000+02:00</published><updated>2005-02-06T13:34:10.830+02:00</updated><title type='text'>Efficient XML processing in Python</title><content type='html'>In a recent article &lt;a href="http://www.xml.com/pub/a/2004/07/28/py-xml.html"&gt;Decomposition, Process, Recomposition&lt;/a&gt; on xml.com, Uche Ogbuji talks about strategies for processing large XML documents in Python. This led me to recall my own experience with processing of multimegabytes XML documents.&lt;br /&gt;&lt;br /&gt;In general, there are at least three popular strategies to deal with XML in Python: SAX-based, DOM-based and, er, shall I say, &lt;i&gt;pythonic&lt;/i&gt;. SAX realizes a speedy and memory-light approach but which shifts the burden of keeping a processing context onto programmer. DOM gives cross-language, standard, verbose and memory-hungry strategy which scale poorly for large documents. By &lt;i&gt;pythonic&lt;/i&gt; I meant a range of libraries, like &lt;a href="http://gnosis.cx/download/"&gt;gnosis.xml.objectify&lt;/a&gt;, &lt;a href="http://effbot.org/downloads/#elementtree"&gt;ElementTree&lt;/a&gt;, &lt;a href="http://www.aaronsw.com/2002/tramp"&gt;xmltramp&lt;/a&gt; which share a common attitude to provide a nice, Python-friendly API.&lt;br /&gt;&lt;br /&gt;I used ElementTree (and recently, it's new, &lt;a href="http://effbot.org/downloads/#cElementTree"&gt;C-based re-incarnation&lt;/a&gt;) library. The task was as follows: given a large (~ 10Mb) XML document of some complex structure the program had to significantly "extend" it with new information and write to a new file. This new data was partially specified using the external sources and partially computed from the document itself, according to a bunch of arcane rules. Computation involved several traversals along the document structure to gather needed information.&lt;br /&gt;&lt;br /&gt;The program (and transformation) itself was just a single link in a lengthy chain of transformations. There were other parts, written as XSLT procedures and DOM-based Javascripts that used to perform other&lt;br /&gt;&lt;br /&gt;A &lt;i&gt;decompose, process, recompose&lt;/i&gt; approach, outlined in the article was realized by the ElementTree itself, my task was only to provide necessarily processing steps. In contrast with SAX, ElementTree builds an accurate in-memory presentation of the entire XML document, but unlike DOM, it's memory footprint grows much more slowly with the size of document, thanks to efficient representation. This gives the best of both worlds: versatile and convenient presentation model with good scalability for large documents.&lt;br /&gt;&lt;br /&gt;My only major complaint was the lack of XPath support. While ElementTree does offer some very limited support for basic XPath expression it goes a long way towards a full-blown implementation. Thus I was forced to write a bunch of custom &lt;i&gt;finders&lt;/i&gt; where a single XPath would do the trick. Luckily, it's pretty straightforward to write them.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110768965083160298?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110768965083160298/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110768965083160298' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110768965083160298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110768965083160298'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/02/efficient-xml-processing-in-python.html' title='Efficient XML processing in Python'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110658710589607741</id><published>2005-01-24T19:15:00.000+02:00</published><updated>2005-01-24T19:18:25.896+02:00</updated><title type='text'>Exception-based code antipatterns</title><content type='html'>To continue the topic of exception-based code, there &lt;i&gt;are&lt;/i&gt; cases when bad code is easy to spot. For example, this snippet is almost always inappropriate:&lt;br /&gt;&lt;pre&gt;  try:&lt;br /&gt;   # do something&lt;br /&gt; except: # catch any possible exception&lt;br /&gt;   pass  # and just ignore it&lt;br /&gt;&lt;/pre&gt;Semantically, this is equals to error-code-based code with no error checking. It has valid use cases but there are a few.&lt;br /&gt;&lt;br /&gt;Another antipattern, more coupled specifically to Python:&lt;br /&gt;&lt;pre&gt;  try:&lt;br /&gt;   # do something&lt;br /&gt; except Exception, e:&lt;br /&gt;   # handle it&lt;br /&gt;&lt;/pre&gt;Most of the time you should catch specific exception class(es) instead of base Exception class. The problem with this approach is that in Python, &lt;i&gt;everything&lt;/i&gt; is reported through exception mechanism, including syntax errors, keyboard interrupts, program exit, memory errors, etc. And usually you &lt;i&gt;don't&lt;/i&gt; want to catch these kind of exceptional conditions.&lt;br /&gt;&lt;br /&gt;This catch-all is often a sign of a sloppy programming, where a programmer was too lazy to list actual exception classes to catch or the calling code is known to raise all kind of exception and there is no documented exception class to look for (which is often the case for poorly written/abstracted modules).&lt;br /&gt;&lt;br /&gt;Unfortunately, advise to catch specific exception classes has a drawback as well. When the calling code is updated it could raise new types of exception and thus handling code must be updated as well. For third-party code, this risk often could be mitigated by abstracting external interface and re-warping (and documentin) use of exception classes.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110658710589607741?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110658710589607741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110658710589607741' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110658710589607741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110658710589607741'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/01/exception-based-code-antipatterns.html' title='Exception-based code antipatterns'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110658688724692659</id><published>2005-01-24T19:11:00.000+02:00</published><updated>2005-01-24T19:14:47.246+02:00</updated><title type='text'>Exception-based code</title><content type='html'>In a recent &lt;a href="http://weblogs.asp.net/oldnewthing/archive/2005/01/14/352949.aspx"&gt;post&lt;/a&gt;, Raymond Chen writes about an important difference between plain old code from pre-exceptions age, that used to return special error codes to indicate errors and modern exception-based code:&lt;br /&gt;&lt;blockquote&gt;...it is extraordinarily difficult to see the difference between bad exception-based code and not-bad exception-based code.&lt;/blockquote&gt;And then he concludes:&lt;br /&gt;&lt;blockquote&gt;Consequently, when I write code that is exception-based, I do not have the luxury of writing bad code first and then making it not-bad later. If I did that, I wouldn't be able to find the bad code again, since it looks almost identical to not-bad code.&lt;br /&gt;&lt;/blockquote&gt;Arguably, exception-based code is &lt;i&gt;safer&lt;/i&gt; because it fails early, as soon as exception is raised at the point of failure. Contrast this with error-checking code where sloppy programming style (not checking for a error code explicitly) could result in an &lt;a href="http://weblogs.asp.net/oldnewthing/archive/2005/01/18/355177.aspx"&gt;obscure failure&lt;/a&gt; in a seemingly unrelated part of the program much later. On the other hand, sloppy programming style for exception-based code is more damaging, as you'd have to review the whole codebase line-by-line to find all potential places where exception-handling code need to be added.&lt;br /&gt;&lt;br /&gt;When I started practicing TDD I often wrote simplest possible implementation that was arguably &lt;i&gt;too&lt;/i&gt; simple with regard to exceptions. As I discovered over time, usually it's more&lt;br /&gt;efficient to write necessarily exception-handling code (if any) right from the start. If I'm in hurry or not sure how to handle a possible exception I at least put in an assertion guard.&lt;br /&gt;&lt;br /&gt;But the killer feature of exception-based code is this: &lt;i&gt;programmer is freed from error-checking most of the time&lt;/i&gt;. While you do have to be careful while writing code and every line of code is a potential source of an exception, typically there is a relatively few places where you add&lt;br /&gt;exception-handling code: external resources' handling, inter-system interfaces, input/output with the outer world, etc.&lt;br /&gt;&lt;br /&gt;Overall, exception seems to be a net benefit. Result is a more stable program (fails early) with less efforts (fewer places to do error handling). Yes, it's hard to write a good exception-based code, harder then write a good error-code-based code but who said it's going to be easy?&lt;br /&gt;&lt;br /&gt;There is no such thing as a free launch, after all.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110658688724692659?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110658688724692659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110658688724692659' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110658688724692659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110658688724692659'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2005/01/exception-based-code.html' title='Exception-based code'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110432484351988403</id><published>2004-12-29T14:51:00.000+02:00</published><updated>2004-12-29T14:54:03.520+02:00</updated><title type='text'>quote of the week</title><content type='html'>&lt;span style="font-style: italic;"&gt;Whatever works is good enough. If you can understand what the customer wants, you win. Of course, if your customer doesn't know what they want, then it is like arguing with your wife: no matter how right you are, you are still sleeping on the couch.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://discuss.joelonsoftware.com/default.asp?design.4.46851.12"&gt;Source&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110432484351988403?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110432484351988403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110432484351988403' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110432484351988403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110432484351988403'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/12/quote-of-week.html' title='quote of the week'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110423455762594538</id><published>2004-12-28T13:46:00.000+02:00</published><updated>2004-12-28T13:49:17.626+02:00</updated><title type='text'>Optional Static Typing in Python</title><content type='html'>Guido van Rossum talks about &lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=85551"&gt;Adding Optional Static Typing to Python&lt;/a&gt;. Here is my take on it.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;about "Compile Time vs. Run Time".&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I 'd be completely happy if the type check would be performed at run-time, not on compile time or import time. After all, that's how a Python developer expects the things to be.&lt;br /&gt;&lt;br /&gt;You may argue that's this doesnt buy you much but I disagree. ;-)&lt;br /&gt;&lt;br /&gt;Firstly, it's a first and logical evolution from the current state of affairs. Secondly, it &lt;i&gt;does&lt;/i&gt; provide some tangible benefits.&lt;br /&gt;&lt;br /&gt;Currently, many developers are used to write something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def foo(g,a):&lt;br /&gt;   assert isinstance(a, str), a&lt;br /&gt;   assert callable(g)&lt;br /&gt;   ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Strictly speaking, these assertions are not required, but they do help to detect errors as early as possible which is  a sound engineering practice.&lt;br /&gt;&lt;br /&gt;With the help of type interferencing or manifest typing we could free programmer from this tedious work, if he wants to.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Duck typing&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;What I really wanted to see in Python is an explicit support of DuckTyping, which is an integral part of type system anyway. The problem is IMO with a reasonable and helpfule implementation.&lt;br /&gt;&lt;br /&gt;For some, a type interferencing (a sketch from the Haskell type system) may help. For instance if the foo() takes parameter a and then invokes method bar() on that parameter, compiler (or VM) could check (at least, at run-time) that the argument passed to foo() does have a callable bar attribute.&lt;br /&gt;&lt;br /&gt;This also can be extended on operator overloading, such as __add__ or __lshift__.&lt;br /&gt;&lt;br /&gt;And my point is, even with such a limited form (run-time checking of automatically derived type information), it could be a big step forward.&lt;br /&gt;&lt;br /&gt;Optional type annotation (embedded in the source code) could be a next step.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110423455762594538?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110423455762594538/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110423455762594538' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110423455762594538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110423455762594538'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/12/optional-static-typing-in-python.html' title='Optional Static Typing in Python'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110337298802204859</id><published>2004-12-18T14:18:00.000+02:00</published><updated>2004-12-18T14:29:48.023+02:00</updated><title type='text'>simple and extensible blogging tool in Python</title><content type='html'>I wonder, can anyone recommend some simple and extensible blogging tool, written in Python? The idea is to retrofit site News section to use a some kind of [primitive] blogging system, instead of hand-written RSS 2.0 feed and hand-made modification to the site's front page.&lt;br /&gt;&lt;br /&gt;To realize this idea I'm looking for some, preferably python-based tool, which could be easily plugged-in into my custom presentation, authentication and persistance modules (ideally) or at least I should be able to provide my own presentation. The API is minimalistic: add post (item), add comment, get item as XML,  get RSS/Atom feed and that's basically all.&lt;br /&gt;&lt;br /&gt;Any recommendations?&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110337298802204859?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110337298802204859/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110337298802204859' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110337298802204859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110337298802204859'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/12/simple-and-extensible-blogging-tool-in.html' title='simple and extensible blogging tool in Python'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110320170504427183</id><published>2004-12-16T14:05:00.000+02:00</published><updated>2004-12-16T14:55:05.043+02:00</updated><title type='text'>Palm may be not dead after all</title><content type='html'>In the course of the recent events in the Palm world (like infamous T5 release or Sony decision to exit PDA market), &lt;a href="http://laurens.typepad.com/sunrise/2004/11/palmos_viewer_a.html"&gt;many&lt;/a&gt;, myself included, start seeing the PalmOS platform as an obvious loser. It will surely take a lot of hardwork and luck for Palm to break this negative trend, but these &lt;a href="http://www.mobileread.com/forums/showthread.php?t=2862"&gt;insiders' comments on PalmOS for Linux project&lt;/a&gt; give me some hope. Not that I care a lot, but still.&lt;br /&gt;&lt;br /&gt;It'd interesting to watch whether PalmSource succeed to repeat Apple's indisputable victory with it's Mac OS X. And I wonder what's happened with BeOS kernel that's already in the disposition of PalmSource's engineers? Has it been abandoned in preference with Linux?&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110320170504427183?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110320170504427183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110320170504427183' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110320170504427183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110320170504427183'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/12/palm-may-be-not-dead-after-all.html' title='Palm may be not dead after all'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110232460037035875</id><published>2004-12-06T10:56:00.000+02:00</published><updated>2004-12-06T11:16:40.370+02:00</updated><title type='text'>strategy for acceptance tests</title><content type='html'>With the version 1.0 of my &lt;a href="http://postman.com.ua/"&gt;project&lt;/a&gt; out there, I have a planning session to decided what to do next. Of course, I'm going to start working on release 1.1 now but in parallel with that, I intend to work on the acceptance (functional) test suite which currently drags behind due to the 1.0 release schedule pressure.&lt;br /&gt;&lt;br /&gt;Recent Robert Martin's post in the &lt;a href="http://groups.yahoo.com/group/fitnesse/"&gt;FIT mailing list&lt;/a&gt; summarises my strategy for these kind of tests nicely:&lt;br /&gt;&lt;blockquote&gt;...[I] INSISTED that the majority of automated acceptance tests be run JUST BELOW the GUI.  (i.e. not THROUGH the GUI).&lt;br /&gt;&lt;br /&gt;Some acceptance tests, those that test GUI functionality only, MUST be run through the GUI. But I don't want any business rules tested through the GUI.&lt;br /&gt;&lt;br /&gt;Of course QA must also get their fingers and eyes on the system. I don't want them doing this with any scripts. Anything that can be scripted should be automated. Rather, I want the QA folks using their ingenuity and creativity to manually operate the GUI and figure out devious ways to break the system.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110232460037035875?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110232460037035875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110232460037035875' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110232460037035875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110232460037035875'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/12/strategy-for-acceptance-tests.html' title='strategy for acceptance tests'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110208521267274985</id><published>2004-12-03T16:36:00.000+02:00</published><updated>2004-12-03T16:46:52.673+02:00</updated><title type='text'>Blog of the week</title><content type='html'> Found a remarkable blogger this week - &lt;a href="http://dirtsimple.org/"&gt;Phillip J. Eby&lt;/a&gt;, a primary author of the ambitious &lt;a href="http://peak.telecommunity.com/"&gt;python framework for enterprise applications&lt;/a&gt;.  I doubt I would use his framework anytime soon, but his general thoughts on python and software development in general are much appreciated.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110208521267274985?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110208521267274985/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110208521267274985' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110208521267274985'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110208521267274985'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/12/blog-of-week.html' title='Blog of the week'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110183202443641726</id><published>2004-11-30T18:07:00.000+02:00</published><updated>2004-11-30T18:27:04.436+02:00</updated><title type='text'>Deleting code</title><content type='html'>Just encountered a nice post titled &lt;span class="headslug"&gt;&lt;a href="http://www.nedbatchelder.com/text/deleting-code.html"&gt;Deleting code&lt;/a&gt; by &lt;/span&gt;&lt;span class="path"&gt;&lt;a href="http://www.nedbatchelder.com/index.html"&gt;Ned Batchelder&lt;/a&gt;.  I mostly share author's attitude toward the subject so there is no point to argue. Just have a small addition regarding the code you wrote as experimentation or in anticipation for something and then discover that YAGNI. In this situation I often found myself not simply delete this code but move it to some temporary file&lt;/span&gt;&lt;span class="path"&gt; instead&lt;/span&gt;&lt;span class="path"&gt;.&lt;br /&gt;&lt;br /&gt;By convention, this file is often called scratch.&lt;something&gt; or just x. Here are the various code snippets that were purged from the production code or even never managed to get there got accumulated over the time.  I found it easier and simpler to look through this file than to rely on SCM.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110183202443641726?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110183202443641726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110183202443641726' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110183202443641726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110183202443641726'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/11/deleting-code.html' title='Deleting code'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110077572996206217</id><published>2004-11-27T13:26:00.000+02:00</published><updated>2004-11-27T21:44:56.210+02:00</updated><title type='text'>Ready? Set. Ship!</title><content type='html'>For several last months, I've been quitely working on my small sideline project which I'm now &lt;strike&gt;ready&lt;/strike&gt; decided to get out of the door. This is my first take on the entrepreneurial-like venture and I have no idea how and where it would land and whether it would take off at all. But even if it won't succeed I glad I managed to drive the project to the point where it's shipped to the wild and not hung as a vaporware forever.&lt;br /&gt;&lt;br /&gt;In spite of a lengthy feature sheet laying in front of me I decided to ship the most basic, bare-bones version that is (potentially) useful to my audience. There is a certain risk that such a primitive version would scare away prospective customers but the risk of developing for too long without being exposed to the real-life feedback is IMO much bigger. If there is any market at all for this kind of service it would shown itself even with such a limited implementation. Or at least, this is what I'm hoping for. ;-)&lt;br /&gt;&lt;br /&gt;Oh, I just re-read the post and noticed I didn't even mentioned what the service is. ;-) It's located at the &lt;a href="http://postman.com.ua/"&gt;http://postman.com.ua&lt;/a&gt; and, specifically for google bots, allows you to &lt;a href="http://postman.com.ua/"&gt;send photos, letters and postcard to your relatives, friends and business partners in Ukraine&lt;/a&gt;.  Actually, you could only send photos for now but the rest will follow (crossed my fingers).&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110077572996206217?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110077572996206217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110077572996206217' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110077572996206217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110077572996206217'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/11/ready-set-ship.html' title='Ready? Set. Ship!'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110121324032475083</id><published>2004-11-23T13:24:00.000+02:00</published><updated>2004-11-23T14:34:00.323+02:00</updated><title type='text'>Two step view pattern implementation with XSLT</title><content type='html'>For the project I'm currently working on (in Python/WebKit) I decided to use an XSL technology to handle a presentation issue, instead of a more stock options like &lt;a href="http://www.cheetahtemplate.org/"&gt;Cheetah&lt;/a&gt; or &lt;a href="http://webware.sourceforge.net/Webware/PSP/Docs/"&gt;PSP&lt;/a&gt;. The main reason for this was to escape from using niche solutions and try to employ more mainstreamo ones instead, leveraging benefits that comes from this.&lt;br /&gt;&lt;br /&gt;For the presentation logic itself, I used a &lt;a href="http://www.martinfowler.com/eaaCatalog/twoStepView.html"&gt;Two-Step View&lt;/a&gt; pattern, publicized by &lt;a href="http://www.martinfowler.com/"&gt;Martin Fowler's&lt;/a&gt; excellent book on &lt;a href="http://www.amazon.com/exec/obidos/asin/0321127420/maxischenblog-20"&gt;enterprise patterns&lt;/a&gt;. The original implementation actually performed two xsl transformation. First one with a page-specific template, which were passed a page-specific data as XML input string and/or parameters dict. It returned an xml with a "logical markup" which were then passed to another xsl template, called site.xsl which is global per site and transformed this xml-based markup into proper (X)HTML.&lt;br /&gt;&lt;br /&gt;It worked OK, except the fact that I had to call to XSL engine &lt;span style="font-style: italic;"&gt;twice&lt;/span&gt; per page, in order to get a resulting (X)HTML which taken a considerable amount of time (about 0.2-0.4 seconds in total).&lt;br /&gt;But recently, due to a nice &lt;a href="http://www-106.ibm.com/developerworks/xml/library/x-tipxsltmp.html"&gt;tip&lt;/a&gt; from 4Suite co-author, I managed to fold these two steps into a single xsl transformation. The trick is a node-set() function which allows you apply the XSL engine to a fragment of output tree already produced.&lt;br /&gt;&lt;br /&gt;Here is except from my implementation. The algorithm is as follows:&lt;br /&gt;&lt;ol&gt;   &lt;li&gt;Build a "logical markup" tree and save it to a variable.&lt;/li&gt;   &lt;li&gt;Apply an imported templates to transform this to required output format.&lt;br /&gt;&lt;/li&gt; &lt;/ol&gt;&lt;br /&gt;&lt;pre class="code" style="margin: 6px;"&gt;&lt;span class="xml_pi"&gt;&lt;/span&gt;&lt;span class="xml_tag"&gt;&amp;lt;xsl:import href=&lt;span class="literal"&gt;"site.xsl"&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="xml_tag"&gt;&amp;lt;xsl:output method=&lt;span class="literal"&gt;"xml"&lt;/span&gt;&lt;br /&gt;doctype-public=&lt;span class="literal"&gt;"-//W3C//DTD XHTML 1.0 Strict//EN"&lt;/span&gt;&lt;br /&gt;doctype-system=&lt;span class="literal"&gt;"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&lt;/span&gt;&lt;br /&gt;encoding=&lt;span class="literal"&gt;"UTF-8"&lt;/span&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="xml_tag"&gt;&amp;lt;xsl:template match=&lt;span class="literal"&gt;"/"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="xml_tag"&gt;&amp;lt;xsl:variable name=&lt;span class="literal"&gt;"view"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="xml_tag"&gt;&amp;lt;xsl:call-template name=&lt;span class="literal"&gt;"logical"&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="xml_tag"&gt;&amp;lt;/xsl:variable&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="xml_tag"&gt;&amp;lt;xsl:apply-templates select=&lt;span class="literal"&gt;"exslt:node-set($view)"&lt;/span&gt; mode=&lt;span class="literal"&gt;"view"&lt;/span&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="xml_tag"&gt;&amp;lt;/xsl:template&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="xml_tag"&gt;&amp;lt;xsl:template name=&lt;span class="literal"&gt;"logical"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="xml_tag"&gt;&amp;lt;view:standard-page title=&lt;span class="literal"&gt;"Test page"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="xml_tag"&gt;&amp;lt;view:content&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="xml_tag"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This is a  test page&lt;span class="xml_tag"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="xml_tag"&gt;&amp;lt;/view:content&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="xml_tag"&gt;&amp;lt;/view:standard-page&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="xml_tag"&gt;&amp;lt;/xsl:template&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;And here is a greatly simplified version of the site.xsl page:&lt;br /&gt;&lt;/p&gt;&lt;pre class="code" style="margin: 6px;"&gt;&lt;span class="xml_pi"&gt;&amp;lt;?xml version=&lt;span class="literal"&gt;"1.0"&lt;/span&gt; encoding=&lt;span class="literal"&gt;"UTF-8"&lt;/span&gt; ?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="xml_tag"&gt;&amp;lt;xsl:stylesheet version=&lt;span class="literal"&gt;"1.0"&lt;/span&gt;&lt;br /&gt; xmlns:xsl=&lt;span class="literal"&gt;"http://www.w3.org/1999/XSL/Transform"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; xmlns=&lt;span class="literal"&gt;"http://www.w3.org/1999/xhtml"&lt;/span&gt;&lt;br /&gt; xmlns:view=&lt;span class="literal"&gt;"http://postman.com.ua/xslt/view10"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &lt;span class="xml_tag"&gt;&amp;lt;xsl:output method=&lt;span class="literal"&gt;"xml"&lt;/span&gt; encoding=&lt;span class="literal"&gt;"UTF-8"&lt;/span&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span class="xml_tag"&gt;&amp;lt;xsl:template match=&lt;span class="literal"&gt;"view:standard-page"&lt;/span&gt; mode=&lt;span class="literal"&gt;"view"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class="xml_tag"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;&lt;br /&gt;     &lt;span class="xml_tag"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;&lt;br /&gt;       &lt;span class="xml_tag"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;&lt;span class="xml_tag"&gt;&amp;lt;xsl:value-of select=&lt;span class="literal"&gt;"@title"&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;span class="xml_tag"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     &lt;span class="xml_tag"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;&lt;br /&gt;     &lt;span class="xml_tag"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;&lt;br /&gt;       &lt;span class="xml_tag"&gt;&amp;lt;xsl:apply-templates select=&lt;span class="literal"&gt;"view:content"&lt;/span&gt; mode=&lt;span class="literal"&gt;"view"&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;br /&gt;     &lt;span class="xml_tag"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   &lt;span class="xml_tag"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;br /&gt; &lt;span class="xml_tag"&gt;&amp;lt;/xsl:template&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span class="xml_tag"&gt;&amp;lt;xsl:template match=&lt;span class="literal"&gt;"view:content"&lt;/span&gt; mode=&lt;span class="literal"&gt;"view"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class="xml_tag"&gt;&amp;lt;div style=&lt;span class="literal"&gt;"min-height: 400px;"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     &lt;span class="xml_tag"&gt;&amp;lt;xsl:apply-templates mode=&lt;span class="literal"&gt;"view"&lt;/span&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class="xml_tag"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;br /&gt; &lt;span class="xml_tag"&gt;&amp;lt;/xsl:template&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span class="xml_tag"&gt;&amp;lt;xsl:template match=&lt;span class="literal"&gt;"*"&lt;/span&gt; mode=&lt;span class="literal"&gt;"view"&lt;/span&gt;&amp;gt;&lt;/span&gt; &lt;span class="xml_tag"&gt;&amp;lt;xsl:copy-of select=&lt;span class="literal"&gt;"current()"&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;span class="xml_tag"&gt;&amp;lt;/xsl:template&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="xml_tag"&gt;&amp;lt;/xsl:stylesheet&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;Being an XSLT newbie myself, the actual code is a bit awkward: I have to use a special namespace (view) and mode parameter of the xsl:template to escape possible infinite loops and to get namespaces right in the output document. Hopefully, an XSLT expert could provide a more streamlined implementation of the same idea.&lt;br /&gt;&lt;br /&gt;The node-set() extension function support both by MSXML and 4Suite XSLT which I happened to use on this project. The only minor problem is that you have to declare the namespace a bit differently for these two engines.&lt;br /&gt;&lt;br /&gt;My conclusions? I was able to simplify the presentation logic and get a considerable speed up (in a  2x-10x range)  with the price of some boilerplate code to add to each xsl page and potential portability problem between other XSL engines. Looks truly like a win to me.&lt;br /&gt;&lt;br /&gt;PS: Glad to have a &lt;a href="http://www.rafb.net/paste/"&gt;NoPaste&lt;/a&gt; service at hand.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110121324032475083?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110121324032475083/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110121324032475083' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110121324032475083'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110121324032475083'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/11/two-step-view-pattern-implementation.html' title='Two step view pattern implementation with XSLT'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110027109390602005</id><published>2004-11-12T16:21:00.000+02:00</published><updated>2004-11-12T16:51:33.906+02:00</updated><title type='text'>using other language to write unit tests</title><content type='html'>Just encountered an article on IBM's devWorks which gives an example on &lt;a href="http://www-106.ibm.com/developerworks/library/j-pg11094/index.html?ca=drs-j4604"&gt;how to use Groovy to write unit tests for Java code&lt;/a&gt;.  And this reminded me of experience I once had with mixing languages in unit testing.&lt;br /&gt;&lt;br /&gt;In a rather big project I once took part, we used an in-house Tcl-based framework to perform system tests via a network. Some other libraries developed for that project were coded in C++ and&lt;a href="http://www.lua.org"&gt; Lua&lt;/a&gt;. I decided to test this libraries as well using the same Tcl framework I've already built. I used &lt;a href="http://www.swig.org"&gt;SWIG&lt;/a&gt; to make C++ code accessible from within Tcl. I used the same trick to access C API of the Lua interpreter and feed it with Lua code. Just imaging this mess -- evaluate Lua code from within Tcl virtual machine (written in C) via generated dispatching code through the Lua virtual machine and down to C, at last!&lt;br /&gt;&lt;br /&gt;It was kind of nice to be able to load a C++ .so library into Tcl shell, experiment with it, call various methods and play with results. But as for production usage, it didn't worked out.&lt;br /&gt;There were two main reasons:&lt;br /&gt;&lt;ol&gt;   &lt;li&gt;Generation step always was a bit brittle. Even though SWIG managed to handle all C++ constructs we used it required some manual setup and it sometimes was hard to figure out how to use the generated code.&lt;/li&gt;   &lt;li&gt;Using different languages (and I'd add, so distinctively different languages)  were putting a significant burden on a developer. It just felt awkward.&lt;/li&gt; &lt;/ol&gt; I don't even mention that instead of developer who is proficient with one language you need a developer who is proficient in both. Plus could master SWIG tool.&lt;br /&gt;&lt;br /&gt;Groovy was designed to be as close to Java as possible and it's interoperability with Java is excellent, so unit tests for Java code written in Groovy won't suffer from the same problems I had. Still, I think it's better to stick to a single language for both, no matter how close Groovy is to Java. If you buy arguments for Groovy's simplicity - then just write &lt;span style="font-style: italic;"&gt;both&lt;/span&gt; production code and unit tests in Groovy. That's my opinion.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110027109390602005?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110027109390602005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110027109390602005' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110027109390602005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110027109390602005'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/11/using-other-language-to-write-unit.html' title='using other language to write unit tests'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110026719813522611</id><published>2004-11-12T14:05:00.000+02:00</published><updated>2004-11-12T15:46:38.136+02:00</updated><title type='text'>profiling unit tests</title><content type='html'>As were already noted &lt;a href="http://www.amk.ca/diary/archives/cat_python.html#003382#more"&gt;elsewhere&lt;/a&gt;, the so-proud-of, "batteries included" Python standard library has a lot to be improved. And while Java tools often being critiqued as overly complex, many of python modules are arguably simplistic, not just "as simple as possible".&lt;br /&gt;&lt;br /&gt;I run into this just yesterday, when tried to profile my unit tests.&lt;br /&gt;&lt;br /&gt;Usually unit tests run in a fraction of a second. Sometimes though, most often because of some heavy-weight interface not being stubbed, they suddenly could take a several seconds. So I thought to myself: "It would be nice if I could a get report about which test methods ate most of the time".&lt;br /&gt;&lt;br /&gt;After struggling for half an hour with a profiler (hotshot or the old one, whatever, they both use pstats module) I give up. Sure enough, I could get an overall program statstics, even filter it by name of the function with a regexp, but there were no way to trace from the actual function (like socket.connect) to a test method that called it (like testReportServerStatus). Or at least, I didn't find it. The latter is probably the case and the reason I was not able to find it is because pstats has a contrived API. I would say, almost a lack of it thereof. When called, it just prints to the screen what's been told but have no way to just return accumulated statistical data lump, so I could play with it by myself.&lt;br /&gt;&lt;br /&gt;But then another idea came to my mind. Why do I have to struggle with a profiler in the first place? I already have a framework (unittest, that is) which handles the task of runing the test methods. It should be simple to extend it to allow time measurement and report results, shouldn't it? Well, it turned out more or less simple.&lt;br /&gt;&lt;br /&gt;I had to extend both TestSuite class and TestRunner but it did worked. The only major problem I encountered is that TestSuite per se has no idea from which module a particular test has come. Luckily, I was already using my own function to gather test suites so it was simple to establish a module-to-suite mapping. Still, it prints only name of the modules not name of the actual test methods but at least it works. Any idea how to fix this is welcome, though.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110026719813522611?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110026719813522611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110026719813522611' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110026719813522611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110026719813522611'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/11/profiling-unit-tests.html' title='profiling unit tests'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110000473341484253</id><published>2004-11-09T14:09:00.000+02:00</published><updated>2004-11-12T15:50:59.883+02:00</updated><title type='text'>A perspective on software methodologies</title><content type='html'>A interesting quote I read the other day by Humphrey, father of the CMM: &lt;blockquote&gt;What people really want is a high-quality system that implements everything they want, at no cost, right now. Everything else is a trade-off.&lt;/blockquote&gt;What's striking in this metaphor is the idea of compromise. You &lt;span style="font-style: italic;"&gt;always &lt;/span&gt;have to sacrifice something, one way or another. And some elaborate models, like the &lt;a href="http://alistair.cockburn.us/crystal/articles/ptfd/processthefourthdimension.htm"&gt;iron triangle&lt;/a&gt; by Alister Cockburn, were probably inspired by this idea.&lt;br /&gt;&lt;br /&gt;I wonder, can we differentiate various software development methodologies by the approach they preach to find this compromise?&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110000473341484253?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/110000473341484253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=110000473341484253' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110000473341484253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110000473341484253'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/11/perspective-on-software-methodologies.html' title='A perspective on software methodologies'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109948194763870679</id><published>2004-11-03T11:28:00.000+02:00</published><updated>2004-11-03T13:39:07.636+02:00</updated><title type='text'>Programmer's HowTo</title><content type='html'>Several years ago,  when trying to master Linux I had to read a lot of documentations, man pages and HOW-TOs in particular. The topics covered by these manuals/how-tos were rather routine (as it seems to me today) - things like modem setup, font setup, pppd configuration, etc. The distinguishing feature for most of the good ones is that they're tightly packed with useful information - often I had to re-read them in order to grok completely.&lt;br /&gt;&lt;br /&gt;Recently I stumbled upon another HOW-TO: &lt;a href="http://samizdat.mines.edu/howto/"&gt;How to be a Programmer&lt;/a&gt; by&lt;span class="firstname"&gt;&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;Robert&lt;/span&gt; &lt;span class="othername"&gt;L&lt;/span&gt; &lt;span class="surname"&gt;Read&lt;/span&gt;. While he addresses a different topic - the topic of a professional growth as a programmer - he managed to preserve the spirit of these HOW-TOs: concise, clear and packed with insights.&lt;br /&gt;&lt;br /&gt;That's one of the best texts I had read on a topic in the last few years and arguably the one with the best size/usefulness ratio. It's a pity I haven't encountered it earlier (the first version was released in 2000).&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109948194763870679?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109948194763870679/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109948194763870679' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109948194763870679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109948194763870679'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/11/programmers-howto.html' title='Programmer&apos;s HowTo'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109845828879380608</id><published>2004-10-22T18:13:00.000+03:00</published><updated>2004-10-22T18:18:08.793+03:00</updated><title type='text'>Best Software Essays of 2004</title><content type='html'>An interesting discussion has opened on Joel On software forum - Joel asks readers to post essay which they consider were the best essay on software in 2004 (2003 is accepted as well). Great way to discover articles and/or authors you may have missed.&lt;br /&gt;&lt;br /&gt;As it turns out, I've already read about a third of them and they were indeed excellent. Looking forward to consume another two-thirds though.&lt;br /&gt;&lt;br /&gt;Check it out here: &lt;a href="http://discuss.joelonsoftware.com/default.asp?best04"&gt;Best Software Essays of 2004&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109845828879380608?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109845828879380608/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109845828879380608' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109845828879380608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109845828879380608'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/10/best-software-essays-of-2004.html' title='Best Software Essays of 2004'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109835126685782161</id><published>2004-10-21T13:03:00.000+03:00</published><updated>2004-10-21T12:34:26.856+03:00</updated><title type='text'>efficience vs. simplicity</title><content type='html'>I had to write a function that would generate a fixed-length sequence of symbols to be used as short, human-readable identifier for some database entities.&lt;br /&gt;&lt;br /&gt;The first version I wrote rather quickly used a brute-force algorithm:&lt;br /&gt;&lt;pre&gt;&lt;code style=""&gt;&lt;br /&gt;def idgenerator(length, prefix=None, seq=None):&lt;br /&gt; if prefix:&lt;br /&gt;     length = length - len(prefix)&lt;br /&gt; seq = seq or (string.digits + string.ascii_lowercase)&lt;br /&gt; while 1:&lt;br /&gt;     bits = []&lt;br /&gt;     for _ in range(length):&lt;br /&gt;         bits.append(random.choice(seq))&lt;br /&gt;     value = ''.join(bits)&lt;br /&gt;     if prefix:&lt;br /&gt;         value = prefix + value&lt;br /&gt;     yield value&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It works okay, but I was concerned with it's efficiency: it calls random.choice() function N times, where N is length of identifier. And I assume random.choice() must be computationally expensive. So, after some googling and hacking, I come up with the following:&lt;br /&gt;&lt;pre&gt;&lt;code style=""&gt;&lt;br /&gt;def str_base(seq, n, base=10):&lt;br /&gt; results = []&lt;br /&gt; while n:&lt;br /&gt;     n, r = divmod(n, base)&lt;br /&gt;     results.append(seq[r])&lt;br /&gt; results.reverse()&lt;br /&gt; return ''.join(results)&lt;br /&gt;&lt;br /&gt;def idgenerator_fast(length, prefix=None, seq=None):&lt;br /&gt;    if prefix:&lt;br /&gt;        length = length - len(prefix)&lt;br /&gt;    seq = seq or (string.digits + string.ascii_lowercase)&lt;br /&gt;    N = len(seq) # a magic number&lt;br /&gt;    minvalue = int(seq[0]*(length-1), N)&lt;br /&gt;    maxvalue = int(seq[-1]*length, N)&lt;br /&gt;    while 1:&lt;br /&gt;        n = random.randint(minvalue, maxvalue)&lt;br /&gt;        value = str_base(seq, n, N)&lt;br /&gt;        if len(value) &lt; length:&lt;br /&gt;            pad = seq[0]*(length-len(value))&lt;br /&gt;            value = pad + value&lt;br /&gt;        if prefix:&lt;br /&gt;            value = prefix + value&lt;br /&gt;        yield value&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I didn't profile this code, but IMO it should be much more efficient. But the problem is that it is twice as big and more difficult to comprehend - due to this base36 conversion trick.&lt;br /&gt;And if you take into account that this function is called by the db-access code than you realize than it's costs are negligible compared to interprocess db calls.&lt;br /&gt;&lt;br /&gt;Therefore I decided to stick with the simpler version. Nevertheless, it was a nice coding exercise, something like a mini-&lt;a href="http://www.pragprog.com/pragdave/Practices/Kata"&gt;Kata&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109835126685782161?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109835126685782161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109835126685782161' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109835126685782161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109835126685782161'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/10/efficience-vs-simplicity.html' title='efficience vs. simplicity'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109826885265774963</id><published>2004-10-20T13:57:00.000+03:00</published><updated>2004-10-20T14:57:44.226+03:00</updated><title type='text'>sofware as a service</title><content type='html'>&lt;span style="font-weight: bold;"&gt;disclaimer: &lt;/span&gt;I'm nor a business wise nor I pretend to be one, so the following thoughts may be just bogus or make you laugh. OK with me. But if you laugh, please spare a minute and enlighten me as well.&lt;br /&gt;&lt;br /&gt;I regret I couldn’t attend Web 2.0 conference, as it turned out to be quite fruitful for ideas, both for business approaches and technical questions. I did listen to some of the talks given on the conference, thanks to &lt;a href="http://www.itconversations.com/"&gt;ITconversations&lt;/a&gt; and &lt;a href="http://web20.weblogsinc.com/"&gt;The Web 2.0 weblog&lt;/a&gt; sites.&lt;br /&gt;&lt;br /&gt;One of them was a &lt;a href="http://www.itconversations.com/shows/detail217.html"&gt;Gillmor Gang from October 8, 2004&lt;/a&gt; on which &lt;span class="small"&gt;Kim Polese (&lt;/span&gt;&lt;span class="small"&gt;CEO)&lt;/span&gt;&lt;span class="small"&gt;, &lt;/span&gt;presented her &lt;span class="small"&gt;new company, &lt;a href="http://www.spikesource.com/"&gt;SpikeSource&lt;/a&gt;. Their business model assumes building a "solid product offering" on top of open source components. For their launch, they're planning to offer a product stack that would include MySQL, Apache, PHP and JBoss. In the future, they would create new offering, driven by the customer's demands. And they have been developing a "deep computer science" code that would allow (as I understood) to build and maintain these product stacks in a (semi-)automatic fashion. They are going to earn money from the support, training and other service-type activities, contributing the code back to the open source community.&lt;br /&gt;&lt;br /&gt;While the idea looks interesting and the talk is quite entertaining I wonder how good this approach would scale in terms of revenue. One of the nice things with software is it's "softness" - once you built a product it costs nothing to duplicate (and sell) any number of copies. With any service, costs to run it usually proportional to it's size. Plus, scaling it depends on people - which mean you need right stuff, with appropriate training, experience, etc, etc. So, basically, building a software product is (potentially) much more profitable than selling a service and it's much easier to sell.&lt;br /&gt;&lt;br /&gt;The SpikeSource (again, IIUC) has two assumptions to address this issue. Firstly, in the brave new world that's coming software components (at least, at the infrastructure level) are a commodity and hence it's very hard to squeeze a revenue in this market niche. IOW, could you build and sell a web server? Probably only a very specialized one, because it hard to compete with Apache. Secondly, there &lt;span style="font-style: italic;"&gt;would be&lt;/span&gt; a custom software in their offering, as an value-add for basic OSS components. So, the success would depend on whether they could add enough value to the commodities to attract customers.&lt;br /&gt;&lt;br /&gt;P.S.: I had read a couple of months ago about a similar initiative to provide a solid OSS-based platform for enterprises on top of Debian but just can't find a link. Pity.&lt;br /&gt;&lt;br /&gt;P.P.S: About a year ago, I was dreaming about starting a similar company here in my country (Ukraine) but not having had enough experience, money and courage I put it aside. So I'm a bit envious (&lt;a href="http://ischenko.blogspot.com/2004/10/google-desktop.html"&gt;again&lt;/a&gt;). ;-)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;update:&lt;/span&gt; google search for "&lt;/span&gt;Lightweight Business Models" turns up quite a few interesting links.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;update: &lt;/span&gt;fascinating &lt;a href="http://www.37signals.com/svn/archives/000881.php"&gt;post&lt;/a&gt; from&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;Jason Fried about "human scaling" and some intrigue details about the Basecamp product.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109826885265774963?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109826885265774963/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109826885265774963' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109826885265774963'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109826885265774963'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/10/sofware-as-service.html' title='sofware as a service'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109784092633809173</id><published>2004-10-15T14:42:00.000+03:00</published><updated>2004-10-15T15:02:44.950+03:00</updated><title type='text'>Google Desktop</title><content type='html'>In recent weeks/months Google literally flooded us with new products and services.  Yesterday they released a &lt;a href="http://desktop.google.com/"&gt;Google Desktop&lt;/a&gt; -- windows application that indexes your hard drive and provides an integrated search: both for web and local files simultaneously.&lt;br /&gt;&lt;br /&gt;I don't intend to describe it in details here or post screenshots how it looks on my computer. Just envy to those guys that happen to be in the right place to work for Google and have an itch to build something remarkable by myself.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;update:&lt;/span&gt;  &lt;a href="http://www.bloglines.com/toplinks"&gt;Bloglines's Most Popular Links&lt;/a&gt; puts google desktop on the top, with +641 increase from yesterday! I guess it's more than all other delta combined.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109784092633809173?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109784092633809173/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109784092633809173' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109784092633809173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109784092633809173'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/10/google-desktop.html' title='Google Desktop'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109783740649699806</id><published>2004-10-15T13:45:00.000+03:00</published><updated>2004-10-15T13:50:06.496+03:00</updated><title type='text'>python coverage tools</title><content type='html'>Some time ago, browsing source code for &lt;a href="http://sqlobject.sourceforge.net/"&gt;SQLObject&lt;/a&gt;, I found a decent &lt;a href="http://www.garethrees.org/2001/12/04/python-coverage/"&gt;module for code coverage analisys for python&lt;/a&gt;. It was hooked to the unittests' runner and in effect, provided you with a statistics on how much of the codebase were actually covered by these tests.&lt;br /&gt;&lt;br /&gt;I decided to try out this idea on my project's test code and results were rather impressive. One of the problem with dynamic languages like Python is that you have to run a particular line of code to be sure that it doesn't contain some syntax error or a typo. Yes, the interpreter is able to detect some classes of errors upon the complication but far fewer than, say, Java compiler. Code coverage, while it does not guarantee anything about the code's behaviour (whether it's correct or not) at least tells you what was and what wasn’t executed. And for Python that's of double importance.&lt;br /&gt;&lt;br /&gt;Now I'm hooked to the idea and pondering about the option to start and keep a coverage database. This should be even more helpful, as I could track the metric over time.&lt;br /&gt;&lt;br /&gt;PS: I've also found an &lt;a href="http://www.logilab.org/projects/apycot/0.5.1"&gt;Apycot&lt;/a&gt; package from Logilab, which contains a whole suite of testing tools, including coverage, lint and more. Unfortunately, it's not very well decoupled from the logilab's internal development process and hence hard to configure. And it's not Windows-aware (where I happen to develop now).&lt;br /&gt;&lt;br /&gt;Apart from the rather old (2001) coverage.py and logilab's project I didn't find a lot of other, metric-oriented tools for python. Any suggestions on what I have missed are welcome.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109783740649699806?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109783740649699806/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109783740649699806' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109783740649699806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109783740649699806'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/10/python-coverage-tools.html' title='python coverage tools'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109749793199681766</id><published>2004-10-11T14:31:00.000+03:00</published><updated>2004-10-11T15:32:11.996+03:00</updated><title type='text'>software is my business</title><content type='html'>Today's been a plentiful day. I've added several high-quality blogs about software business:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.stevepavlina.com/blog/"&gt;Steve Pavlina's blog&lt;/a&gt;&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;&lt;a href="http://lachlan.gemmell.com/"&gt;a software startup&lt;/a&gt; by Lachlan Gemmell&lt;/li&gt;   &lt;li&gt;&lt;a href="http://www.cloudshack.com/blog/"&gt;going from software developer to salesman&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109749793199681766?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109749793199681766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109749793199681766' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109749793199681766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109749793199681766'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/10/software-is-my-business.html' title='software is my business'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109707291512772955</id><published>2004-10-06T17:14:00.000+03:00</published><updated>2004-10-06T17:28:35.126+03:00</updated><title type='text'>The linkblogs are dead, long live del.icio.us</title><content type='html'>"Linkblog" is a blog which just links to entries in other blogs/sites.&lt;br /&gt;&lt;br /&gt;With &lt;a href="http://del.icio.us/"&gt;del.icio.us&lt;/a&gt; I can mix-and-match available links to create just a kind of linkblog &lt;span style="font-style: italic;"&gt;I &lt;/span&gt;want. Or even a bunch of them.&lt;br /&gt;&lt;br /&gt;The procedure is very simple:&lt;br /&gt;1. &lt;a href="http://del.icio.us/register"&gt;Register&lt;/a&gt; with del.icio.us.&lt;br /&gt;2. &lt;a href="http://del.icio.us/"&gt;Browse&lt;/a&gt; available links select ones you want to track and subscribe to them.&lt;br /&gt;3. Grab aggregated feed from &lt;a href="http://del.icio.us/inbox/maksim"&gt;your inbox&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Voila!&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109707291512772955?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109707291512772955/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109707291512772955' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109707291512772955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109707291512772955'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/10/linkblogs-are-dead-long-live-delicious.html' title='The linkblogs are dead, long live del.icio.us'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109704362827071636</id><published>2004-10-06T09:18:00.000+03:00</published><updated>2004-10-06T11:27:28.683+03:00</updated><title type='text'>Open source platform for rich web application</title><content type='html'>Laszlo announced that they are open sourcing their platform for developing rich internet applications (RIA).&lt;br /&gt;&lt;br /&gt;More info here: &lt;a href="http://www.openlaszlo.org/"&gt;http://www.openlaszlo.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Looks very promising, at lest for enterprise world. Will see how this will take off.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;update&lt;/span&gt;: Laszlo uses XML-based language to specify user interfaces and it is &lt;span style="font-style: italic;"&gt;object-oriented&lt;/span&gt;. Result looks rather ... er ... &lt;strike&gt;awkward&lt;/strike&gt;, a bit unusual, but easy to get used to. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109704362827071636?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109704362827071636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109704362827071636' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109704362827071636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109704362827071636'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/10/open-source-platform-for-rich-web.html' title='Open source platform for rich web application'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109696665100888648</id><published>2004-10-05T11:45:00.000+03:00</published><updated>2004-10-06T11:44:13.500+03:00</updated><title type='text'>Gmail new features - have you seen them?</title><content type='html'>When I started Gmail today I noticed some changes in the interface: the "Contacts" link is move to the left and now opens without a popup and I found "forwarding" option in the settings menu, Plus, there is prominent link "New features!" at the top right corner.&lt;br /&gt;&lt;br /&gt;That's nothing new here, some UI changes I notice regularly. The interesting part of the story is that my co-worker, sitting next table and also using Gmail &lt;span style="font-style: italic;"&gt;does not&lt;/span&gt; have this features but see the old interface.&lt;br /&gt;&lt;br /&gt;This is interesting, indeed. A reasonable explanation I may be that may be some Gmail users are switched to the new version to gather feedback. Or, another one, that Gmail's users that are actually report bugs got new versions first/exclusively while the rest using more-or-less stable beta.&lt;br /&gt;&lt;br /&gt;So, my question is - have &lt;span style="font-style: italic;"&gt;you &lt;/span&gt;seen these new features?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;update:&lt;/span&gt; others notice this too. See, for example, comments on &lt;a href="http://blog.codefront.net/archives/2004/10/04/gmails-new-features-atom-feed/"&gt;this post about Gmail's new features&lt;/a&gt;.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109696665100888648?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109696665100888648/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109696665100888648' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109696665100888648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109696665100888648'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/10/gmail-new-features-have-you-seen-them.html' title='Gmail new features - have you seen them?'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-110190487834381266</id><published>2004-10-01T14:21:00.000+03:00</published><updated>2004-12-01T14:41:18.343+02:00</updated><title type='text'>Hire me</title><content type='html'>Hi there!&lt;br /&gt;&lt;br /&gt;I'm willing to provide software development and consulting services both for short-term and long-term projects. The price tag typically lies within 15-30 USD/hour, but this is all negotiable, depending on the kind of work.&lt;br /&gt;&lt;br /&gt;If you managed to reach this page, hopefully you already have an idea how I could be helpful for your particular situation. Detailed resume and references are available upon request.&lt;br /&gt;&lt;br /&gt;You could contact me via &lt;a href="mailto:mfi@ukr.net"&gt;e-mail&lt;/a&gt; or phone: +38 050 1660266.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-110190487834381266?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110190487834381266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/110190487834381266'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/10/hire-me.html' title='Hire me'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109629269552622879</id><published>2004-09-27T16:16:00.000+03:00</published><updated>2004-09-29T15:31:23.106+03:00</updated><title type='text'>code smell: tests/production LOC ratio</title><content type='html'>&lt;span style="font-weight: bold;"&gt;disclaimer&lt;/span&gt;: this reasoning assumes the project is striving for 100% production code coverage by unit tests.&lt;br /&gt;&lt;br /&gt;As noted elsewhere, optimal lines of code (LOC) ratio for production code vs unit tests is about 1:1. I wonder, does significant deviation on either part indicate a &lt;a href="http://c2.com/cgi/wiki?CodeSmell"&gt;code smell&lt;/a&gt;?&lt;br /&gt;&lt;br /&gt;First, consider the case when the ratio is about 5:1. This could mean two things:&lt;br /&gt;&lt;ol&gt;   &lt;li&gt;Code coverage is poor (a good guess -- about 20-30%). No good, obviously.&lt;br /&gt;&lt;/li&gt;   &lt;li&gt;If code coverage is in 80-95%% range than we most probably have some flavour of acceptance (functional) tests not a canonical unit tests. Which is no good either.&lt;br /&gt;&lt;/li&gt; &lt;/ol&gt; Second scenario - when the ratio is 1:3 or even 1:5. Though less common, I still got into this situation from time to time. From my experience, this is usually a sign of a code smell:&lt;br /&gt;&lt;ol&gt;   &lt;li&gt;Elaborate  setup code and/or a lot of stubs may indicate not well factored class hierarchy.&lt;/li&gt;   &lt;li&gt;Lengthy test cases for particular production methods can indicate a heavyweight class waiting for the &lt;a href="http://www.refactoring.com/catalog/extractClass.html"&gt;Extract class refactoring&lt;/a&gt; to be applied.&lt;br /&gt;&lt;/li&gt; &lt;/ol&gt; Usually this ratio for my own code varies between 2:1 and 1:2. If it grows more, I tend to pay attention to either tests or the code itself. My experience here is mostly Python-based, in more verbose language like Java these figures may be a bit more vague.&lt;br /&gt;&lt;br /&gt;PS: May be a "design smell" is a more appropriate term here?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;update&lt;/span&gt;: My post's arguments were completed thrashed at &lt;a href="http://www.c2.com/cgi/wiki?ProductionCodeVsUnitTestsRatio"&gt;c2.com&lt;/a&gt;. I'm still trying to figure out how much I (dis-)agree with them.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109629269552622879?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109629269552622879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109629269552622879' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109629269552622879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109629269552622879'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/09/code-smell-testsproduction-loc-ratio.html' title='code smell: tests/production LOC ratio'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109610766310478824</id><published>2004-09-25T13:15:00.000+03:00</published><updated>2004-09-25T13:21:03.106+03:00</updated><title type='text'>Another argument for Google browser</title><content type='html'>To support &lt;a href="http://www.kottke.org/04/09/more-google-browser"&gt;community&lt;/a&gt; &lt;a href="http://www.vasanthdharmaraj.com/PermaLink,guid,d9962a2b-2ac9-402b-9365-d3515f661ba4.aspx"&gt;buzz&lt;/a&gt; about Google making a browser, they have launched a &lt;a href="http://www.google.com/mozilla/google.xul"&gt;version of the frontpage&lt;/a&gt; specifically for Mozilla browser. Things are &lt;a href="http://news.zdnet.com/2100-9595_22-5322521.html"&gt;getting interesting&lt;/a&gt;.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109610766310478824?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109610766310478824/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109610766310478824' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109610766310478824'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109610766310478824'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/09/another-argument-for-google-browser.html' title='Another argument for Google browser'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109544905128989894</id><published>2004-09-17T18:51:00.000+03:00</published><updated>2004-09-18T14:17:32.940+03:00</updated><title type='text'>More about inheritance vs. composition</title><content type='html'>I was reading excellent &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0201310058/qid=1095448920/sr=8-2/ref=sr_8_xs_ap_i2_xgl14/102-4991730-3664950?v=glance&amp;s=books&amp;amp;n=507846"&gt;Effective Java&lt;/a&gt; by Joshua Bloch, on a topic about typical pitfalls when implementing &lt;code&gt;Object.equals&lt;/code&gt; method. One of the least obvious is related to extending equals' implementation. To quote an author:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;There is simply no way to extend an instantiable class and add an aspect while preserving the equals contract.&lt;/blockquote&gt;The author ended up with advice to use composition instead of inheritance with for such cases. I mention this story now because my reflections on unit tests for class hierarchies led me to the same conclusion.&lt;br /&gt;&lt;br /&gt;Actually, I have in mind one specific case of class hierarchy: heavy-weight base and a bunch of subclasses that override/extend a particular aspect of it. An example may be a Finder superclass to define basic code to search the database and specific subclasses for specific domain objects, like Person.&lt;br /&gt;&lt;br /&gt;The problem lies in unit tests: if you write them both for base class and for each of subclasses you'll find a sheer amount of duplication in you test code. Moreover, it could be &lt;em&gt;very&lt;/em&gt; difficult to eliminate because the code would be&lt;em&gt; a bit different&lt;/em&gt; for each of the subclasses' test case.  A possible way out could be to replace inheritance with composition.  There are two choices:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Aggregate former base class into attribute. This is usually a relatively simple and this allows you to "stub" base class for testing thus eliminating a duplication in test code. If the base class' interface was much richer than that of subclasses you may end up with a lot of delegate methods, though.&lt;/li&gt;&lt;li&gt;Pass an instance of a former subclass to the base class in order to configure it with specialized data and code. This would also mean that all former subclasses must implement the same protocol (interface) that would be used by the base class. That's could be harder or even just not feasible, though - the hierarchy was created in the first place because you saw no other way to factor out the similarities. Additionaly, if you succeed, this refactoring could make this already heavy base class simply unmanageable.&lt;/li&gt;&lt;/ol&gt;Nice example of how TDD actually &lt;em&gt;drives&lt;/em&gt; a design, isn't it?&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;update:&lt;/strong&gt; renamed post title and improved reasoning for the two choices.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109544905128989894?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109544905128989894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109544905128989894' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109544905128989894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109544905128989894'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/09/more-about-inheritance-vs-composition.html' title='More about inheritance vs. composition'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109524434199969413</id><published>2004-09-15T13:23:00.000+03:00</published><updated>2004-09-22T10:18:23.370+03:00</updated><title type='text'>FireFox 1.0 PR impressions</title><content type='html'>First impressions on pre-1.0 release, in the order of their importantance to me:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;&lt;strike&gt;&lt;span style="font-weight: bold;"&gt;Major flaw&lt;/span&gt;. Popup blocker is either broken or just fascist.  It prevents windows from open when &lt;span style="font-style: italic;"&gt;I&lt;/span&gt; click a link, requiring me to add each site I want to use to whitelist. That's just stupid. Moreover, even after I added gmail.google.com to that list I still can't open a "Contacts" pop-up. &lt;/strike&gt; Sorry, it was my fault. The "Contacts" window now is working fine, so I guess this should have been a GMail bug, not FireFox.&lt;br /&gt;&lt;/li&gt;   &lt;li&gt;&lt;span style="font-weight: bold;"&gt;Bug fix. &lt;/span&gt; Gmail interface for contacts management is now working (it was completely broken before). There is a possibility though, that this is a fix by Gmail team.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Bug fix. &lt;/span&gt;Individual feeds in  &lt;a href="http://www.bloglines.com/"&gt;bloglines&lt;/a&gt; can be opened (at last!).&lt;/li&gt;  &lt;li&gt;&lt;span style="font-weight: bold;"&gt;Compatibility problem. &lt;/span&gt;Some of the installed extensions I happen to use were disabled as non-compatible with Firefox 0.10 (including ieview, livehttpheaders and text/plain). Hopefully their respective authors will update them soon so that I could continue to use them.&lt;/li&gt;&lt;li&gt;&lt;strike&gt;&lt;span style="font-weight: bold;"&gt;Minor irritation. &lt;/span&gt; The Find dialog is now appears as a toolbar at the bottom of the window. The problem is that there is no keyboard shortcut to close it. Admittedly, it's not really irritating because it's not clutter a browser window now.&lt;/strike&gt;  I changed my mind and I don't perceive this as an irritation anymore. Actually, it's a nice change because it allowed me to uncheck "Find as you type" option to allow Gmail's keyboard shortcuts and still have a handy search box. &lt;span style="font-weight: bold;"&gt;Nice &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;tweak.&lt;/span&gt;&lt;/li&gt;   &lt;li&gt;&lt;span style="font-weight: bold;"&gt;Nice tweak. &lt;/span&gt;Some (or may be most) windows that are shown by browser itself are now "inlined" at the top of the rendered page with a yellow substrate. I noticed this for popup blocker window, missing plugin notification and new find dialog.&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Nice tweak. &lt;/span&gt;The address bar for secure sites is now colored in yellow which make them hard to overlook (compared to a small lock at the corner we have previously)&lt;/li&gt;   &lt;li&gt;&lt;span style="font-weight: bold;"&gt;New feature. &lt;/span&gt;Live Bookmark feature is interesting, but I prefer &lt;a href="http://www.bloglines.com/"&gt;bloglines&lt;/a&gt; service to read RSS channels. There is a new &lt;a href="http://projects.koziarski.net/fyr/"&gt;Feed Your Reader&lt;/a&gt; extension which is similar to Live Bookmark but allows for external RSS readers.  Version 0.7 (due this week) &lt;a href="http://projects.koziarski.net/"&gt;is going to support&lt;/a&gt; bloglines as well.&lt;br /&gt;&lt;/li&gt;  &lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109524434199969413?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109524434199969413/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109524434199969413' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109524434199969413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109524434199969413'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/09/firefox-10-pr-impressions.html' title='FireFox 1.0 PR impressions'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109524343962829180</id><published>2004-09-15T13:09:00.000+03:00</published><updated>2004-09-28T14:27:08.696+03:00</updated><title type='text'>My blog's PageRank</title><content type='html'>Interesting, but my blog's site do not even appear on the first page of results when I search for &lt;a href="http://www.google.com/search?q=max+ischenko"&gt;max ischenko&lt;/a&gt;. Search for &lt;a href="http://www.google.com/search?q=max+ischenko+blog"&gt;max ischenko blog&lt;/a&gt; gives it third position which is not great either.&lt;br /&gt;&lt;br /&gt;Have to do something about that. Hey, &lt;a href="http://www.microsoft.com/"&gt;microsoft.com&lt;/a&gt; guys, please put a link to my blog on your front page! Please do or I won't ever link back to your site, improving &lt;span style="font-style: italic;"&gt;your&lt;/span&gt; PageRank.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;update&lt;/span&gt;: not sure if someone at microsoft.com really linked to my site, but now both above mentioned searches yield profile page and index page at first two positions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109524343962829180?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109524343962829180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109524343962829180' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109524343962829180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109524343962829180'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/09/my-blogs-pagerank.html' title='My blog&apos;s PageRank'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109524276464759694</id><published>2004-09-15T11:58:00.000+03:00</published><updated>2004-09-20T10:16:55.370+03:00</updated><title type='text'>Spammers move on to blogs and forums</title><content type='html'>Joel Spolsky &lt;a href="http://www.joelonsoftware.com/items/2004/09/14.html"&gt;writes&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;If you think comment spam is not a big problem, you haven't moderated a discussion group lately... this is the number one priority for spammers these days, since email filters are starting to work pretty well and spamming a lot of discussion groups is perceived as a good way to trick Google into giving a site prominent placement.&lt;br /&gt;&lt;/blockquote&gt;I read about spam posting on one or two other sites but didn't think it was a serious problem until now. Actually, just never bothered to ponder over it. Of course, this is more of a problem for popular sites, like Joel's, with a high PageRank. I wonder, if any forum/blogging software already ships with filtering included or at least has a plug-in for this.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;update: &lt;/span&gt;&lt;a href="http://kalsey.com/2003/11/comment_spam_manifesto/"&gt; Comment Spam Manifesto&lt;/a&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109524276464759694?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109524276464759694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109524276464759694' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109524276464759694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109524276464759694'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/09/spammers-move-on-to-blogs-and-forums.html' title='Spammers move on to blogs and forums'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109515442578006171</id><published>2004-09-14T10:24:00.000+03:00</published><updated>2005-03-25T18:52:33.890+02:00</updated><title type='text'>Testing web-based applications with FIT</title><content type='html'>I have had a need to automate testing of our web-based applications because manual testing could never be completed in a reasonable timeframe.&lt;br /&gt;&lt;br /&gt;For the last two weeks, I've been writing a fixture for FIT specifically to test web-based applications. The idea is to use very sophisticated &lt;a href="http://htmlunit.sourceforge.net/"&gt;HtmlUnit&lt;/a&gt; library for actual HTTP interactions and dealing with HTML (and Javascript) and to use &lt;a href="http://fitnesse.org/"&gt;FIT&lt;/a&gt; for specifing, running and reporting on test cases.&lt;br /&gt;&lt;br /&gt; &lt;span style="font-weight: bold;"&gt;update: &lt;/span&gt;project is now hosted on public subversion repository. See &lt;a href="http://opensvn.csie.org/webfixture"&gt;&lt;span style="text-decoration: underline;"&gt;http://opensvn.csie.org/webfixture&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;For those who have missed it, here is a short description of the FIT framework. FIT is a web-based tool for specifying and executing acceptance tests for all kinds of application, with a particular accent on simplicity of the specs (they could be understood and may be even written by a non-programmer, i.e. customer). The central role in the FIT framework is devoted to a &lt;span style="font-style: italic;"&gt;fixture.&lt;/span&gt; A fixture implements a &lt;span style="font-style: italic;"&gt;vocabulary&lt;/span&gt;, which is used by user to describe things he wants FIT to perform. For example, &lt;span style="font-style: italic;"&gt;to press&lt;/span&gt; a button or &lt;span style="font-style: italic;"&gt;to follow&lt;/span&gt; a link. Or &lt;span style="font-style: italic;"&gt;to evaluate&lt;/span&gt; 2+2 and &lt;span style="font-style: italic;"&gt;to check&lt;/span&gt; that result is 4.  Thus, user writes these checks using &lt;span style="font-style: italic;"&gt;vocabulary&lt;/span&gt; and programmer implements this vocabulary with a fixture in a meaningful way. If you're intrigued, &lt;span class="as"&gt;Michael Feathers has written a more elaborate intro in his &lt;/span&gt;&lt;span class="ts"&gt;&lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=67373"&gt;Pitching a Fit&lt;/a&gt; post.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Originally, I tried to write a custom &lt;a href="http://fitnesse.org/FitNesse.ActionFixture"&gt;ActionFixture&lt;/a&gt; for each web page I had to handle but soon discovered that it was a bad idea. Firstly, it was too much work -- to write a Java class for each page I need to test. Secondly, and more important, each fixture would use different vocabulary for each page which means that test writer had to be familiar with an underlying Java class. Therefore I decided it would be better to write a &lt;span style="font-style: italic;"&gt;single&lt;/span&gt; class (a fixture) that could be used to exercise &lt;span style="font-style: italic;"&gt;any&lt;/span&gt; web page. Luckily web languages' expressiveness is rather limited so the resulting vocabulary to describe test cases should be manageable.&lt;br /&gt;&lt;br /&gt;Shortly after I started to work on my WebFixture, I discovered a (semi?)-official &lt;a href="http://fitnesse.org/FitNesse.HtmlFixture"&gt;HtmlFixture&lt;/a&gt;, created for the same purpose and which even uses the same  &lt;a href="http://htmlunit.sourceforge.net/"&gt;HtmlUnit&lt;/a&gt; library! Nevertheless, I decided to continue to develop my own fixture, for these reasons:&lt;br /&gt;&lt;ol&gt;   &lt;li&gt;&lt;span style="font-weight: bold;"&gt;To get experience with Java platform&lt;/span&gt;. &lt;p&gt;One of my goals with this mini-project has been to try out a Java platform. I've been on most C++, Python, Tcl camps these years and my Java programs never went beyond the "Hello, world!" exercise. This project seems like a perfect opportunity to learn a new platform.&lt;/p&gt;&lt;/li&gt;   &lt;li&gt;&lt;span style="font-weight: bold;"&gt;To control fixture's development&lt;/span&gt;.&lt;p&gt;I want a control over this fixture to add things I want in a way I want. While the HtmlFixture is mature, its source code is undocumented and poorly written (to me). This probably a funny thing to say from a novice Java developer, but still, the source code seems like a mess to me and don't want to dive into it.&lt;br /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt; &lt;p&gt;To design it differently.&lt;/p&gt;&lt;/span&gt; If I decided to base my work on HtmlFixture there would be still no guarantee that my changes would ever go into original codebase. Why? Because I my approach is different and therefore there is a good chance that changes I propose won't "fit" author's concepts. Don't get me wrong, HtmlFixture is a fine work, I just want to implement the same concept a bit differently.&lt;br /&gt; &lt;p&gt;&lt;/p&gt;  &lt;/li&gt;   &lt;/ol&gt; So how my fixture does look like?&lt;br /&gt;&lt;br /&gt;The important design goal to me is to make fixture's vocabulary as simple and as high-level as possible. It should be similar in terms to those used by a web browser metaphor. It's better to sacrifice some underlying versatility of HtmlUnit to gain in simplicity and consistency for a user. It's better to overload verbs (where appropriate) than to invent new ones.&lt;br /&gt;&lt;br /&gt;For example, I use verb &lt;span style="font-style: italic;"&gt;click&lt;/span&gt; to follow links and submit buttons and use verb &lt;span style="font-style: italic;"&gt;enter&lt;/span&gt; to enter data to input boxes, text areas and select boxes. This way, the same verb can performs technically different things as long as it means &lt;span style="font-style: italic;"&gt;one&lt;/span&gt; thing to the user.&lt;br /&gt;&lt;br /&gt;There are some other features I've added so far: site configuration, Java delegates, erroneous page detection.&lt;br /&gt;&lt;br /&gt;The site command allows you to set some site options (or preferences)&lt;span style="font-family:monospace;"&gt; &lt;/span&gt;which include site root, timing information, error page patterns and more. These preferences are kept in a static storage so that you could set them in SetUp page and use on test pages.&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;The error page patterns used to detect erroneous web pages - normal HTML pages which are returned with HTTP response code 200 but which nevertheless are a sign of some internal error in the web application. For example, some application servers (like &lt;a href="http://www.webwareforpython.org/"&gt;WebKit&lt;/a&gt;)  show crash reports in this way and fixture could be configured to detect these automatically.&lt;br /&gt;&lt;br /&gt;Java delegates are extension point to be able to hook custom checks that are beyond normal web processing, like verifying the database state. A delegate is passed a current HtmlElement and should return a boolean result - whether a test has passed or not.&lt;br /&gt;&lt;br /&gt;And finally, some closing words on my first impressions on Java platform.&lt;br /&gt;&lt;br /&gt;The IDE for a statically-typed language could do amazing things and &lt;a href="http://www.eclipse.org/"&gt;Eclipse&lt;/a&gt; actually does them! Moreover, it is very capable in other aspects making handling of Java verbosity almost imperceptible. With advanced browsing support and context assist I managed to grasp an essence of both FIT and HtmlUnit library very quickly. And QuickFix assist helps greatly to correct my naive syntax errors. Overall, I must say, the development process goes much more smoothly and is much more fun that I have expected, thanks to IDE.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109515442578006171?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109515442578006171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109515442578006171' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109515442578006171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109515442578006171'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/09/testing-web-based-applications-with.html' title='Testing web-based applications with FIT'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109506384922459948</id><published>2004-09-13T11:14:00.000+03:00</published><updated>2004-09-13T11:29:27.803+03:00</updated><title type='text'>Mozilla FireFox extensions</title><content type='html'>&lt;a href="http://www.flexbeta.net/main/index.php"&gt;Flexbeta&lt;/a&gt; has posted a nice &lt;a href="http://www.flexbeta.net/main/articles.php?action=show&amp;amp;showarticle=79"&gt;guide to Firefox extensions&lt;/a&gt;, including &lt;a href="http://www.bolinfest.com/targetalert/"&gt;Target Alert&lt;/a&gt; for links, &lt;a href="http://adblock.mozdev.org/"&gt;Adblock&lt;/a&gt; with a nice configuration file, &lt;a href="http://sage.mozdev.org/"&gt;Sage&lt;/a&gt; RSS reader and more. Definitely worth a read for anyone who uses FireFox as a primary browser.&lt;br /&gt;&lt;br /&gt;Btw, Firefox 1.0 Preview Release is going to be release tomorrow.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109506384922459948?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109506384922459948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109506384922459948' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109506384922459948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109506384922459948'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/09/mozilla-firefox-extensions.html' title='Mozilla FireFox extensions'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109482641332557418</id><published>2004-09-10T17:12:00.000+03:00</published><updated>2004-09-10T17:32:41.826+03:00</updated><title type='text'>Flickr services</title><content type='html'>The &lt;a href="http://www.flickr.com/"&gt;Flickr.com&lt;/a&gt; is yet another photo service site. But the distinguishing feature (at least for me) is that it provides an &lt;a href="http://www.flickr.com/services/api/"&gt;API&lt;/a&gt; with array of supported access methods (REST, SOAP, XML-RPC) to get a &lt;span style="font-style: italic;"&gt;full programming control&lt;/span&gt; of your account's data and settings. Quite impressive, really. I can't agree more with &lt;a href="http://jeremy.zawodny.com/blog/archives/002526.html"&gt;&lt;span class="description"&gt;Jeremy Zawodny&lt;/span&gt;&lt;/a&gt;: [Flickr is a] next generation web services.&lt;br /&gt;&lt;br /&gt;If we add to this Google, Blogger, A9 and others it surely looks like a trend. And you (myself in the first place) don't want to miss the idea while launching your next web-based service. Sure, this kind of access is helpful only for a fraction of web-based services out there, but it could gain them a lot.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109482641332557418?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109482641332557418/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109482641332557418' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109482641332557418'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109482641332557418'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/09/flickr-services.html' title='Flickr services'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109404712637488261</id><published>2004-09-01T16:49:00.000+03:00</published><updated>2004-09-01T16:58:46.373+03:00</updated><title type='text'>Blogger</title><content type='html'>While the Blogger web application is one of the most pleasing I have worked with, it seems a bit shaky. I have already seen several errors in the past two days, including NullPointerException from a Java application,  a page saying "internal error has occured" and a misleading error message which said about an error deleting a comment while it was actually deleted.&lt;br /&gt;&lt;br /&gt;Anyway, overall experience has been excellent so far. The only major thing I miss is ability to post into different categories.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109404712637488261?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109404712637488261/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109404712637488261' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109404712637488261'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109404712637488261'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/09/blogger.html' title='Blogger'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109396452620833477</id><published>2004-08-31T17:14:00.000+03:00</published><updated>2004-08-31T18:05:17.486+03:00</updated><title type='text'>The Python paradox and PIL</title><content type='html'>In the recent &lt;a href="http://www.paulgraham.com/gh.html" title="Great Hackers"&gt;remarkable talk&lt;/a&gt; and later &lt;a href="http://www.paulgraham.com/pypar.html" title="The Python Paradox"&gt;clarification&lt;/a&gt; Paul Graham said:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Python programmers are smart. It's a lot of work to learn a new programming language. And people don't learn Python because it will get them a job; they learn it because they genuinely like to program and aren't satisfied with the languages they already know.&lt;br /&gt;&lt;/blockquote&gt;Today I had to perform a simple image transformation task in Python and decided to use well-known &lt;a href="http://www.pythonware.com/products/pil/"&gt;PIL&lt;/a&gt; library. While working with PIL I had to recall this &lt;a href="http://www.paulgraham.com/pypar.html"&gt;Python Paradox&lt;/a&gt;.  The reason?&lt;br /&gt;&lt;br /&gt;The PIL's API is weird. Not only it contains stupid bugs but it is awkward to use. I can't judge the underlying C implementation, it may be just excellent, but the python wrapping code is far from perfect. It is simply mediocre at best. And who said &lt;span style="font-style: italic;"&gt;the Python programmers are smart&lt;/span&gt; here? :-)&lt;br /&gt;&lt;br /&gt;Just to support this rant, here are some issues I have discovered while trying to resize an image (a pretty typical use-case, isn't it?):&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;&lt;span style="font-weight: bold;"&gt;to create an image you'll need a file-like object, plain string won't work.&lt;/span&gt; Actually, this is very common in python libraries and can be seen quite often in standard lib as well. But this is still irritating. Why the library can't provide both methods instead of forcing the user to mess with StringIO buffer? From the implementation point of view one method could be easily done as a thin wrapper over the other. It is easy and facilitates unit testing. The only excuse could be the laziness of the library author.&lt;br /&gt;&lt;/li&gt;   &lt;li&gt;&lt;span style="font-weight: bold;"&gt;you have to save the image just to get image data&lt;/span&gt;. To me, this feels awkward - why don't provide a method to get (or compute, who cares?) image data directly? The issue is emphasized by the save() method itself.&lt;br /&gt;&lt;/li&gt;   &lt;li&gt;&lt;span style="font-weight: bold;"&gt;the save() method is just weird.&lt;/span&gt; Firstly, as you may have guessed, it requires a file-like object. Secondly, it &lt;span style="font-style: italic;"&gt;requires&lt;/span&gt; you to specify a format in which you want to save it. It would be OK if this parameter is optional but it is mandatory! In my case I simply don't know original format nor I could care less. I just want to resize an image and get the result. As it is, I had to determine image type first, despite the fact that resizing routine accepts many different kind of image files. And the final stroke of untidiness -- format is specified as string and never explicitly checked for correctness. So if you pass JPG instead of JPEG you'd get a KeyError with very informative "JPG" explanation text.&lt;br /&gt;&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;On a positive side, the functionality is excellent - the resizing routine performed fine (after I specified more sophisticated resampling filter instead of NEAREST).&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109396452620833477?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109396452620833477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109396452620833477' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109396452620833477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109396452620833477'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/08/python-paradox-and-pil.html' title='The Python paradox and PIL'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109385293465131755</id><published>2004-08-30T10:25:00.000+03:00</published><updated>2004-08-30T11:02:14.650+03:00</updated><title type='text'>Blogger + Gmail</title><content type='html'>In less than an hour after I opened a blogger account I received 5 invites in my Gmail account. A coincidence?&lt;br /&gt;&lt;br /&gt;P.S.: Yes, I know that first gmail accounts were given to blogger people (among others)&lt;br /&gt;P.P.S.: Anyone still need a Gmail invite?&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109385293465131755?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109385293465131755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109385293465131755' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109385293465131755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109385293465131755'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/08/blogger-gmail.html' title='Blogger + Gmail'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8128258.post-109385017062600679</id><published>2004-08-30T10:02:00.000+03:00</published><updated>2004-08-30T11:40:26.993+03:00</updated><title type='text'>Managing code repositories on two machines</title><content type='html'>I have two machines on which I work and have to move &lt;span style="font-style: italic;"&gt;complete&lt;/span&gt; source code repository back and forth to replicate changes. This is quite cumbersome as these repositories are rather large (hundreds of megabytes).&lt;br /&gt;&lt;br /&gt;I have been pondering for a way to replicate only diffs but still haven't found a solution. My two candidates were (are) subversion (as I use it to host projects) and unison (file system synchronization utility). The problem is that I can't connect these machines via network and thus simple "svn up" is not possible.&lt;br /&gt;&lt;br /&gt;I think there should be a subversion way to "export" changes and then "apply" it to another WC. But even if this is possible I need to replicate the subversion repository itself.&lt;br /&gt;&lt;br /&gt;Internet-living Mastermind, are you hearing me?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;update:&lt;/span&gt; Davin suggested Windows built-in 'briefcase' tool, that's what I'm going to try.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8128258-109385017062600679?l=ischenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ischenko.blogspot.com/feeds/109385017062600679/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8128258&amp;postID=109385017062600679' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109385017062600679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8128258/posts/default/109385017062600679'/><link rel='alternate' type='text/html' href='http://ischenko.blogspot.com/2004/08/managing-code-repositories-on-two.html' title='Managing code repositories on two machines'/><author><name>Max Ischenko</name><uri>http://www.blogger.com/profile/15303722628632310474</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry></feed>
