<?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>Curiously Nerdy &#187; Software Development</title>
	<atom:link href="http://blogs.6bit.com/josh/category/technology/software-development/feed/" rel="self" type="application/rss+xml" />
	<link>http://blogs.6bit.com/josh</link>
	<description>The Original</description>
	<lastBuildDate>Fri, 02 Jul 2010 17:58:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Linq Aggregate Empty Sequence</title>
		<link>http://blogs.6bit.com/josh/2010/04/linq-aggregate-empty-sequence/</link>
		<comments>http://blogs.6bit.com/josh/2010/04/linq-aggregate-empty-sequence/#comments</comments>
		<pubDate>Tue, 20 Apr 2010 18:19:51 +0000</pubDate>
		<dc:creator>Josh Perry</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[LINQ]]></category>

		<guid isPermaLink="false">http://blogs.6bit.com/josh/?p=280</guid>
		<description><![CDATA[Linq is great for its compact expressions, and for its &#8212; usually efficient &#8212; lazy-evaluation. These two virtues seem to be spit upon by the Aggregate function. Say you want to aggregate a list of ints. var s = new int[] {1, 2, 3}; int sum = ints.Aggregate((a,b) => a + b); This works great [...]]]></description>
			<content:encoded><![CDATA[<p>Linq is great for its compact expressions, and for its &#8212; usually efficient &#8212; lazy-evaluation. These two virtues seem to be spit upon by the Aggregate function.</p>
<p>Say you want to aggregate a list of ints.</p>
<p><code class="prettyprint">var s = new int[] {1, 2, 3};<br />
int sum = ints.Aggregate((a,b) => a + b);<br />
</code></p>
<p>This works great if your list has elements in it, or they aren&#8217;t filtered out in a where clause. Say you had a function that took a list of ints and someone passed that list of 1,2,3 to your function:</p>
<p><code class="prettyprint">int SumOverTen(IEnumerable&lt;int&gt; ints)<br />
{<br />
    int agg = ints.Where(i => i > 10).Aggregate((a,b)=> a+b);<br />
    return agg;<br />
}</code></p>
<p>Everything now goes pear-shaped and you get an InvalidOperationException &#8220;Sequence contains no elements&#8221;.</p>
<p>So what do you do to fix this? You could rewrite your function to check for an empty result first:</p>
<p><code class="prettyprint">int SumOverTen(IEnumerable&lt;int&gt; ints)<br />
{<br />
    int agg = 0;<br />
    var bigints = ints.Where(i => i > 10);<br />
    if(bigints.Count() > 0)<br />
        agg = bigints.Aggregate((a,b)=> a+b);</p>
<p>    return agg;<br />
}</code></p>
<p>This makes a nice Linq expression into a nasty branching mess. The list will now be enumerated twice, once for Count and once for Aggregate.</p>
<p>Well, it turns out that there is a better way, using Linq:</p>
<p><code class="prettyprint">int SumOverTen(IEnumerable&lt;int&gt; ints)<br />
{<br />
    int agg = ints.Where(i => i > 10)<br />
                  .DefaultIfEmpty()<br />
                  .Aggregate((a,b)=> a+b);</p>
<p>    return agg;<br />
}</code></p>
<p>This results in the same value as the previous function but is much more legible and throws no exceptions on an empty list. However, I don&#8217;t know how DefaultIfEmpty checks for an empty list so it may not be more efficient than the previous code.</p>
<p>What I want to know is, why does Aggregate throw instead of returning the same result as using DefaultIfEmpty?</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.6bit.com/josh/2010/04/linq-aggregate-empty-sequence/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>C++/CLI Converting from String to wchar_t and to char*</title>
		<link>http://blogs.6bit.com/josh/2010/01/ccli-converting-from-string-to-wchar_t-and-to-char/</link>
		<comments>http://blogs.6bit.com/josh/2010/01/ccli-converting-from-string-to-wchar_t-and-to-char/#comments</comments>
		<pubDate>Sun, 24 Jan 2010 21:01:19 +0000</pubDate>
		<dc:creator>Josh Perry</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[C++/CLI]]></category>
		<category><![CDATA[CLI]]></category>

		<guid isPermaLink="false">http://blogs.6bit.com/josh/?p=189</guid>
		<description><![CDATA[I recently started working on a managed wrapper for the Terminal Services API, and as my C++/CLI is a bit rusty I ran into some issues which I&#8217;m sure are common when trying to handle the impedance mismatch between the managed and unmanaged worlds. I&#8217;m going to take a look at one of those issues [...]]]></description>
			<content:encoded><![CDATA[<p>I recently started working on a managed wrapper for the Terminal Services API, and as my C++/CLI is a bit rusty I ran into some issues which I&#8217;m sure are common when trying to handle the impedance mismatch between the managed and unmanaged worlds.</p>
<p>I&#8217;m going to take a look at one of those issues here, and that is using System::String with native functions. The Win32 API is one such body of native functions and they fairly consistently take LPTCHAR parameters for strings. This type is a typedef to TCHAR*, TCHAR in turn is a typedef to wchar_t for Unicode builds and char otherwise.</p>
<h2>Toll-free bridge with CString</h2>
<p>One easy and automatic way to do this conversion is to bridge it through CString, this is a type that is part of Microsoft&#8217;s ATL. I believe it was first part of MFC but it&#8217;s since been divorced from depending on the rest of MFC and even the ATL proper or it&#8217;s server classes; include atlstr.h instead of cstringt.h.</p>
<p>The char type of CString is internally based on TCHAR as well, so depending on if you are doing a Unicode build the internal representation of the CString will be either wchar_t or char. The CLI has no such type differentiation, String is always a wide character string. This means that in Unicode builds we don&#8217;t need to do a conversion, but non-Unicode builds will, and CString takes care of this for us through it&#8217;s helpfull conversion constructor that accepts a System::String^.</p>
<p><code class="prettyprint"><br />
template &lt;class SystemString><br />
CStringT( SystemString^ pString ) :<br />
	CThisSimpleString( StringTraits::GetDefaultManager() )<br />
{<br />
	cli::pin_ptr&lt;const System::Char> pChar = PtrToStringChars( pString );<br />
	const wchar_t *psz = pChar;<br />
	*this = psz;<br />
}<br />
</code></p>
<p>`PtrToStringChars` retrieves a pointer to the String&#8217;s internal memory buffer, no copy here. The pointer returned is then pinned so that the Garbage Collector will not move it while we use it. It then uses an implicit conversion to go from `pin_ptr&lt;const System::Char&gt;` to `const wchar_t*`. Finally it uses the copy assignment operator of CString (which delegates to a base class operator) to copy the contents of the String buffer into itself. In a Unicode build this copy assignment operator decays to a basic memory copy, otherwise a different copy assignment operator is invoked that uses WideCharToMultiByte to convert to the CStrings internal char type.</p>
<p><code class="prettyprint"><br />
// This gets called when the right-hand-side pszSrc is the same char type as the internal storage<br />
// It simply delegates to it's base class to copy the source buffer into itself<br />
CStringT&#038; operator=( _In_opt_z_ PCXSTR pszSrc )<br />
{<br />
	CThisSimpleString::operator=( pszSrc );</p>
<p>	return( *this );<br />
}</p>
<p>// This gets called when the right-hand-side pszSrc has a different char type than the internal storage<br />
// It converts to the internal storage char type directly into it's internal buffer<br />
CStringT&#038; operator=( _In_opt_z_ PCYSTR pszSrc )<br />
{<br />
	// nDestLength is in XCHARs<br />
	int nDestLength = (pszSrc != NULL) ? StringTraits::GetBaseTypeLength( pszSrc ) : 0;<br />
	if( nDestLength > 0 )<br />
	{<br />
		PXSTR pszBuffer = GetBuffer( nDestLength );<br />
		StringTraits::ConvertToBaseType( pszBuffer, nDestLength, pszSrc);<br />
		ReleaseBufferSetLength( nDestLength );<br />
	}<br />
	else<br />
	{<br />
		Empty();<br />
	}</p>
<p>	return( *this );<br />
}</p>
<p>static void ConvertToBaseType(_Out_cap_(nDestLength) _CharType* pszDest, _In_ int nDestLength,<br />
	_In_count_(nSrcLength) const wchar_t* pszSrc, _In_ int nSrcLength = -1) throw()<br />
{<br />
	// nLen is in XCHARs<br />
	::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL);<br />
}<br />
</code></p>
<p>Now we can use the CString in place of `LPCTSTR` parameter because it has a user-defined conversion operator that simply returns the guts of the CString. This automatically does-the-right-thing when calling functions in Unicode builds and non-Unicode builds, all with no #ifdefs.</p>
<p><code class="prettyprint"><br />
operator PCXSTR() const throw()<br />
{<br />
	return( m_pszData );<br />
}<br />
</code></p>
<p>`PCXSTR` is a chain of typedefs that eventually, through TCHAR, finds it&#8217;s way to a `const wchar_t*`. PCXSTR means &#8220;pointer to a const null-terminated string of the same char type I am&#8221;, it also has PXSTR and XCHAR typedefs. In addition to the `X` typedefs it also has a set of `Y` typedefs (PCYSTR, PYSTR, YCHAR) that map to the opposite of the `X` typedefs, if the `X` is wchar_t then the `Y` is char. It uses the set of `Y` typedefs to create a number of copy assignment operators and conversion constructors that convert from either character type to the internal type.</p>
<h2>Conversion to Mutlibyte UTF8</h2>
<p>There is one problem that this doesn&#8217;t cover however, and that is how to convert your Unicode String into a `const char*` for use as parameters to functions that don&#8217;t have Unicode counterparts. Stan Lippman has a <a href="http://blogs.msdn.com/slippman/archive/2004/06/02/147090.aspx">blog post</a> from back in 2004 where he presents a couple of functions to handle this conversion to char* and to std::string. We&#8217;ll see some similarities with the CString constructors.</p>
<p><code class="prettyprint"><br />
bool To_CharStar( String^ source, char*&#038; target )<br />
{<br />
    pin_ptr&lt;const wchar_t&gt; wch = PtrToStringChars( source );<br />
    int len = (( source-&gt;Length+1) * 2);<br />
    target = new char[ len ];<br />
    return wcstombs( target, wch, len ) != -1;<br />
}</p>
<p>bool To_string( String^ source, string &#038;target )<br />
{<br />
    pin_ptr&lt;const wchar_t&gt; wch = PtrToStringChars( source );<br />
    int len = (( source-&gt;Length+1) * 2);<br />
    char *ch = new char[ len ];<br />
    bool result = wcstombs( ch, wch, len ) != -1;<br />
    target = ch;<br />
    delete ch;<br />
    return result;<br />
}<br />
</code></p>
<p>There are a couple problems with these functions. First, they are not reentrant and hence not thread safe, wcstombs keeps a global internal state during the conversion of a string. Second, they only work with UTF-16, which String always is, but it over allocates for simple single-byte character sets like ASCII. Third, they create an unecissary temporary buffer in the case of the std::string converter. And in the case of the char* converter it put the onus of freeing the buffer on the caller, which is doubly dangerous here because since the function uses new[] to allocate the buffer, the caller needs to know to call delete[].</p>
<p>Lets take a whack at implementing these functions in the way of the C++ standard library while solving these deficiencies (thanks to Kniht on freenode ##C++ for helping me distill this).</p>
<p><code class="prettyprint"><br />
#include &lt;limits.h&gt;<br />
#include &lt;wchar.h&gt;<br />
#include &lt;algorithm&gt;<br />
#include &lt;stdexcept&gt;</p>
<p>struct ConversionError : std::runtime_error {<br />
  ConversionError()<br />
  : std::runtime_error("ConversionError")<br />
  {}</p>
<p>  explicit<br />
  ConversionError(std::string const&#038; what)<br />
  : std::runtime_error("ConversionError: " + what)<br />
  {}</p>
<p>protected:<br />
  struct NoPrefix {};</p>
<p>  ConversionError(NoPrefix, std::string const&#038; what)<br />
  : std::runtime_error(what)<br />
  {}<br />
};</p>
<p>template&lt;class OutIter&gt;<br />
struct mboutput_t : std::iterator&lt;wchar_t,void,void,void,void&gt; {<br />
  mboutput_t(OutIter out) : _mbstate(), _out(out) {}</p>
<p>  mboutput_t&#038; operator++()    { return *this; }<br />
  mboutput_t&#038; operator++(int) { return *this; }<br />
  mboutput_t&#038; operator* ()    { return *this; }</p>
<p>  void operator=(wchar_t wc) {<br />
    char buf[MB_LEN_MAX];<br />
    int len = ::wcrtomb(buf, wc, &#038;_mbstate);<br />
    if (len == -1) {<br />
      throw ConversionError("wcrtomb");<br />
    }<br />
    _out = std::copy(buf, buf + len, _out);<br />
  }</p>
<p>  mbstate_t _mbstate;<br />
  OutIter _out;<br />
};</p>
<p>template&lt;class OutIter&gt;<br />
mboutput_t&lt;OutIter&gt; mboutput(OutIter out) {<br />
    return mboutput_t&lt;OutIter&gt;(out);<br />
}</p>
<p>template&lt;class Cont&gt;<br />
mboutput_t&lt;std::back_insert_iterator&lt;Cont&gt; &gt; mb_back_inserter(Cont&#038; c) {<br />
  return mboutput(std::back_inserter(c));<br />
}</p>
<p>template&lt;class Cont><br />
void wcs_to_mb(Cont&#038; c, wchar_t const* s) {<br />
  if (s) {<br />
    std::copy(s, s + wcslen(s), mb_back_inserter(c));<br />
  }<br />
}<br />
</code></p>
<p>This code is completely standards compliant so it will work perfectly well on any standards compliant compiler/OS. In our examples however our source is a System::String and there are two targets we&#8217;re interested in, std::string and char*. We can accomplish each of these targets easily using std::copy with our custom mb_back_inserter.</p>
<p><code class="prettyprint"><br />
template&lt;class Cont><br />
void String_to_mb(Cont&#038; c, System::String^ source) {<br />
    pin_ptr&lt;const wchar_t> wch = ::PtrToStringChars( source );<br />
    wcs_to_mb(c, wch);<br />
}</p>
<p>void ctest(const char* str) {<br />
    std::cout << str << std::endl;<br />
}</p>
<p>void stest(const std::string&#038; str) {<br />
    std::cout << str << std::endl;<br />
}</p>
<p>void convtest() {<br />
    String^ sstr = L"Hello!";</p>
<p>    std::vector<char> charStar;<br />
    String_to_mb(charStar, sstr);<br />
    // vector<char> can be used as a char* by passing &#038;charStar[0] to a function taking char*<br />
    ctest(&#038;charStar[0]);</p>
<p>    std::string s;<br />
    String_to_mb(s, sstr);<br />
    // the std::string can be used as-is or it can also produce a char* by calling string::c_str()<br />
    stest(s);<br />
    ctest(s.c_str());</p>
<p>    // the vector and string are automatically deallocated leaving this scope<br />
}<br />
</code></p>
<p>Making effective use of containers, iterators, and wcrtomb(&#8230;) we&#8217;ve created a solution that doesn&#8217;t require caller deallocation and that is reentrant.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.6bit.com/josh/2010/01/ccli-converting-from-string-to-wchar_t-and-to-char/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jeff Atwood of Borg-StackOverflow Careers Assimilation</title>
		<link>http://blogs.6bit.com/josh/2009/12/jeff-atwood-of-borg-stackoverflow-careers-assimilation/</link>
		<comments>http://blogs.6bit.com/josh/2009/12/jeff-atwood-of-borg-stackoverflow-careers-assimilation/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 15:46:25 +0000</pubDate>
		<dc:creator>Josh Perry</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[opinion]]></category>
		<category><![CDATA[stackoverflow]]></category>

		<guid isPermaLink="false">http://blogs.6bit.com/josh/?p=158</guid>
		<description><![CDATA[I&#8217;ve found StackOverflow to be a fun and vibrant community as well as an almost daily touchstone for programming and tech problems. Because of my enjoyment of the site I&#8217;ve started listening to the StackOverflow podcast with Jeff Atwood and Joel Spolsky (my opinion of which is another post altogether). I&#8217;ve found Jeff to be [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blogs.6bit.com/josh/wp-content/uploads/2009/12/Jeff_of_Borg.jpg"><img src="http://blogs.6bit.com/josh/wp-content/uploads/2009/12/Jeff_of_Borg-300x223.jpg" alt="Jeff of Borg" title="Jeff of Borg" width="300" height="223" class="alignnone size-medium wp-image-162" /></a>I&#8217;ve found StackOverflow to be a fun and vibrant community as well as an almost daily touchstone for programming and tech problems. Because of my enjoyment of the site I&#8217;ve started listening to the StackOverflow podcast with Jeff Atwood and Joel Spolsky (my opinion of which is another post altogether).</p>
<p>I&#8217;ve found Jeff to be rather level-headed and analytical during discussions, Joel on the other hand is quite often disruptive. This I&#8217;ve found to be a lot like their blogs though I don&#8217;t read them often. I also see these traits surface to varying degrees through Jeff and Joel&#8217;s joint venture.</p>
<p>I feel that Jeff has been an exceedingly gracious proprietor of the StackOverflow community, balancing monetization of the site with respect for the well from which their success flows. The well obviously being the thousands of users that spend their time providing content and moderation for the StackOverflow site.</p>
<p>Visitiing the site recently &#8212; not logged in &#8212; using a family member&#8217;s computer I found that the StackOverflow site is totally different for the drive-by Googler, the advertisements are much more prominent and inline with the content. Jeff has had the presence of mind to squelch the advertising for their most loyal and content-providing users, this is brilliant and show that the Golden Rule is in full effect at StackOverflow. And why wouldn&#8217;t they do this? It is my understanding that their traffic is somewhere around 80/20% anonymous/member mix, it&#8217;s a small tradeoff in revenue to take care of their content stream to ensure it will continue to flow.</p>
<p>Unfortunately with their latest attempt to monetize StackOverflow it seems that Joel&#8217;s traits (as PM of the venture) have surfaced more than Jeff should allow. Being the consummate businessman, with an office in New York and a home in The Hamptons, Joel wants to monetize on the traffic and content of StackOverflow with more than advertising. Who can blame him, StackOverflow receives millions of page views a month and is ranked in the top 1000 sites on the internet.</p>
<p>Where else would Joel think to go than his tried and true job listing service. This is comfortable ground for Joel, for years he has been providing employers visibility to a well defined demographic of potential employees for a somewhat standard industry rate of $350 per listing. He has been able to make a good living monetizing his blog traffic for years through advertisements and these job listings and extending this service to the even more laser focused programmer demographic of StackOverflow is a no-brainer.</p>
<p>Up to this point the site at jobs.stackoverflow.com has basically been a mirror of the joelonoftware listing, but in true StackOverflow spirit Jeff and Joel have just recently released a much more in-depth whack at the problem of finding and hiring good developers. I think their idea is genious; leveraging the StackOverflow content and infrastructure (tags, profiles, Q&#038;A) to allow developers to effectively cash-in on the time spent on StackOverflow to woo potential employers, and for employers to get invaluable information about developers that could never be communicated on a simple résumé.</p>
<p>But one word with Unicode characters wasn&#8217;t enough, so Jeff and Joel decided that developers should fill out a Curriculum Vitæ (CV) instead of a résumé. I find the distinction that they&#8217;ve made here to be refreshing and a great fit for the synergy of a developer&#8217;s passion, past experience and StackOverflow répertoire. Besides the time, filling out and publishing a public CV is a no cost proposition provided by the StackOverflow team.</p>
<p>Their plans for monetizing the careers site is two-fold. For the first revenue stream &#8212; like the jobs listing &#8212; there will be a subscription fee for employers to get access to search developer CVs to the tune of $500 per week up to $5000 per year. If you&#8217;ve ever tried to find and hire good developers using the standard method of newspaper/dice/monster, you know that this fee is worth every cent. A recruiting agency will charge you 10-25% of a placment&#8217;s salary to send people your way, and more often than not they just use the wet noodle approach and throw developers at you until one sticks. For someone that makes $80K it will cost you $8-20,000 for that single placement.</p>
<p>&#8220;So wherein does your quibble lie?&#8221; you might ask. Well, it&#8217;s in the second of the two revenue streams for the careers site, for the measly pittance of $99/year they&#8217;ve decided to throw out the baby with the bathwater. On the other side of the employer&#8217;s looking glass developers will need to pony up hard cash in order to &#8220;file&#8221; their CV to be searchable on the StackOverflow careers site. This is an affront to the content providers of their community and I can&#8217;t believe that this token filing fee is worth the bad will that it could generate.</p>
<p>It is done under the guise of filtering out those &#8220;who knew that they had no reasonable chance of getting a job&#8221;[<a href="http://careers.stackoverflow.com/faq#pricing">1</a>]. I think Jeff even believes this, but it&#8217;s really just an unfortunate scapegoat for making money at the expense of your content providers.</p>
<p>In their <a href="http://blog.stackoverflow.com/2009/12/podcast-76/">latest podcast</a> Jeff was pretty adamant that the job seekers not be sortable by their StackOverflow reputation, he wants people with little or no reputation to have an equal visibility to those that do. This bodes even worse for their plan of charging job seekers to file their CV.</p>
<p>The kind of people that are passionate and give of their time to answer other&#8217;s questions are <em>exactly</em> the kind of developers that <strong>I</strong> want to hire. And these are exactly the same people that are less likely to view this filing fee in an unfavorable way. These are the kind of developers that program at home, are constantly learning new things, work on OSS projects, and are not 9-5 just-for-the-paycheck programmers. Their loyalty when treated well is often unmatched.</p>
<p>Then there&#8217;s the other kind of developer; you know the guy I&#8217;m talking about, the smooth talker, usually the &#8220;Team Leader&#8221;. The guy who drives his Audi to work and knows how to play the corporate game better than he knows how to cut-n-paste code from Google. Their loyalty is usually suspect and their main goal is to either climb the corporate ladder (hence team lead instead of in-the-trenches programmer) or jump ship at any time for a higher salary. StackOverflow is a godsend for these types of programmers as it&#8217;s rife with snippets free for the taking.</p>
<p>If their goal was to vet potential job seekers, to provide more value to employers, then money is definitely not the way to do it. Even the &#8220;smart hiring managers&#8221;[1] will have a hard time filtering out these smooth talkers that are always on the market for the highest bidder. These are exactly the people these &#8220;smart hiring managers&#8221; don&#8217;t want, it is expensive to bring people into a company just to have them bail 60 days later.</p>
<p>At my current job we really, really need some talented developers, and there are 5 job seekers on careers in our area. The Salt Lake job market is a small world, I&#8217;m sure that I know a third of the people on the list and that&#8217;s what scares me; I know a lot of smooth talking &#8220;Team Leaders&#8221;. With the current criteria to entry I don&#8217;t think I can justify finding out who they are for $500.</p>
<p>So in effect Jeff and Joel have ignored they&#8217;re best formula for vetting job seekers and instead have opened the doors for anyone who is willing to pay $99/year. If they were really hard up to make money through this channel they could easily provide free filing for anyone who has generated over X reputation on the site in the last rolling year. Similar to their banner advertising this serves the 80% of people who are willing to pay $99 and pays respect to the 20% truly exceptional developers who they owe the success of their site.</p>
<p>Jeff, please doff the cybernetic business suit!</p>
<ol>
<li>http://careers.stackoverflow.com/faq#pricing</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blogs.6bit.com/josh/2009/12/jeff-atwood-of-borg-stackoverflow-careers-assimilation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Subclipse for SVN on Eclipse CDT</title>
		<link>http://blogs.6bit.com/josh/2009/11/subclipse-svn-on-eclipse-cdt/</link>
		<comments>http://blogs.6bit.com/josh/2009/11/subclipse-svn-on-eclipse-cdt/#comments</comments>
		<pubDate>Mon, 02 Nov 2009 00:52:58 +0000</pubDate>
		<dc:creator>Josh Perry</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[cdt]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[subclipse]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://blogs.6bit.com/josh/?p=135</guid>
		<description><![CDATA[Subversion is a great way to work on code in a collaborative fashion. There are a couple subversion plugins that work with Eclipse, one of them is called Subclipse. To install Subclipse in Eclipse goto the Help menu and choose &#8220;Software Updates&#8230;&#8221;. Once the &#8220;Software Updates and Add-ons&#8221; window displays itself we need to add [...]]]></description>
			<content:encoded><![CDATA[<p>Subversion is a great way to work on code in a collaborative fashion. There are a couple subversion plugins that work with Eclipse, one of them is called Subclipse.</p>
<p>To install Subclipse in Eclipse goto the Help menu and choose &#8220;Software Updates&#8230;&#8221;.</p>
<p>Once the &#8220;Software Updates and Add-ons&#8221; window displays itself we need to add the Subclipse update URL. Choose the &#8220;Available Software&#8221; tab, click &#8220;Add Site&#8221; and put in &#8220;http://subclipse.tigris.org/update_1.6.x&#8221; as the location and click &#8220;OK&#8221;.</p>
<p><a href="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/add_site.png"><img src="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/add_site.png" alt="Add Plugin Location" title="Add Plugin Location" width="912" height="619" class="alignnone size-full wp-image-136" /></a></p>
<p>You will now see a new item in the list corresponding to the URL that you just added. Now to add subclipse you need to choose two plugins, subclipse itself and the JavaHL. JavaHL is the API that subclipse uses to talk to your SVN server. You can find these by expanding the tree by clicking the triangle to the left of the URL you just added, and then expanding the Subclipse subnode. After selecting the plugins click install and follow the dialogs through to the end.</p>
<p><a href="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/choose_subclipse.png"><img src="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/choose_subclipse.png" alt="Plugin Selection" title="Plugin Selection" width="912" height="619" class="alignnone size-full wp-image-137" /></a></p>
<p>Now that subclipse is installed, in the top right of Eclipse click the &#8220;Open Perspective&#8221; icon choose &#8220;Other&#8221; and choose &#8220;SVN Repository Exploring&#8221;, this perspective will give you the tools to work with your SVN repo, assuming you aren&#8217;t already happily using a tool like TortoiseSVN or the command line client to do so.</p>
<p>Add your repo location to the SVN perspecitve by clicking the icon at the top right of the repositories view and typing in the URL of your repo. Any repositories added here will also show up in other dialogs when working with SVN in Eclipse such as when adding or importing projects.</p>
<p><a href="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/add_repo.png"><img src="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/add_repo.png" alt="Add Repository" title="Add Repository" width="485" height="63" class="alignnone size-full wp-image-145" /></a></p>
<h2>Adding Your Project to the SVN Repository</h2>
<p>To add a project to SVN go back to your development perspective and simply right click on the project in the &#8220;Project Explorer&#8221;, expand the &#8220;Team&#8221; subitem and choose &#8220;Share Project&#8230;&#8221;. Now choose what repository to add your project to, click Next.</p>
<p><a href="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/share_project_repo.png"><img src="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/share_project_repo.png" alt="Choose Repository" title="Choose Repository" width="525" height="435" class="alignnone size-full wp-image-150" /></a></p>
<p>Now you will be prompted to choose a folder name for your project in the repo; you can just use the name of the project or specify some folder further down in your repository hierarchy, click Next.</p>
<p><a href="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/share_project_folder.png"><img src="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/share_project_folder.png" alt="Repository Folder" title="Repository Folder" width="525" height="435" class="alignnone size-full wp-image-151" /></a></p>
<p>The wizard will now ask for an initial commit comment, click Finish and your project will be created in the repo, but you will still need to commit your changes for the code to actually show up in SVN.</p>
<p><a href="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/share_project_ready.png"><img src="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/share_project_ready.png" alt="Ready to Share" title="Ready to Share" width="525" height="435" class="alignnone size-full wp-image-149" /></a></p>
<p>Once you clicked Finish Eclipse will ask if you want to open the &#8220;Team Synchronizing&#8221; perspective. Click yes and once the perspective opens you can simply right click on the root project node and choose commit. You can also do commits from the SVN perspective, or in your development perspective the project right-click menu now has a bunch of SCM options under the Team submenu.</p>
<p><a href="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/team_scm_options.png"><img src="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/team_scm_options.png" alt="Team SCM Operations" title="Team SCM Operations" width="690" height="672" class="alignnone size-full wp-image-153" /></a></p>
<p>At this point working with SVN in Eclipse is like working with any SCM tool, make changes, commit changes, rinse, repeat.</p>
<h2>Importing a Project from SVN</h2>
<p>There may be a project in an SVN repo that you want to import, this is fairly simple. Open the workspace that you want to import the project into. Goto &#8220;File&#8221; and choose &#8220;Import&#8221;. Expand SVN in the tree and choose &#8220;Checkout Project from SVN&#8221;, click Next.</p>
<p><a href="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/import_svn.png"><img src="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/import_svn.png" alt="Import from SVN" title="Import from SVN" width="525" height="420" class="alignnone size-full wp-image-139" /></a></p>
<p>This next dialog lets you choose from which SVN location to pull the project, if you have already added a repo location in the SVN repo perspective it will show on the dialog, otherwise you can specify the location now, click Next. You will now be shown a list of folders on your repository, you can navigate them and click the folder that you&#8217;d like to import, click Next.</p>
<p><a href="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/import_svn_folder.png"><img src="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/import_svn_folder.png" alt="Choose Project Folder" title="Choose Project Folder" width="525" height="432" class="alignnone size-full wp-image-141" /></a></p>
<p>The next window asks how you would like to setup the local project, including a name and which version to pull. The defaults should usually suffice unless you want to maybe pull and older version or a branch to work on, click Next.</p>
<p><a href="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/import_svn_project.png"><img src="http://blogs.6bit.com/josh/wp-content/uploads/2009/11/import_svn_project.png" alt="Local Project Properties" title="Local Project Properties" width="525" height="502" class="alignnone size-full wp-image-143" /></a></p>
<p>The next dialog simply lets you import to a different workspace than the one you currently have mounted. You should already be in the workspace you want to import to so just click finish. The import process will take a moment after which you should see a new project in your workspace.</p>
<p>Congratulations, you&#8217;ve successfully imported the project and since it is bound to SVN you can now work on the code with your coworkers!</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.6bit.com/josh/2009/11/subclipse-svn-on-eclipse-cdt/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
