<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Seeping Matter &#187; C++</title>
	<atom:link href="http://www.mvryan.org/tag/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mvryan.org</link>
	<description>Tidbits about cars, auto racing, music, motocross, football, video games, investing, corporate America, politics...</description>
	<lastBuildDate>Sat, 04 Feb 2012 06:26:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Go &#8211; Programming Language Nirvana?</title>
		<link>http://www.mvryan.org/2009/11/go-programming-language-nirvana/</link>
		<comments>http://www.mvryan.org/2009/11/go-programming-language-nirvana/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 04:35:43 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://blog.mvryan.org/?p=718</guid>
		<description><![CDATA[Earlier this week Google announced their new programming language, called Go. Usually I don&#8217;t get too worked up about programming languages.  I already feel like I know more languages than I should need to know, and often a new language seems to me like &#8220;Hey, check this out!  Here&#8217;s a more complex or non-intuitive way [...]]]></description>
			<content:encoded><![CDATA[<div class="wp-caption alignleft" style="width: 163px"><a href="http://golang.org/" onclick="pageTracker._trackPageview('/outgoing/golang.org/?referer=');"><img title="The Go Gopher" src="http://golang.org/doc/logo-153x55.png" alt="The Go Gopher" width="153" height="55" /></a><p class="wp-caption-text">The Go Gopher</p></div>
<p>Earlier this week <a href="http://google-opensource.blogspot.com/2009/11/hey-ho-lets-go.html" onclick="pageTracker._trackPageview('/outgoing/google-opensource.blogspot.com/2009/11/hey-ho-lets-go.html?referer=');">Google announced their new programming language</a>, called Go.</p>
<p>Usually I don&#8217;t get too worked up about programming languages.  I already feel like I know more languages than I should need to know, and often a new language seems to me like &#8220;Hey, check this out!  Here&#8217;s a more complex or non-intuitive way to accomplish a task you already know how to accomplish, but in a language you will never use professionally!&#8221;</p>
<p>I know, I&#8217;m disappointing you.</p>
<p>But Go!  Oh my, this seems different.  From the blog post:</p>
<blockquote><p>Go combines the development speed of working in a dynamic language like Python with the performance and safety of a compiled language like C or C++. Typical&#8230;</p></blockquote>
<p>Wait!  Hold on there — my heart just skipped a beat and it freaked me out.  Can you please repeat that again?</p>
<blockquote><p>&#8230;a dynamic language like <strong>Python </strong>with the performance and safety of a compiled language like <strong>C or C++</strong>.</p></blockquote>
<p>Ooh baby.  Someone help me — I&#8217;m shaking with anticipation.  A systems programming language that combines Python and C++?  Can it really be?  It seems too good to be true!  My two favorite programming languages combined in one:  It&#8217;s like true programming nirvana!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mvryan.org/2009/11/go-programming-language-nirvana/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Actions Speak Louder Than Code</title>
		<link>http://www.mvryan.org/2009/08/actions-speak-louder-than-code/</link>
		<comments>http://www.mvryan.org/2009/08/actions-speak-louder-than-code/#comments</comments>
		<pubDate>Sat, 08 Aug 2009 00:19:35 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Career]]></category>
		<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Introspection]]></category>
		<category><![CDATA[Novell]]></category>
		<category><![CDATA[Rants]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://blog.mvryan.org/?p=620</guid>
		<description><![CDATA[It took me a while, but I finally settled into my routine and got to where I&#8217;m reading my RSS feeds most days again.  I was going through the posts of the past month or so, since the job change, and ran across this article on the &#8220;Making Good Software&#8221; blog about things that keep [...]]]></description>
			<content:encoded><![CDATA[<p>It took me a while, but I finally settled into my routine and got to where I&#8217;m reading my RSS feeds most days again.  I was going through the posts of the past month or so, since the job change, and ran across <a href="http://www.makinggoodsoftware.com/2009/07/07/5-top-non-technical-mistakes-made-by-programmers/" onclick="pageTracker._trackPageview('/outgoing/www.makinggoodsoftware.com/2009/07/07/5-top-non-technical-mistakes-made-by-programmers/?referer=');">this article</a> on the &#8220;Making Good Software&#8221; blog about things that keep someone from being a good software engineer, outside of (and often in spite of) an ability to engineer software.</p>
<p>I&#8217;ll summarize here.  It isn&#8217;t my intent to plagiarize; if you are remotely interested <a href="http://www.makinggoodsoftware.com/2009/07/07/5-top-non-technical-mistakes-made-by-programmers/" onclick="pageTracker._trackPageview('/outgoing/www.makinggoodsoftware.com/2009/07/07/5-top-non-technical-mistakes-made-by-programmers/?referer=');">go read the article</a>.  Here are the things:</p>
<ul>
<li>Lack of discipline</li>
<li>Big ego</li>
<li>Poor communication</li>
<li>Forgetting the customer</li>
<li>Lack of proper work prioritization</li>
</ul>
<p>I have known many of these people during my career.  Indeed, I was one of them.  I remember coming to Novell from IBM almost ten years ago.  I thought I was pretty hot stuff and I made sure my team knew it.  In fact, I actually said (this is embarrassing to admit) on more than one occasion, &#8220;There are people who know C++ better than I do, but I haven&#8217;t met any of them.&#8221;  My ego surely made me hard to work with.  It definitely was a cause of friction between myself and my management chain, and ended up being a (deserved) source of frustration and difficulty for me, until I recognized the problem and started working to address it.</p>
<p>I&#8217;m pretty ashamed of having behaved that way back then.  I hope I&#8217;m better than that today.  I guess recognizing the weakness is a good first step.  Fortunately for me, back then I was on a really great team with a lot of very capable, patient, and talented engineers that waited for me to learn from my mistakes and to grant them the mutual respect they deserved.  I consider myself pretty fortunate to have been able to learn from them what real software engineering is about.</p>
<p>Over my career I&#8217;ve had to work with people like this from time to time, software engineers that manifest one or more of these traits.  Sometimes these guys are pretty talented technically.  I&#8217;ve felt sorry for them as I&#8217;ve observed, realizing that these weaknesses are going to hold their career back until they recognize them and work to overcome them.  No amount of programming prowess will compensate for it.  And what&#8217;s even worse is, often because these people have the personality issues they have, you don&#8217;t get anywhere by trying to bring these weaknesses to their attention; they are often unreceptive to this type of feedback.  Like I said, you just have to wait until they recognize it themselves.</p>
<p>I can imagine being in a performance review with someone like this, having them explain to me all the technical awesome they did, and me replying, &#8220;Your poor soft skills are shouting so loudly that I cannot hear your technical awesomeness.&#8221;  Or, as I said in the title, actions speak louder than code.</p>
<p>I really believe this is true.  To write software professionally, of course you must have technical ability; however, this is a necessary but not sufficient condition for greatness.  The best software engineers I&#8217;ve had the fortune to work with in my career, past and present, not only had awesome technical ability but did not exhibit weakness in these areas.  And I&#8217;ll tell you what:  Those teams are wonderful teams to be a part of.  Those teams create strong. uplifting work environments and are able to deliver great products that meet customer demand.</p>
<p>Another way to say this is, in order to be a good software engineer, you must first be a good employee.</p>
<p>In fact, I&#8217;ll tell you how important I think this is.  The ability to mitigate or eliminate these defects from a software engineer&#8217;s persona is so important to me that, if I had my own company and were making the hiring decisions, I <em><strong>would not hire</strong></em> a candidate that I knew had these problems, no matter how incredible their technical ability.</p>
<p>A person with these weaknesses is really only suited to be set to the side to work on a special side R&amp;D project where interaction with other employees is limited, and they don&#8217;t have to interact with customers at all.  Problem is, those kind of projects are either a) strategically important to the long-term future of the company, or b) of little to no real value, or c) a combination, often high potential value but with a lot of inherent risk that causes the real value to be low.  If the project is strategically important or of high value, do you really want to reward the biggest jerk in your company by giving him the highest profile assignment, leaving your best engineers to maintain the legacy project?  Wouldn&#8217;t you want to have someone working on that high profile assignment that knows how to collaborate with others and assemble all the best ideas to solve the problem the best way, even if that solution isn&#8217;t his/her own?  Contrariwise, if the project is of little real value or has so much risk that it offsets the real value, why even do it at all?</p>
<p>Nope.  In my company, if I were ever to have one, I wouldn&#8217;t hire or keep an employee who had these weaknesses and was not committed to addressing them.  I&#8217;ve seen the difference, both in morale and productivity, between teams where they don&#8217;t have these problems and teams that do.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mvryan.org/2009/08/actions-speak-louder-than-code/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Versioning Containers and Iterators</title>
		<link>http://www.mvryan.org/2009/06/versioning-containers-and-iterators/</link>
		<comments>http://www.mvryan.org/2009/06/versioning-containers-and-iterators/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 00:52:22 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Shameless Self-Promotion]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://blog.mvryan.org/?p=555</guid>
		<description><![CDATA[Uh, this is a programming post.  Just so you know. The Problem Okay, so let&#8217;s start this discussion with a simple linked list that contains the ingredients for Bill Cosby&#8217;s Chocolate Cake for Breakfast: Normally we&#8217;d use a linked list in programming when we know we may have to arbitrarily insert items later on.  For [...]]]></description>
			<content:encoded><![CDATA[<p>Uh, this is a programming post.  Just so you know.</p>
<h3>The Problem</h3>
<p>Okay, so let&#8217;s start this discussion with a simple linked list that contains the ingredients for Bill Cosby&#8217;s Chocolate Cake for Breakfast:</p>
<div class="wp-caption aligncenter" style="width: 560px"><img title="Cake List 1" src="http://www.mvryan.org/images/cakelist1.png" alt="Fig. 1 - Linked list of ingredients for Chocolate Cake for Breakfast" width="550" height="148" /><p class="wp-caption-text">Fig. 1 - Linked list of ingredients for Chocolate Cake for Breakfast</p></div>
<p>Normally we&#8217;d use a linked list in programming when we know we may have to arbitrarily insert items later on.  For example, I just realized that this cake does not contain chocolate, so I should be able to insert that into the list by shuffling a little bit:</p>
<div class="wp-caption aligncenter" style="width: 560px"><img title="Chocolate Cake, with Chocolate" src="http://www.mvryan.org/images/cakelist2.png" alt="Fig. 2 - Chocolate Cake for Breakfast, with Chocolate Added" width="550" /><p class="wp-caption-text">Fig. 2 - Chocolate Cake for Breakfast, with Chocolate Added</p></div>
<p>This seems like a much tastier recipe.  But there can be a slight problem with this.</p>
<p>Suppose the linked list is serving as a model for your recipe view.  You have a UI that accessess the model and then displays the results in some sort of view that you can see on your laptop in the kitchen.  Suppose further that you decide to go even crazier and not just stop with adding chocolate, but you are also going to add sugar and frosting.  INSANE!</p>
<p>This is not a problem yet.  Likely your UI offers the ability to add new ingredients through the UI, so you just add them and the model gets updated, and when your view refreshes you see the new list:</p>
<div class="wp-caption aligncenter" style="width: 560px"><img title="Insane Chocolate Cake" src="http://www.mvryan.org/images/cakelist3.png" alt="Fig. 3 - Chocolate Cake for Breakfast - Dessert Style!" width="550" /><p class="wp-caption-text">Fig. 3 - Chocolate Cake for Breakfast - Dessert Style!</p></div>
<p>That sounds like a great chocolate cake.  But now suppose Mr. Cosby is on stage in Winnemucca doing his Chocolate Cake for Breakfast routine, and for some reason that nobody can understand the teleprompter that reminds him of the routine is using your data model to render the view &#8211; right at the exact moment in time that you are changing the recipe.</p>
<p>Uh-oh.</p>
<p>I&#8217;ve run into this problem a number of times in my software development career, where I have a data structure that is being accessed by more than one user at the same time.  In our case, we have one read-only accessor and one read/write accessor.  At first glance it doesn&#8217;t seem like this should be a problem.  But unfortunately, even though the reader isn&#8217;t making changes to the model, the reader still depends on the model having a constant state.</p>
<p>There&#8217;s a couple of fairly simple ways to address this problem.</p>
<p>First, we can make a copy of the model for each user.  We can have a resource that provides a copy when a user requests the copy.  Then that user can do whatever they want with the model &#8211; read or write.  When they are done, they can either discard their copy, or turn it back to the resource for the changes to be merged into the whole.</p>
<p>This might work for some implementations.  In our trivial example here it would probably be just fine.  But if I have a data structure with two million 50-byte records, this isn&#8217;t such a great idea.  It isn&#8217;t just that I don&#8217;t want to make a copy of a 100 Mbyte (okay, 95 for you technicality folk) data structure &#8211; I don&#8217;t want to double my memory usage from 100 Mbytes to 200 Mbytes (or 95 to 190, sheesh).  So making a copy won&#8217;t always work.</p>
<p>Another option is to lock the structure.  Using some sort of a mutual exclusion primitive I can lock the data structure so that only one user can access it at a time.  I can&#8217;t just hold the lock per-access, though &#8211; I have to maintain sessions and locks for the entire session.  In other words, I have to make sure that nobody can change the recipe at all throughout the duration of Mr. Cosby&#8217;s act.  This high level of granularity in the locking of the data structure makes it hard to use.  And it is particularly frustrating for read-only users who are thinking, &#8220;Why can&#8217;t I access the structure?  All I want to know is what is in it!&#8221;</p>
<h3>Versioning</h3>
<p>One way I&#8217;ve successfully solved this problem in production code is to use a versioned container and versioned iterators for that container.  I used these at Volera, for example, for some reason that doesn&#8217;t matter now, because Volera is DEAD.  Anyway, here&#8217;s how they work:</p>
<p><strong>Versioned Containers</strong> act pretty much like regular containers &#8211; vectors, lists, hashtables, etc.  The difference is that each link from one element in the container to the next has an associated version number on the link.  Any given element can have a number of &#8220;next&#8221; links &#8211; even a singly linked list, like in our example.  Each link would have a different version number.  The container itself also has a version number, which corresponds to the highest numbered link in the container.</p>
<p><strong>Versioned Iterators</strong> go along with the versioned container.  When you request an iterator from a container, it gives the iterator a version number which corresponds to the current version number of the container at the time of request.  The user requesting the iterator can also request a different version number.</p>
<p>Here&#8217;s what our data structure might look like if it were versioned:</p>
<div class="wp-caption aligncenter" style="width: 560px"><img title="Versioned Cake" src="http://www.mvryan.org/images/cakelist4.png" alt="Fig. 4 - Chocolate Cake for Breakfast with Versioned Containers and Iterators" width="550" /><p class="wp-caption-text">Fig. 4 - Chocolate Cake for Breakfast with Versioned Containers and Iterators</p></div>
<p>This ends up working out pretty cool.  Mr. Cosby can request a versioned iterator of the view when his show begins that displays the model as it is when his show starts.  Let&#8217;s say that his iterator is version 1.  That iterator traverses the list by only following links where the version number is less than or equal to the version number on the iterator.  So it first goes to &#8220;eggs&#8221;, then follows link 1 to &#8220;milk&#8221;, then follows link 1 to &#8220;wheat&#8221;, then ends.  It can be doing this at the same time that another user is changing the data structure, first by inserting &#8220;chocolate,&#8221; which creates the version 2 link from &#8220;milk&#8221; to &#8220;chocolate&#8221; and the version 2 link from &#8220;chocolate&#8221; to &#8220;wheat,&#8221; and later by inserting &#8220;sugar&#8221; and &#8220;frosting&#8221; as version 3.  A version two iterator on the structure would start with &#8220;eggs&#8221; then follow the version 1 link (remember &#8211; less than or equal to the iterator version) to &#8220;milk.&#8221;  But then it would follow the version 2 link instead of the version 1 link, so now it goes to &#8220;chocolate&#8221; instead of going directly to &#8220;wheat.&#8221;</p>
<p>The same goes for the version 3 iterator, which gives us everything in the data structure.</p>
<p>There&#8217;s a couple of issues you have to deal with when you implement a structure like this.  First off, you need some sort of a scheme to go through the structure and prune it of old traversal versions.  If I remember correctly, a scheme that will work to do this is to have the container itself remember how many users are accessing it and what versions they are at.  When one iterator goes away, the iterator should report this back to the container.  The container then looks to see if that iterator is the lowest-version-number iterator that it knew about.  If it is, the container can go through and prune all of the links that are versioned at that number and below, as well as nodes in the structure that are only included in the structure by links at that version and below.  So there&#8217;s a little bit of housekeeping that has to go on, but the container should be able to do this after iterators go away.</p>
<p>In other words, once Mr. Cosby&#8217;s show ends, the data structure that previously looked like Fig. 4 should end up looking more like Fig. 3.</p>
<p>Another problem to consider is this:  If the data structure lives for a long time and has lots of accessors, it is possible for the version numbers to overflow.  The overflowing isn&#8217;t necessarily a problem, though, as long as you keep track of what is really the oldest version in the data structure.  Another way to do this is, as you prune the table, you can take the liberty of reversioning the table if there are no accessors to the table.  Depending on your situation, you may never have a chance to lock the whole structure in order to reversion it, but the first option should be workable.</p>
<p>Lastly, since you have to version the links themselves, you might not be able to directly use standard containers; for example, if you are using C++ you might have to create your own linked list template with a list of versioned next pointers in each node, instead of implementing your versioned list container in terms of the STL list container.  I never tried this so I&#8217;m not sure how it would work.  When I did this, I did it using a tree container that was implemented in STL style, with versioning in the pointers and iterators.  It was pretty cool.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mvryan.org/2009/06/versioning-containers-and-iterators/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Computer Science Books</title>
		<link>http://www.mvryan.org/2009/05/computer-science-books/</link>
		<comments>http://www.mvryan.org/2009/05/computer-science-books/#comments</comments>
		<pubDate>Wed, 13 May 2009 00:41:41 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Career]]></category>
		<category><![CDATA[Learn To Program]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://blog.mvryan.org/?p=480</guid>
		<description><![CDATA[My inbox is overflowing with emails from people asking, &#8220;Matt, how can I be more like you?&#8221; Honestly, that is only sort of true.  Some of the emails say, &#8220;Lose 30 pounds in 12 minutes!&#8221;  And some say, &#8220;I am the prince of Nigeria!&#8221;  And some say, &#8220;I am lonely and looking for a purely [...]]]></description>
			<content:encoded><![CDATA[<p>My inbox is overflowing with emails from people asking, &#8220;Matt, how can I be more like you?&#8221;</p>
<p>Honestly, that is only sort of true.  Some of the emails say, &#8220;Lose 30 pounds in 12 minutes!&#8221;  And some say, &#8220;I am the prince of Nigeria!&#8221;  And some say, &#8220;I am lonely and looking for a purely physical relationship!&#8221;</p>
<p>More honestly, that pretty much comprises the bulk of the email I receive.  Nobody has actually asked how to be more like me, strangely enough.  But that day is surely coming, and since I am a computer scientist, or at least since USU says so, I could start with a list of books that you can read if you want to become a true nerd and rule the world the way I do, which is to say, not.</p>
<p>(So, in fairness, I haven&#8217;t actually read all of these or owned them.  There are some that I haven&#8217;t read, but I read one like it; those are marked in blue.  There are some that I haven&#8217;t read but think I should; those are marked in gray.  There are some that where I read one like it, but I want to read that particular one &#8211; they are bluish-gray.  And I didn&#8217;t list the probably 40-50 CS books I own or have owned and read that are not shown here.  So cut me a break.)</p>
<h2>Math and English</h2>
<p>First off, in order to be a good software engineer and computer scientist, you have to be a good mathematician and a good writer.  Sorry.  You simply can&#8217;t be a competent software engineer without a solid mathematical background, and you can&#8217;t be an effective one if you can&#8217;t figure out how to express your ideas clearly in writing.</p>
<div align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr valign="top">
<td align="center" style="background:#add8fd;">
<a href="http://www.amazon.com/Elementary-Algebra-Harold-R-Jacobs/dp/0716710471/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242093466&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Elementary-Algebra-Harold-R-Jacobs/dp/0716710471/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242093466_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/elemalgebra.jpg" width="100"></a>
</td>
<td align="center" style="background:#add8fd;">
<a href="http://www.amazon.com/Calculus-Made-Easy-Silvanus-Thompson/dp/0312185480/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242093698&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Calculus-Made-Easy-Silvanus-Thompson/dp/0312185480/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242093698_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/calculusmadeeasy.jpg" width="100"></a>
</td>
<td align="center" style="background:#81a1bc;">
<a href="http://www.amazon.com/Concrete-Mathematics-Foundation-Computer-Science/dp/0201558025/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242093750&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Concrete-Mathematics-Foundation-Computer-Science/dp/0201558025/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242093750_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/concretemathematics.jpg" width="100"></a>
</td>
<td align="center" style="background:#add8fd;">
<a href="http://www.amazon.com/Writing-Computer-Science-Justin-Zobel/dp/1852338024/ref=sr_1_2?ie=UTF8&#038;s=books&#038;qid=1242093953&#038;sr=1-2" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Writing-Computer-Science-Justin-Zobel/dp/1852338024/ref=sr_1_2?ie=UTF8_038_s=books_038_qid=1242093953_038_sr=1-2&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/writingforcompsci.jpg" width="100"></a>
</td>
</tr>
</table>
</div>
<h2>Learning to Program</h2>
<p>Your next step is to learn basic programming concepts.  In my opinion, you should learn two languages at this point:  Python and C.  Python is a good beginning language, very easy to create real applications, easy to learn, and very versatile and useful in the real world.  C is the fundamental systems programming language.  Knowing Python and C will allow you to program just about anything and gives you a good fundamental background.</p>
<div align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr valign="top">
<td align="center" style="background:#81a1bc;"><a href="http://www.amazon.com/Python-Programming-Introduction-Computer-Science/dp/1887902996/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242094819&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Python-Programming-Introduction-Computer-Science/dp/1887902996/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242094819_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/pythonprogramming.jpg" width="100"></a></td>
<td align="center"><a href="http://www.amazon.com/Python-Nutshell-Second-OReilly/dp/0596100469/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242094832&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Python-Nutshell-Second-OReilly/dp/0596100469/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242094832_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/pythoninanutshell.jpg" width="100"></a></td>
<td align="center" style="background:#add8fd;"><a href="http://www.amazon.com/Programming-C-3rd-Developers-Library/dp/0672326663/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242094851&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Programming-C-3rd-Developers-Library/dp/0672326663/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242094851_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/programminginc.jpg" width="100"></a></td>
<td align="center"><a href="http://www.amazon.com/Programming-Language-Prentice-Hall-Software/dp/0131103628/ref=sr_1_3?ie=UTF8&#038;s=books&#038;qid=1242094851&#038;sr=1-3" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Programming-Language-Prentice-Hall-Software/dp/0131103628/ref=sr_1_3?ie=UTF8_038_s=books_038_qid=1242094851_038_sr=1-3&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/cprogramminglanguage.jpg" width="100"></a></td>
</tr>
</table>
</div>
<h2>Computer Science Fundamentals</h2>
<p>Having learned how to write basic computer programs, now is time to get into the science of computer science.</p>
<div align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr valign="top">
<td align="center" style="background:#dddddd;"><a href="http://www.amazon.com/Art-Computer-Programming-Volumes-Boxed/dp/0201485419/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242095681&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Art-Computer-Programming-Volumes-Boxed/dp/0201485419/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242095681_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/knuth.jpg" width="100"></a></td>
<td align="center" style="background:#81a1bc;"><a href="http://www.amazon.com/Introduction-Algorithms-Thomas-H-Cormen/dp/0262032937/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242095885&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Introduction-Algorithms-Thomas-H-Cormen/dp/0262032937/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242095885_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/introtoalgorithms.jpg" width="100"></a></td>
<td align="center"><a href="http://www.amazon.com/Introduction-Computer-Theory-Daniel-Cohen/dp/0471137723/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242095921&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Introduction-Computer-Theory-Daniel-Cohen/dp/0471137723/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242095921_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/introtocomputertheory.jpg" width="100"></a></td>
<td align="center" style="background:#dddddd;"><a href="http://www.amazon.com/Algorithms-Parts-1-5-Bundle-Fundamentals/dp/0201756080/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242095936&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Algorithms-Parts-1-5-Bundle-Fundamentals/dp/0201756080/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242095936_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/algorithmsinc.jpg" width="100"></a></td>
</tr>
<tr valign="top">
<td align="center" style="background:#dddddd;"><a href="http://www.amazon.com/Compilers-Principles-Techniques-Tools-2nd/dp/0321486811/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242096093&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Compilers-Principles-Techniques-Tools-2nd/dp/0321486811/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242096093_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/compilers.jpg" width="100"></a></td>
<td align="center" style="background:#81a1bc;"><a href="http://www.amazon.com/Computer-Networks-4th-Andrew-Tanenbaum/dp/0130661023/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242096114&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Computer-Networks-4th-Andrew-Tanenbaum/dp/0130661023/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242096114_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/computernetworks.jpg" width="100"></a></td>
<td align="center" style="background:#81a1bc;"><a href="http://www.amazon.com/Beginning-Database-Design-Novice-Professional/dp/1590597699/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242096131&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Beginning-Database-Design-Novice-Professional/dp/1590597699/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242096131_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/begdbdesign.jpg" width="100"></a></td>
<td align="center" style="background:#81a1bc;"><a href="http://www.amazon.com/Schneiers-Cryptography-Classics-Library-Practical/dp/0470226269/ref=sr_1_2?ie=UTF8&#038;s=books&#038;qid=1242096150&#038;sr=1-2" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Schneiers-Cryptography-Classics-Library-Practical/dp/0470226269/ref=sr_1_2?ie=UTF8_038_s=books_038_qid=1242096150_038_sr=1-2&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/cryptographyclassics.jpg" width="100"></a></td>
</tr>
<tr valign="top">
<td align="center" style="background:#dddddd;"><a href="http://www.amazon.com/Synchronization-Algorithms-Concurrent-Programming-Taubenfeld/dp/0131972596/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242096282&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Synchronization-Algorithms-Concurrent-Programming-Taubenfeld/dp/0131972596/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242096282_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/syncalgandconcurrentprg.jpg" width="100"></a></td>
<td align="center" style="background:#81a1bc;"><a href="http://www.amazon.com/Art-Multiprocessor-Programming-Maurice-Herlihy/dp/0123705916/ref=sr_1_2?ie=UTF8&#038;s=books&#038;qid=1242096282&#038;sr=1-2" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Art-Multiprocessor-Programming-Maurice-Herlihy/dp/0123705916/ref=sr_1_2?ie=UTF8_038_s=books_038_qid=1242096282_038_sr=1-2&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/artofmultiprocprogramming.jpg" width="100"></a></td>
<td align="center" style="background:#add8fd;"><a href="http://www.amazon.com/Handbook-Mathematics-Computational-Science-Harris/dp/0387947469/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242096305&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Handbook-Mathematics-Computational-Science-Harris/dp/0387947469/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242096305_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/handbookofmathandcompsci.jpg" width="100"></a></td>
<td align="center"></td>
</tr>
</table>
</div>
<h2>Programming Technique and Methodology</h2>
<p>How to write software well.</p>
<div align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr valign="top">
<td align="center"><a href="http://www.amazon.com/Writing-Solid-Code-Microsofts-Programming/dp/1556155514/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242096617&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Writing-Solid-Code-Microsofts-Programming/dp/1556155514/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242096617_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/writingsolidcode.jpg" width="100"></a></td>
<td align="center"><a href="http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242096768&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242096768_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/codecomplete.jpg" width="100"></a></td>
<td align="center" style="background:#dddddd;"><a href="http://www.amazon.com/Software-Security-Building-Addison-Wesley/dp/0321356705/ref=pd_sim_b_3" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Software-Security-Building-Addison-Wesley/dp/0321356705/ref=pd_sim_b_3?referer=');"><img src="http://www.mvryan.org/images/bookcovers/swsec.jpg" width="100"></a></td>
</tr>
<tr valign="top">
<td align="center"><a href="http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/0201835959/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242096905&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/0201835959/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242096905_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/mythicalmanmonth.jpg" width="100"></a></td>
<td align="center"><a href="http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242096974&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242096974_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/designpatterns.jpg" width="100"></a></td>
<td align="center" style="background:#dddddd;"><a href="http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242096988&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242096988_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/pragmaticprogrammer.jpg" width="100"></a></td>
</tr>
<tr valign="top">
<td align="center" style="background:#add8fd;"><a href="http://www.amazon.com/Fundamentals-Software-Engineering-Carlo-Ghezzi/dp/0133056996/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242097068&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Fundamentals-Software-Engineering-Carlo-Ghezzi/dp/0133056996/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242097068_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/fundamentalsofsweng.jpg" width="100"></a></td>
<td align="center" style="background:#add8fd;"><a href="http://www.amazon.com/Extreme-Software-Engineering-Hands-Approach/dp/0130473812/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242097089&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Extreme-Software-Engineering-Hands-Approach/dp/0130473812/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242097089_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/extremesweng.jpg" width="100"></a></td>
<td align="center" style="background:#add8fd;"><a href="http://www.amazon.com/Practices-Agile-Developer-Pragmatic-Programmers/dp/097451408X/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242097107&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Practices-Agile-Developer-Pragmatic-Programmers/dp/097451408X/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242097107_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/practicesofagiledev.jpg" width="100"></a></td>
</tr>
</table>
</div>
<h2>General Programming</h2>
<p>Two other languages you might want to know are C++ and Java.  C++ is much maligned, but widely used, especially for systems applications, games, and other high-performing software applications.  Java is an abomination in every sense of the word.  But it is also very popular and good to know.  If you are going to learn Java, you should also learn JNI, so you can get from Java back to C and get some real work done.</p>
<div align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr valign="top">
<td align="center"><a href="http://www.amazon.com/C-Programming-Language-Special-3rd/dp/0201700735/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242152926&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/C-Programming-Language-Special-3rd/dp/0201700735/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242152926_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/c++programminglanguage.jpg" width="100"></a></td>
<td align="center"><a href="http://www.amazon.com/Effective-Specific-Addison-Wesley-Professional-Computing/dp/0321334876/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242152957&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Effective-Specific-Addison-Wesley-Professional-Computing/dp/0321334876/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242152957_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/effectivec++.jpg" width="100"></a></td>
<td align="center" style="background:#add8fd;"><a href="http://www.amazon.com/Introduction-Java-Programming-Comprehensive-Version/dp/0136012671/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242153004&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Introduction-Java-Programming-Comprehensive-Version/dp/0136012671/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242153004_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/introtojava.jpg" width="100"></a></td>
<td align="center"><a href="http://www.amazon.com/Java-Nutshell-5th-David-Flanagan/dp/0596007736/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242153036&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Java-Nutshell-5th-David-Flanagan/dp/0596007736/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242153036_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/javainanutshell.jpg" width="90"></a></td>
<td align="center"><a href="http://www.amazon.com/Essential-Jni-Java-Native-Interface/dp/0136798950/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242153058&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Essential-Jni-Java-Native-Interface/dp/0136798950/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242153058_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/essentialjni.jpg" width="90"></a></td>
</tr>
</table>
</div>
<h2>Systems Programming</h2>
<p>If you are going to do systems programming, you&#8217;ve got to know the specifics of how to program to the environment in question.  It&#8217;s worth noting here that the UNIX books basically cover POSIX, which applies not only to UNIX but BSD, Linux, and Mac as well to varying reasonable degrees.  I&#8217;ve also included an internals book for the big three platforms (Windows, Linux, and Mac).  And if you are going to program for Mac, you will probably want to learn another language: Objective-C.</p>
<div align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr valign="middle">
<th colspan="3">
<h3>UNIX/Linux</h3>
</th>
</tr>
<tr valign="top">
<td align="center"><a href="http://www.amazon.com/Programming-Environment-Addison-Wesley-Professional-Computing/dp/0321525949/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242153632&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Programming-Environment-Addison-Wesley-Professional-Computing/dp/0321525949/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242153632_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/apue.jpg" width="100"></a></td>
<td align="center"><a href="http://www.amazon.com/Unix-Network-Programming-Addison-Wesley-Professional/dp/0131411551/ref=sr_1_6?ie=UTF8&#038;s=books&#038;qid=1242153632&#038;sr=1-6" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Unix-Network-Programming-Addison-Wesley-Professional/dp/0131411551/ref=sr_1_6?ie=UTF8_038_s=books_038_qid=1242153632_038_sr=1-6&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/unp1.jpg" width="100"></a></td>
<td align="center"><a href="http://www.amazon.com/UNIX-Network-Programming-Interprocess-Communications/dp/0130810819/ref=sr_1_10?ie=UTF8&#038;s=books&#038;qid=1242153632&#038;sr=1-10" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/UNIX-Network-Programming-Interprocess-Communications/dp/0130810819/ref=sr_1_10?ie=UTF8_038_s=books_038_qid=1242153632_038_sr=1-10&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/unp2.jpg" width="100"></a></td>
</tr>
<tr valign="top">
<td align="center" style="background:#81a1bc;"><a href="http://www.amazon.com/UNIX-Systems-Programming-Communication-Concurrency/dp/0130424110/ref=sr_1_4?ie=UTF8&#038;s=books&#038;qid=1242153632&#038;sr=1-4" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/UNIX-Systems-Programming-Communication-Concurrency/dp/0130424110/ref=sr_1_4?ie=UTF8_038_s=books_038_qid=1242153632_038_sr=1-4&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/unixsysprog.jpg" width="100"></a></td>
<td align="center" style="background:#81a1bc;"><a href="http://www.amazon.com/Linux-Programming-Example-Fundamentals-Development/dp/0131429647/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242153850&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Linux-Programming-Example-Fundamentals-Development/dp/0131429647/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242153850_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/linuxprogrammingbyexample.jpg" width="100"></a></td>
<td align="center" style="background:#dddddd;"><a href="http://www.amazon.com/Linux-Kernel-Development-Novell-Press/dp/0672327201/ref=sr_1_2?ie=UTF8&#038;s=books&#038;qid=1242153862&#038;sr=1-2" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Linux-Kernel-Development-Novell-Press/dp/0672327201/ref=sr_1_2?ie=UTF8_038_s=books_038_qid=1242153862_038_sr=1-2&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/linuxkerneldev.jpg" width="100"></a></td>
</tr>
<tr valign="middle">
<th colspan="3">
<h3>Windows</h3>
</th>
</tr>
<td align="center"><a href="http://www.amazon.com/Windows-via-C-Pro-Developer/dp/0735624240/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242154365&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Windows-via-C-Pro-Developer/dp/0735624240/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242154365_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/windowsviac.jpg" width="100"></a></td>
<td align="center"><a href="http://www.amazon.com/Advanced-Debugging-Addison-Wesley-Microsoft-Technology/dp/0321374460/ref=sr_1_2?ie=UTF8&#038;s=books&#038;qid=1242154365&#038;sr=1-2" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Advanced-Debugging-Addison-Wesley-Microsoft-Technology/dp/0321374460/ref=sr_1_2?ie=UTF8_038_s=books_038_qid=1242154365_038_sr=1-2&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/advancedwindowsdebugging.jpg" width="100"></a></td>
<td align="center" style="background:#dddddd;"><a href="http://www.amazon.com/Microsoft-Windows-Internals-4th-Server/dp/0735619174/ref=sr_1_3?ie=UTF8&#038;s=books&#038;qid=1242154365&#038;sr=1-3" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Microsoft-Windows-Internals-4th-Server/dp/0735619174/ref=sr_1_3?ie=UTF8_038_s=books_038_qid=1242154365_038_sr=1-3&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/windowsinternals.jpg" width="100"></a></td>
<tr valign="top">
</tr>
<tr valign="middle">
<th colspan="3">
<h3>Mac OS X</h3>
</th>
</tr>
<tr valign="top">
<td align="center"><a href="http://www.amazon.com/Programming-Objective-C-2-0-Developers-Library/dp/0321566157/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242154381&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Programming-Objective-C-2-0-Developers-Library/dp/0321566157/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242154381_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/proginobjc.jpg" width="100"></a></td>
<td align="center"><a href="http://www.amazon.com/Cocoa-Programming-Mac-OS-3rd/dp/0321503619/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242154388&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Cocoa-Programming-Mac-OS-3rd/dp/0321503619/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242154388_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/cocoaprogramming.jpg" width="100"></a></td>
<td align="center" style="background:#dddddd;"><a href="http://www.amazon.com/Mac-OS-Internals-Systems-Approach/dp/0321278542/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242154399&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Mac-OS-Internals-Systems-Approach/dp/0321278542/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242154399_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/macosxinternals.jpg" width="100"></a></td>
</tr>
</table>
</div>
<h2>Other</h2>
<p>Every good software engineer should clearly understand open source; hence The Cathedral and the Bazaar.  You will find you are missing out on a number of inside jokes if you don&#8217;t read The Hitchhiker&#8217;s Guide to the Galaxy.  And everyone should read The Code Book, simply because it is so interesting.</p>
<div align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr valign="top">
<td align="center"><a href="http://www.amazon.com/Cathedral-Bazaar-Musings-Accidental-Revolutionary/dp/0596001088/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242154799&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Cathedral-Bazaar-Musings-Accidental-Revolutionary/dp/0596001088/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242154799_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/catb.jpg" width="100"></a></td>
<td align="center"><a href="http://www.amazon.com/Ultimate-Hitchhikers-Guide-Galaxy/dp/0345453743/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242154808&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Ultimate-Hitchhikers-Guide-Galaxy/dp/0345453743/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242154808_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/hitchhikersguide.jpg" width="100"></a></td>
<td align="center"><a href="http://www.amazon.com/Code-Book-Science-Secrecy-Cryptography/dp/0385495323/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1242154815&#038;sr=1-1" onclick="pageTracker._trackPageview('/outgoing/www.amazon.com/Code-Book-Science-Secrecy-Cryptography/dp/0385495323/ref=sr_1_1?ie=UTF8_038_s=books_038_qid=1242154815_038_sr=1-1&amp;referer=');"><img src="http://www.mvryan.org/images/bookcovers/thecodebook.jpg" width="100"></a></td>
</tr>
</table>
</div>
<h6>Image Credits: amazon.com and barnesandnoble.com</h6>
]]></content:encoded>
			<wfw:commentRss>http://www.mvryan.org/2009/05/computer-science-books/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Interview Tip &#8211; Don&#8217;t Lie</title>
		<link>http://www.mvryan.org/2009/03/interview-tip-dont-lie/</link>
		<comments>http://www.mvryan.org/2009/03/interview-tip-dont-lie/#comments</comments>
		<pubDate>Thu, 05 Mar 2009 07:02:02 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rants]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Career]]></category>
		<category><![CDATA[Mozy]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://blog.mvryan.org/?p=425</guid>
		<description><![CDATA[Mozy is hiring.  I mean, Decho is hiring.  Decho is the silly name given to replace the awesome of Mozy.  We still call it Mozy, we can&#8217;t help it. Anyway, we&#8217;re hiring.  Specifically, my team, the client team, is hiring.  And since Mozy decided to make me the manager of the Windows client team, that [...]]]></description>
			<content:encoded><![CDATA[<p>Mozy is hiring.  I mean, Decho is hiring.  Decho is the silly name given to replace the awesome of Mozy.  We still call it Mozy, we can&#8217;t help it.</p>
<p>Anyway, we&#8217;re hiring.  Specifically, my team, the client team, is hiring.  And since Mozy decided to make me the manager of the Windows client team, that means I&#8217;m participating in the interviews.  This is stressing me out, because I feel like I am deciding the fate of people.</p>
<p>The process of getting hired at Mozy (arrgh, Decho) goes something like this:</p>
<ul>
<li>Apply and submit a resume.</li>
<li>If we like your resume we will do a phone interview.</li>
<li>If you do well in the phone interview we will bring you in for on-site interviews.</li>
<li>If you do well in the on-site interviews we will assign you a homework assignment.</li>
<li>If you do well on the homework and you are the best candidate we have for the position, there&#8217;s a decent chance you&#8217;ll get an offer.</li>
</ul>
<p>Development work at Mozy is primarily done in C++.  Objective-C on the Mac side.  Pretty much you have to know C and C++ and/or Objective-C to get a development job, unless you want to work for the web team, using Ruby.  But those guys are kinda weird.  They sit on a different floor in the building and everything.  We&#8217;re not talking about those guys.</p>
<p>So during the phone screen, we ask you to rate yourself on C++.</p>
<p>We explain the rating scale like this:  0 means you are my father, waiting for this computer fad to go away, and you haven&#8217;t really heard of C++.  1 means you wrote Hello World in C++ once, and might be able to do it again today.  On the other end of the scale, 10 means your name is Bjarne Stroustrup, or maybe Herb Sutter or Andrei Alexandrescu.  9 means you have written books on C++; 8 means you could write a book on it, or teach courses on it.</p>
<p>Please, people.  Do not flatter yourself on the C++ scale.</p>
<p>I interviewed with Google once, over the phone.  They asked me this same question with pretty much the same scale, except they made no mention of my father.  I told them I was a 6 or a 7.  And I actually have taught courses on C++.</p>
<p>Lately we&#8217;re asking people this question and invariably we&#8217;re getting people saying, &#8220;Oh, based on that scale, I&#8217;m a 7 or an 8.&#8221;  Even kids in college.  Now I&#8217;m not saying that kids in college can&#8217;t be a 7 or an 8 &#8211; just, keep in mind, we&#8217;re not seeing a lot of true 7&#8242;s or 8&#8242;s among experienced professionals.  I&#8217;m just sayin&#8217;.</p>
<p>When you say in your interview, &#8220;I&#8217;m a 7 or an 8,&#8221; what you are telling me is this:  &#8220;I know C++ better than you.&#8221;  Now, you don&#8217;t probably know me personally, so hey, maybe you are better.  All I&#8217;m saying is, you&#8217;d better be ready to prove it when we bring you on-site.</p>
<p>For example, you&#8217;d better know <strong>at least</strong> most of this stuff:</p>
<ul>
<li>How to define a template class</li>
<li>How to correctly define the assignment operator for a class</li>
<li>How to overload the insertion and extraction operators for a class you define</li>
<li>How to iterate over an STL vector</li>
<li>Whether ++i is better, worse, or the same as i++, performance-wise, and why</li>
<li>What methods the compiler will create for you if you don&#8217;t create them yourself, and the implications of this</li>
<li>How to indicate in your developer contract whether a class is meant to be subclassed, which methods are overrideable, and how you insist that only subclasses can be instantiated</li>
<li>How to specify default values for parameters</li>
</ul>
<p>If you are a 7 or an 8, you probably should have read most of &#8220;The C++ Programming Language&#8221; and/or &#8220;Effective C++&#8221; and/or &#8220;Advanced C++&#8221; and/or a number of equivalents.  Having read &#8220;Design Patterns&#8221; would certainly help, although lately those have kinda lost their glimmer and so I don&#8217;t weigh on those like I used to.</p>
<p>Also:</p>
<ul>
<li>What <em>const </em>and <em>mutable</em> mean</li>
</ul>
<p>Yeah.  <em>const</em>.  Don&#8217;t be like the self-proclaimed C++ expert I worked with at Enterasys Networks, who told the whole company he was the go-to guy for C++ questions, who, when asked, &#8220;Why does it say <em>const</em> after this method declaration?&#8221; replied, &#8220;Oh, they just do that a lot in C++; it doesn&#8217;t mean anything.&#8221;  Yeah.  Don&#8217;t be a doofus.</p>
<p>Don&#8217;t try to impress me by saying you are a 7 or an 8 if you aren&#8217;t.  Really &#8211; you don&#8217;t have to be a 7 or an 8 to get a job at Mozy (Decho&#8230;hrm).  If you say, &#8220;Oh, I&#8217;m probably a 5,&#8221; that tells me you are a good, solid C++ dude (or dudette, whatever) that knows how to write decent C++ applications.  You&#8217;ll probably get asked to come in for an interview anyway.</p>
<p>When we bring you in, it is my job (and Cody&#8217;s) to figure out how much of C++ you really know.  We will start out at the point you specified and go from there.  If you are really a 5 or a 6, but you said 7 or 8, you will feel like we&#8217;re being very brutal on you.  Hey, you are the one who said you knew your stuff.</p>
<p>Oh &#8211; one more thing.  Some of you experienced hires don&#8217;t think you should have to go through all of this to get a job with us.  Well, we make the rules.  Every one of us that works there has gone through it.  If you think the rules of Monopoly are dumb, nobody&#8217;s gonna think bad of you if you decide not to play.  But if you want to play but not follow the rules, well, don&#8217;t be too surprised if people take issue with that.  If you&#8217;re gonna try to work at Moz &#8211; uh, Decho, at least for my team, just go through the process like everyone else.</p>
<p>Okay, I feel better.  Whew.  Oh, and by the way, if you really are a 7 or an 8 (or better), I have a <a href="http://mozy.com/careers" onclick="pageTracker._trackPageview('/outgoing/mozy.com/careers?referer=');">link</a> for you.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mvryan.org/2009/03/interview-tip-dont-lie/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Popping Threadsafe Containers</title>
		<link>http://www.mvryan.org/2009/02/popping-threadsafe-containers/</link>
		<comments>http://www.mvryan.org/2009/02/popping-threadsafe-containers/#comments</comments>
		<pubDate>Tue, 17 Feb 2009 17:56:02 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.mvryan.org/?p=406</guid>
		<description><![CDATA[After spending a bit of time last week dealing with thread safety issues and a queue in C++, it only seems appropriate to blog a bit about it.  (Obviously, the information below would also apply to a stack or probably any other container type.) Suppose you have a very common multiprocessing scenario:  two threads, one [...]]]></description>
			<content:encoded><![CDATA[<p>After spending a bit of time last week dealing with thread safety issues and a queue in C++, it only seems appropriate to blog a bit about it.  (Obviously, the information below would also apply to a stack or probably any other container type.)</p>
<p>Suppose you have a very common multiprocessing scenario:  two threads, one of which is producing work to be done, and another which is consuming the work to be done and performing the work.  You can accomplish this in a pretty straightforward fashion with:</p>
<ul>
<li>A queue</li>
<li>Mutexes to prevent concurrent queue access</li>
<li>A condition variable to tell the consumer when there is work to do</li>
</ul>
<p>Originally I thought about creating my own container class for this.  Then part of my brain resisted.  &#8220;Quiet, engineering part of Matt&#8217;s brain!&#8221; it exclaimed.  &#8220;You&#8217;re just trying to do that because it seems Interesting!&#8221;  So I shut down that idea and pushed on trying to use a standard STL queue.  However, after I had to deal with some concurrency issues over and over, I realized that, at least this time, the engineering part of my brain was right.</p>
<p>So I set out to create a threadsafe queue.  The idea was that it would feel a lot like an STL queue, and would implement thread safety under the covers for you &#8211; so, for example, a simple call to q.empty() would automatically lock the mutex for you, see if the underlying queue was empty, then unlock and return the result.  So, essentially an STL queue wrapper class with automatic mutex locking, right?  It should be easy!</p>
<p>Well, you&#8217;d think so, until you get to an implementation of pop().</p>
<p>To see why this matters, first we should establish what we expect out of a threadsafe queue in C++:</p>
<ul>
<li>It should feel like an STL queue.  This means that it should have similar semantics and API if possible, and also, it should be a template.</li>
<li>You get out what you put in.  Not a handle to what you put in; exactly what you put in is what you get out.</li>
<li>Thread safety should be handled automatically &#8211; the user shouldn&#8217;t have to deal with thread safety.</li>
</ul>
<p>An STL queue &#8220;pop()&#8221; isn&#8217;t as simple as it sounds.  The concept of &#8220;pop&#8221; is actually performed like this:</p>
<pre>    std::queue q;
    ...
    if (! q.empty()) {
        int v = q.front();
        q.pop();
    }</pre>
<p>Popping an empty queue has strange consequences; in fact, on my machine, it segfaults.  You&#8217;d think the queue would be resilient to that behavior but it isn&#8217;t.  Also, you have to get the item off the front in a separate operation from actually removing the item.  This is so you can store anything in the queue &#8211; pointers, reference objects, etc. &#8211; and obtain the item in the front of the queue and know it will survive long enough for you to do something with it.  You pop() the queue after you are finished with the item.</p>
<p>That&#8217;s all fine but it makes our threadsafe queue a bit of a problem.  Suppose we decide to follow strictly the STL queue API.  In that case, we&#8217;d perform an &#8220;if not q.empty(), then q.front() and q.pop()&#8221; dance.  We have to assume that each of those three actions is legal on its own though, and we surely can&#8217;t release the lock after each one.  So that would mean that the user has to obtain a lock on their own, to be used outside of the whole three-step dance, which breaks one of our rules, namely, that the user shouldn&#8217;t have to deal with thread safety.</p>
<p>Okay, so what if we abandon the need for strict adherence to the STL queue semantics, and instead just implement a pop() method that does everything?  Now we can hide the thread safety management from the user.  But now we have a different problem.  How do we know whether the value we get back from pop() is a legal value?  How do we know whether it came from the queue or whether the queue was empty and there was nothing to pop()?  We need some way to check to see whether the value coming back is valid, i.e., whether there was something in the queue to pop beforehand.</p>
<p>There&#8217;s a couple of ways to do this, but none I like.</p>
<ul>
<li>If the return value were a pointer (or an iterator), we could check for NULL (or end()).  However, we don&#8217;t necessarily know that.  If the class is a template, and if we always get back what we put in, we can&#8217;t know whether the return value is a pointer or a value or a reference.  True, we could <strong>cast</strong> the return value to a pointer type &#8211; but then, not only are we not returning what we put in, but we are getting into a rather scary situation where the user is required to massage the data before it can be used properly.  And we lose type safety.</li>
<li>We could return a std::pair&lt;bool, t&gt; where t is the type used to populate the queue.  Not as scary as the casting solution before, but still with the problem where the user has to massage the data, and the return value isn&#8217;t strictly what was put in (although it is contained in the pair).</li>
<li>We could throw an exception if the container is empty, but an empty container isn&#8217;t exactly an exceptional case and is probably not a good ethical candidate for throwing an exception.</li>
<li>We could stop using the STL queue and create our own queue with more reasonable semantics.  However, although I&#8217;m not necessarily in love with the STL queue, I&#8217;m also not convinced I can do it better, at least not convinced enough that I want to spend the time to do something that already exists.</li>
<li>We could do away with making the wrapper class a template and instead make it implementation-specific.</li>
</ul>
<p>Since I don&#8217;t know for sure that I will need my threadsafe queue for anything other than a very specific data type I have in mind right now, I chose the last option.  This is the agile way &#8211; I&#8217;ll meet today&#8217;s requirements today, and trust that I can refactor the code to meet future requirements when they show up.</p>
<p>So now everything works great, except doing the wait on the condition variable, which normally looks something like this:</p>
<pre>    mutex m;
    condvar cv;
    m.lock();
    if (q.empty()) cv.wait(m);
    v = q.pop();</pre>
<p>Yeah, here I am, managing thread safety outside of the queue again.  I really should put this into my threadsafe queue also; except I would need a method something like waitThenDo(action) where action is a function pointer or some other callable.  I hate how that makes my code look though.  And at this point, with the waiting done as shown above (roughly), my code is working, so I&#8217;ve stopped caring.</p>
<p>But if you have a great solution to this problem, I&#8217;d love to hear it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mvryan.org/2009/02/popping-threadsafe-containers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

