<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Thoughts on Software and Computers</title>
	
	<link>http://software.tulentsev.com</link>
	<description>.NET, OO and functional programming, software reviews...</description>
	<lastBuildDate>Fri, 03 Sep 2010 15:58:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ThoughtsOnSoftwareAndComputers" /><feedburner:info uri="thoughtsonsoftwareandcomputers" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Mass creation of symlinks</title>
		<link>http://feedproxy.google.com/~r/ThoughtsOnSoftwareAndComputers/~3/da7kS-cOVx4/</link>
		<comments>http://software.tulentsev.com/2010/09/mass-creation-of-symlinks/#comments</comments>
		<pubDate>Fri, 03 Sep 2010 15:55:48 +0000</pubDate>
		<dc:creator>Sergei Tulentsev</dc:creator>
				<category><![CDATA[Problem solving]]></category>

		<guid isPermaLink="false">http://software.tulentsev.com/?p=198</guid>
		<description><![CDATA[Today I was installing a new server. Downloaded the latest version of Ruby Enterprise Edition and installed it successfully. As I didn&#8217;t have any other ruby sitting in my system, I decided to symlink all of ruby executables from /usr/bin. But how do I do that? The first, obvious and sub-optimal way would be to [...]]]></description>
			<content:encoded><![CDATA[<p>Today I was installing a new server. Downloaded the latest version of <a title="Ruby Enterprise Edition" href="http://www.rubyenterpriseedition.com/download.html">Ruby Enterprise Edition</a> and installed it successfully. As I didn&#8217;t have any other ruby sitting in my system, I decided to symlink all of ruby executables from /usr/bin. But how do I do that? The first, obvious and sub-optimal way would be to issue &#8220;ln -s&#8221; command for each file. &#8220;That&#8217;s too much work&#8221; &#8211; I said and started googling.</p>
<p>Long story short, this is the solution I came up with:</p>
<pre class="brush: bash">find /opt/rubyee/bin/ -type f -name '*' -printf '%f,' | xargs -I '{}' -d ,  sudo ln -s /opt/rubyee/bin/{} /usr/bin/{}
</pre>
<p>A bit of explanation:</p>
<pre class="brush: bash">find /opt/rubyee/bin/ -type f -name '*' -printf '%f,'</pre>
<p>This command finds all (<em>-name &#8216;*&#8217;</em>) files (<em>-type f</em>) in /opt/rubyee/bin and list their names, separated by comma (<em>-printf &#8216;%f,&#8217;</em>). Then the resulting output is passed to the next command.</p>
<pre class="brush: bash">xargs -I '{}' -d ,  sudo ln -s /opt/rubyee/bin/{} /usr/bin/{}</pre>
<p>It basically splits its input stream by comma (<em>-d ,</em>) and executes &#8220;<em>sudo ln</em>&#8220;, replacing every occurence of {} in its arguments with actual filename.</p>
<p>The resulting command surely seems scary for a novice Linux admin, who I am. Probably I could utilize <em>-exec</em> parameter of the <em>find</em>, but this worked well enough for me. Also, if I did it manually, it actually would be several times faster. But hey, are we programmers or not? :-)</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=da7kS-cOVx4:5tmmnX4d0yY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=da7kS-cOVx4:5tmmnX4d0yY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?i=da7kS-cOVx4:5tmmnX4d0yY:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=da7kS-cOVx4:5tmmnX4d0yY:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ThoughtsOnSoftwareAndComputers/~4/da7kS-cOVx4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://software.tulentsev.com/2010/09/mass-creation-of-symlinks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://software.tulentsev.com/2010/09/mass-creation-of-symlinks/</feedburner:origLink></item>
		<item>
		<title>jQuery chaining</title>
		<link>http://feedproxy.google.com/~r/ThoughtsOnSoftwareAndComputers/~3/s-08tUXHIOU/</link>
		<comments>http://software.tulentsev.com/2010/08/jquery-chaining/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 16:00:13 +0000</pubDate>
		<dc:creator>Sergei Tulentsev</dc:creator>
				<category><![CDATA[Web development]]></category>

		<guid isPermaLink="false">http://software.tulentsev.com/?p=189</guid>
		<description><![CDATA[I am beginning to fall in love with jQuery. Screw you, bicycle inventors! :-) function next_step() { // note how elegant and self-explanatory this code is. var cl = 'step_selected'; $('.' + cl).removeClass(cl).next().addClass(cl); // Also look at previous version of the code, // before I remembered about chaining methods. // var li = $('.step_selected'); // [...]]]></description>
			<content:encoded><![CDATA[<p>I am beginning to fall in love with jQuery. Screw you, <a href="http://vkontakte.ru">bicycle inventors</a>! :-)</p>
<pre class="brush: javascript">    function next_step() {
        // note how elegant and self-explanatory this code is.
        var cl = 'step_selected';
        $('.' + cl).removeClass(cl).next().addClass(cl);

        // Also look at previous version of the code,
        // before I remembered about chaining methods.

        // var li = $('.step_selected');
        // li.removeClass('step_selected');
        // li.next().addClass('step_selected');

        // Not as sexy, right? :-)
    }
</pre>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=s-08tUXHIOU:yWLxAL38JWE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=s-08tUXHIOU:yWLxAL38JWE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?i=s-08tUXHIOU:yWLxAL38JWE:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=s-08tUXHIOU:yWLxAL38JWE:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ThoughtsOnSoftwareAndComputers/~4/s-08tUXHIOU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://software.tulentsev.com/2010/08/jquery-chaining/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://software.tulentsev.com/2010/08/jquery-chaining/</feedburner:origLink></item>
		<item>
		<title>Funny side benefit :-)</title>
		<link>http://feedproxy.google.com/~r/ThoughtsOnSoftwareAndComputers/~3/1euWxdzaLR0/</link>
		<comments>http://software.tulentsev.com/2010/08/funny-side-benefit/#comments</comments>
		<pubDate>Sun, 22 Aug 2010 16:17:18 +0000</pubDate>
		<dc:creator>Sergei Tulentsev</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[LINQ]]></category>

		<guid isPermaLink="false">http://software.tulentsev.com/?p=187</guid>
		<description><![CDATA[There I was, minding my own business, trying to solve problems in graph theory and I accidentally made a Sudoku puzzle solver! Isn&#8217;t it funny how life turns out sometimes? But that&#8217;s just how awesome LINQ is. Eric Lippert on LINQ]]></description>
			<content:encoded><![CDATA[<blockquote><p>There I was, minding my own business, trying to solve problems in graph theory and I accidentally made a Sudoku puzzle solver! Isn&#8217;t it funny how life turns out sometimes? But that&#8217;s just how awesome LINQ is.</p></blockquote>
<p><a href="http://blogs.msdn.com/b/ericlippert/archive/2010/07/29/graph-colouring-part-five.aspx">Eric Lippert on LINQ</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=1euWxdzaLR0:wXJ6wWdMdqA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=1euWxdzaLR0:wXJ6wWdMdqA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?i=1euWxdzaLR0:wXJ6wWdMdqA:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=1euWxdzaLR0:wXJ6wWdMdqA:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ThoughtsOnSoftwareAndComputers/~4/1euWxdzaLR0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://software.tulentsev.com/2010/08/funny-side-benefit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://software.tulentsev.com/2010/08/funny-side-benefit/</feedburner:origLink></item>
		<item>
		<title>Atomic updates, part 2</title>
		<link>http://feedproxy.google.com/~r/ThoughtsOnSoftwareAndComputers/~3/bNH5dv4TRhA/</link>
		<comments>http://software.tulentsev.com/2010/06/atomic-updates-part-2/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 14:12:41 +0000</pubDate>
		<dc:creator>Sergei Tulentsev</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MongoDb]]></category>

		<guid isPermaLink="false">http://software.tulentsev.com/?p=184</guid>
		<description><![CDATA[Let&#8217;s review another common scenario: posts and votes. Mongo&#8217;s approach would be to store vote count in the post itself (caching) and keep voters also in the post, in an array field. Let&#8217;s assume we want to register a new vote on post. This operation consists of three steps: 1. ensure that the voter hasn&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>Let&#8217;s review another common scenario: posts and votes. Mongo&#8217;s approach would be to store vote count in the post itself (caching) and keep voters also in the post, in an array field. Let&#8217;s assume we want to register a new vote on post. This operation consists of three steps:</p>
<blockquote><p>
1. ensure that the voter hasn&#8217;t voted yet, and, if not,<br />
2. increment the number of votes and<br />
3. add the new voter to the array.</p>
<p>MongoDB&#8217;s query and update features allows us to perform all three actions in a single operation. Here&#8217;s what that would look like from the shell:</p>
<pre class='brush: ruby'>
// Assume that story_id and user_id represent real story and user ids.
db.stories.update({_id: story_id, voters: {'$ne': user_id}},
  {'$inc': {votes: 1}, '$push': {voters: user_id}});
</pre>
<p>What this says is &#8220;get me a story with the given id whose voters array does not contain the given user id and, if you find such a story, perform two atomic updates: first, increment votes by 1 and then push the user id onto the voters array.&#8221;</p>
<p>This operation highly efficient; it&#8217;s also reliable. The one caveat is that, because update operations are &#8220;fire and forget,&#8221; you won&#8217;t get a response from the server. But in most cases, this should be a non-issue.
</p></blockquote>
<p>quote from <a href="http://www.mongodb.org/display/DOCS/MongoDB+Data+Modeling+and+Rails">MongoDB site</a>.</p>
<p>How would you implement this in your regular SQL database?</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=bNH5dv4TRhA:y3zT520ikQI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=bNH5dv4TRhA:y3zT520ikQI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?i=bNH5dv4TRhA:y3zT520ikQI:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=bNH5dv4TRhA:y3zT520ikQI:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ThoughtsOnSoftwareAndComputers/~4/bNH5dv4TRhA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://software.tulentsev.com/2010/06/atomic-updates-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://software.tulentsev.com/2010/06/atomic-updates-part-2/</feedburner:origLink></item>
		<item>
		<title>MongoId and atomic increment</title>
		<link>http://feedproxy.google.com/~r/ThoughtsOnSoftwareAndComputers/~3/v889RYZzSpg/</link>
		<comments>http://software.tulentsev.com/2010/06/mongoid-and-atomic-increment/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 23:01:26 +0000</pubDate>
		<dc:creator>Sergei Tulentsev</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MongoDb]]></category>
		<category><![CDATA[MongoId]]></category>

		<guid isPermaLink="false">http://software.tulentsev.com/?p=179</guid>
		<description><![CDATA[I am starting to learn this new piece of technology, the MongoDB. It has many sweet features. However, using Ruby driver directly is not too comfortable. Plus we&#8217;re all hooked to ORM sweeteners. So people started developing ORM libraries for MongoDB and Ruby (MongoId, MongoMapper to name a few). I have decided to try MongoId [...]]]></description>
			<content:encoded><![CDATA[<p>I am starting to learn this new piece of technology, the MongoDB. It has many sweet features. However, using Ruby driver directly is not too comfortable. Plus we&#8217;re all hooked to ORM sweeteners. So people started developing ORM libraries for MongoDB and Ruby (<a href="http://mongoid.org">MongoId</a>, <a href="http://github.com/mongomapper/mongomapper">MongoMapper</a> to name a few).</p>
<p>I have decided to try MongoId first. It seems to be a quite good library. However, it still has gaps in documentation. Today I was finding out how to perform an atomic increment of a field. In SQL world this would like like:</p>
<pre class='brush: sql'>
update users set spam_count = spam_count + 1;
</pre>
<p>Mongo Ruby driver supports this kind of operation, but MongoId doesn&#8217;t. So I was trying to get down to the driver. And this is what I couldn&#8217;t easily find in the docs. If you&#8217;re like me, I&#8217;ll save you a couple of hours. Here it is:</p>
<pre class='brush: ruby'>
# assume we know object id already
User.collection.update({'_id' => '4c05848e45760182b5000001'}, {'$inc' => {'spam_count' => 1}})
</pre>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=v889RYZzSpg:RvLKBJUE34k:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=v889RYZzSpg:RvLKBJUE34k:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?i=v889RYZzSpg:RvLKBJUE34k:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=v889RYZzSpg:RvLKBJUE34k:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ThoughtsOnSoftwareAndComputers/~4/v889RYZzSpg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://software.tulentsev.com/2010/06/mongoid-and-atomic-increment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://software.tulentsev.com/2010/06/mongoid-and-atomic-increment/</feedburner:origLink></item>
		<item>
		<title>Intuitive behaviour</title>
		<link>http://feedproxy.google.com/~r/ThoughtsOnSoftwareAndComputers/~3/L5A4wCuxVP0/</link>
		<comments>http://software.tulentsev.com/2009/05/intuitive-behaviour/#comments</comments>
		<pubDate>Mon, 18 May 2009 15:19:25 +0000</pubDate>
		<dc:creator>Sergei Tulentsev</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[RubyMine]]></category>

		<guid isPermaLink="false">http://software.tulentsev.com/?p=176</guid>
		<description><![CDATA[Today I was looking at exception stack trace. One of suspicious places was &#8216;&#8230;\reports_controller.rb:129&#8243;. Okay, navigating to this location using RubyMine is a piece of cake. Ctrl+Shift+N to get to reports_controller.rb, then Ctrl+G to position caret at specified line. But hey, that&#8217;s two actions. I hit Ctrl+Shift+N, put &#8216;reports_controller.rb:129&#8242; in and voila! It worked just [...]]]></description>
			<content:encoded><![CDATA[<p>Today I was looking at exception stack trace. One of suspicious places was &#8216;&#8230;\reports_controller.rb:129&#8243;. Okay, navigating to this location using RubyMine is a piece of cake. Ctrl+Shift+N to get to reports_controller.rb, then Ctrl+G to position caret at specified line. But hey, that&#8217;s two actions. I hit Ctrl+Shift+N, put &#8216;reports_controller.rb:129&#8242; in and voila! It worked just as I expected!<br />
RubyMine: +1 to intuitivity, +1 to overall impression. </p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=L5A4wCuxVP0:BmIkF1ty7gQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=L5A4wCuxVP0:BmIkF1ty7gQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?i=L5A4wCuxVP0:BmIkF1ty7gQ:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=L5A4wCuxVP0:BmIkF1ty7gQ:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ThoughtsOnSoftwareAndComputers/~4/L5A4wCuxVP0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://software.tulentsev.com/2009/05/intuitive-behaviour/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://software.tulentsev.com/2009/05/intuitive-behaviour/</feedburner:origLink></item>
		<item>
		<title>Advanced default parameters</title>
		<link>http://feedproxy.google.com/~r/ThoughtsOnSoftwareAndComputers/~3/miK4Y0Mt8o8/</link>
		<comments>http://software.tulentsev.com/2009/03/advanced-default-parametes/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 02:20:29 +0000</pubDate>
		<dc:creator>Sergei Tulentsev</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://software.tulentsev.com/?p=162</guid>
		<description><![CDATA[Today I was quite amazed by one of Ruby features. It is about default values of method parameters. For example you can do something like this: def get_current_actions(project_id, status_id = params[:status_id] &#124;&#124; DEFAULT_STATUS_ID) # implementation goes here end The code is saying basically this: &#8220;if status_id is not passed explicitly, try to take its value [...]]]></description>
			<content:encoded><![CDATA[<p>Today I was quite amazed by one of Ruby features. It is about default values of method parameters. For example you can do something like this:</p>
<pre class="brush: ruby">
def get_current_actions(project_id, status_id = params[:status_id] || DEFAULT_STATUS_ID)
    # implementation goes here
end
</pre>
<p>The code is saying basically this: &#8220;if status_id is not passed explicitly, try to take its value from <strong>params</strong> array. If it doesn&#8217;t contain specified key, then fall back to a constant&#8221;. This feature (as almost all the rest of Ruby magic) made avaiable by Ruby&#8217;s nature: it is interpreted language. This type of code is totally unusual to guys like me, who come from the world of static typing and compiled languages. But I think I&#8217;m gonna get used to it :-)</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=miK4Y0Mt8o8:QMIfVUkDbog:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=miK4Y0Mt8o8:QMIfVUkDbog:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?i=miK4Y0Mt8o8:QMIfVUkDbog:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=miK4Y0Mt8o8:QMIfVUkDbog:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ThoughtsOnSoftwareAndComputers/~4/miK4Y0Mt8o8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://software.tulentsev.com/2009/03/advanced-default-parametes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://software.tulentsev.com/2009/03/advanced-default-parametes/</feedburner:origLink></item>
		<item>
		<title>Iterations are good</title>
		<link>http://feedproxy.google.com/~r/ThoughtsOnSoftwareAndComputers/~3/dhJfQG07_Kk/</link>
		<comments>http://software.tulentsev.com/2009/03/iterations-are-good/#comments</comments>
		<pubDate>Wed, 04 Mar 2009 19:11:47 +0000</pubDate>
		<dc:creator>Sergei Tulentsev</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Agile]]></category>

		<guid isPermaLink="false">http://software.tulentsev.com/?p=155</guid>
		<description><![CDATA[Iterations in software development. Tried to implement proper solution on the first try? I bet you failed. It’s like in Google Earth zooming in your house from the planet view. To achieve your goal, you&#8217;ve got to advance a little bit, adjust your position, advance further… Iterate until done.]]></description>
			<content:encoded><![CDATA[<p>Iterations in software development. Tried to implement proper solution on the first try? I bet you failed. It’s like in Google Earth zooming in your house from the planet view. To achieve your goal, you&#8217;ve got to advance a little bit, adjust your position, advance further… Iterate until done.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=dhJfQG07_Kk:zQfiSC0pkiI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=dhJfQG07_Kk:zQfiSC0pkiI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?i=dhJfQG07_Kk:zQfiSC0pkiI:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=dhJfQG07_Kk:zQfiSC0pkiI:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ThoughtsOnSoftwareAndComputers/~4/dhJfQG07_Kk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://software.tulentsev.com/2009/03/iterations-are-good/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://software.tulentsev.com/2009/03/iterations-are-good/</feedburner:origLink></item>
		<item>
		<title>Making more mockups</title>
		<link>http://feedproxy.google.com/~r/ThoughtsOnSoftwareAndComputers/~3/8YPN1mT5ZQg/</link>
		<comments>http://software.tulentsev.com/2009/03/making-more-mockups/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 19:29:10 +0000</pubDate>
		<dc:creator>Sergei Tulentsev</dc:creator>
				<category><![CDATA[Software reviews]]></category>
		<category><![CDATA[mockups]]></category>
		<category><![CDATA[UI]]></category>

		<guid isPermaLink="false">http://software.tulentsev.com/?p=142</guid>
		<description><![CDATA[Today Elen, my manager, approached me and asked to make a prototype of a new functionality in our project management system. This is a reimbursement management module: employees spend some money (taxi from airport, for example), then they create requests for reimbursements and if they are lucky and management approves the requests, they get the [...]]]></description>
			<content:encoded><![CDATA[<p>Today Elen, my manager, approached me and asked to make a prototype of a new functionality in our project management system. This is a reimbursement management module: employees spend some money (taxi from airport, for example), then they create requests for reimbursements and if they are lucky and management approves the requests, they get the money back :-)</p>
<p>So, prototype it is. <span id="more-142"></span>I fired up my <a title="Balsamiq Mockups for Desktop" href="http://balsamiq.com/products/mockups/desktop">Balsamiq for Desktop </a>and in under ten minutes mockups of two pages were ready. This is one of them:</p>
<p style="text-align: center;"><a href="http://software.tulentsev.com/wp-content/uploads/2009/03/manager_view.png"><img class="aligncenter size-full wp-image-144" title="manager_view" src="http://software.tulentsev.com/wp-content/uploads/2009/03/manager_view.png" alt="manager_view" width="579" height="385" /></a></p>
<p style="text-align: left;">But when I sent them to Elen, I thought that maybe she meant some real code, or HTML stubs in real system, because there was a mockup attached to her original email. Here it is:</p>
<p style="text-align: left;"><a href="http://software.tulentsev.com/wp-content/uploads/2009/03/reembolso.jpg"><img class="aligncenter size-medium wp-image-145" title="reembolso" src="http://software.tulentsev.com/wp-content/uploads/2009/03/reembolso-300x159.jpg" alt="reembolso" width="300" height="159" /></a>According to her, she made it in Paint (<strong>duh!</strong>). And it took her approximately 30 minutes to make this one, because she had to printscreen some real pages and cut pieces from them. What a tedious work! :-) And it must be a hell to modify such mockup!</p>
<p style="text-align: left;">When I told her about <a href="http://balsamiq.com/">Balsamiq Mockups</a>, she became very interested and decided to give it a try. Another happy story. Thank you, Peldi :-)</p>
<p style="text-align: left;">Related posts: <a href="http://software.tulentsev.com/2008/12/creating-ui-mockups-with-balsamiq/">Creating UI mockups with Balsamiq</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=8YPN1mT5ZQg:k78rgFJkhbE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=8YPN1mT5ZQg:k78rgFJkhbE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?i=8YPN1mT5ZQg:k78rgFJkhbE:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?a=8YPN1mT5ZQg:k78rgFJkhbE:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/ThoughtsOnSoftwareAndComputers?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ThoughtsOnSoftwareAndComputers/~4/8YPN1mT5ZQg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://software.tulentsev.com/2009/03/making-more-mockups/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://software.tulentsev.com/2009/03/making-more-mockups/</feedburner:origLink></item>
		<item>
		<title>SugarCRM: More colors!</title>
		<link>http://feedproxy.google.com/~r/ThoughtsOnSoftwareAndComputers/~3/yUcli0aEbyU/</link>
		<comments>http://software.tulentsev.com/2009/02/sugarcrm-more-colors/#comments</comments>
		<pubDate>Fri, 06 Feb 2009 18:24:41 +0000</pubDate>
		<dc:creator>Sergei Tulentsev</dc:creator>
				<category><![CDATA[SugarCRM]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[Calendar]]></category>
		<category><![CDATA[color]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://software.tulentsev.com/?p=120</guid>
		<description><![CDATA[When I was implementing previous issue, my manager asked me: &#8220;Can we also mark meetings with colors, corresponding to users?&#8221;. This way it becomes somewhat easier to identify originator of an event. &#8220;Yeah, it would be cool, but it can be tricky and difficult to implement&#8221;,  I said, rejecting the feature request. I said so [...]]]></description>
			<content:encoded><![CDATA[<p>When I was implementing <a title="SugarCRM: Really shared calendar" href="http://software.tulentsev.com/2009/02/sugarcrm-really-shared-calendar/">previous issue</a>, my manager asked me: &#8220;Can we also mark meetings with colors, corresponding to users?&#8221;. This way it becomes somewhat easier to identify originator of an event. &#8220;Yeah, it would be cool, but it can be tricky and difficult to implement&#8221;,  I said, rejecting the feature request. I said so just to save my ass from potentially frustrating project. Just the day before Marcelo had told me that he has a friend who was working with SugarCRM for a year and he hadn&#8217;t quite enjoyed the experience.<span id="more-120"></span></p>
<p>But later at home I was thinking about it and decided that it may not be as hard as it looks. We can divide the task into two subtasks:</p>
<ul>
<li>provide a unique color for each user</li>
<li>use this color when generating markup for an event</li>
</ul>
<p>The latter subtask was quite easy to implement, I already knew a place where the markup was generated. I was more scared by the former one. If done in &#8220;enterprisey&#8221; way, it could involve new property in User entity, new configuration screens, database alterations, etc. But there is a solution almost as good as abovementioned and much more simple. Let&#8217;s define a function that maps user name to color. md5() is a good candidate :-)</p>
<pre class="brush: php">function get_color_by_name($name)
{
    $html_color_string = substr(md5($name), 0, 6);
    return $html_color_string;
}</pre>
<p>I also used RGB&lt;=&gt;HSV transformation functions, because I wanted to get lighter colors. Initially I wanted to highlight event&#8217;s name with the color, but it turned out that text is not always readable. I decided not to write functions that calculate good contrasting colors and put a small color rectangle instead of highlight. This rectangle is essentially a span with several &amp;nbsp; &#8216;s as a body.</p>
<p>So, final result looks like this:<a href="http://software.tulentsev.com/wp-content/uploads/2009/02/sugar_colors.png"><img class="aligncenter size-full wp-image-123" title="sugar_colors" src="http://software.tulentsev.com/wp-content/uploads/2009/02/sugar_colors.png" alt="sugar_colors" width="577" height="616" /></a></p>
<p>Here is <a title="colors.patch" href="http://software.tulentsev.com/wp-content/uploads/2009/02/colors.patch">complete patch</a> (it has too big lines to look good on this page)</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/ThoughtsOnSoftwareAndComputers?a=by1vvwLE"><img src="http://feeds.feedburner.com/~f/ThoughtsOnSoftwareAndComputers?d=41" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/ThoughtsOnSoftwareAndComputers?a=tiwTl5lv"><img src="http://feeds.feedburner.com/~f/ThoughtsOnSoftwareAndComputers?i=tiwTl5lv" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/ThoughtsOnSoftwareAndComputers?a=7KUC6JWV"><img src="http://feeds.feedburner.com/~f/ThoughtsOnSoftwareAndComputers?d=52" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ThoughtsOnSoftwareAndComputers/~4/yUcli0aEbyU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://software.tulentsev.com/2009/02/sugarcrm-more-colors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://software.tulentsev.com/2009/02/sugarcrm-more-colors/</feedburner:origLink></item>
	</channel>
</rss>
