<?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>HMK&#039;s Spurious Thoughts &#187; Programming</title>
	<atom:link href="http://www.spuriousthoughts.com/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.spuriousthoughts.com</link>
	<description>Biased / Nicht immer ausgewogen</description>
	<lastBuildDate>Mon, 06 Feb 2012 19:30:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Thoughtworks Event, Frankfurt</title>
		<link>http://www.spuriousthoughts.com/2011/10/18/thoughtworks-event-frankfurt/</link>
		<comments>http://www.spuriousthoughts.com/2011/10/18/thoughtworks-event-frankfurt/#comments</comments>
		<pubDate>Tue, 18 Oct 2011 18:43:42 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.spuriousthoughts.com/?p=1369</guid>
		<description><![CDATA[Last night, Thoughtworks was hosting an public event @ Japan Center, Frankfurt &#8211; right next to the EZB and Deutsche Bank headquarters (I sure hope that those buildings were filled with busy &#038; smart people working on setting things straight with the Euro). 18:45 &#8211; Welcome by Nick Ashley, MD of ThoughtWorks Deutschland 19:00 &#8211; [...]]]></description>
			<content:encoded><![CDATA[<p>Last night, <a href="http://www.thoughtworks.com/">Thoughtworks</a> was hosting an public event @ Japan Center, Frankfurt &#8211; right next to the EZB and Deutsche Bank headquarters (I sure hope that those buildings were filled with busy &#038; smart people working on setting things straight with the Euro).</p>
<ul>
<li>18:45 &#8211; Welcome by Nick Ashley, MD of ThoughtWorks Deutschland</li>
<li>19:00 &#8211; Wolf Schlegel: &#8220;Dos and don&#8217;ts of Continuous Integration and Delivery&#8221;</li>
<li>19.20 &#8211; Erik Dörnenburg: &#8220;Lean for enterprise architecture</li>
<li>19:45 &#8211; Martin Fowler: &#8220;Software Design in the 21st Century&#8221;</li>
<li>20:30 &#8211; Networking &#8211; drinks and food</li>
</ul>
<p>Unfortunately, I missed about half of Wolf Schlegel&#8217;s talk on Continous Delivery, but judging on the second half, I would have preferred more in-depth discussion of technologies and best practices. The talk seemed like a space-station&#8217;s eye view of the topic.</p>
<p><a href="http://twitter.com/erikdoe">Erik Dörnenburg</a> was next talking about Lean Enterprise Architecture. I very much liked his analogy of comparing the role of a Software Architect to that of a Gardener instead of a traditional Architect. Spot on. Quite a few interesting thoughts on how to causing change in an organisation / team, too.</p>
<p><a href="http://twitter.com/martinfowler">Martin Fowler</a> gave two short talks, on on &#8220;<a href="http://martinfowler.com/dsl.html">Domain Specific Languages</a>&#8221; and one on &#8220;<a href="http://martinfowler.com/articles/nonDeterminism.html">Nondeterministic Tests</a>&#8220;.</p>
<p>I was quite keen on the Domain Specific Language part, as we&#8217;re currently moving away from a &#8220;home-grown&#8221; Domain Specific Language for NC-code templating &#038; output to a Python-based solution as we found that our own language lacked the expressiveness we are looking for. My key take-away was that there are two ways to create a DSL, external &#038; internal and that we&#8217;re migrating from an external DSL to an internal DSL. Looks like the DSL book is supposed to be on my reading list real soon now.</p>
<p>Martin&#8217;s thoughts on &#8220;Nondeterministic Tests&#8221; were especially interesting as I was attending a talk on <a href="http://www.spuriousthoughts.com/2011/10/10/objektforum-karlsruhe-testen-in-der-konkurrenz-situation-trotz-nebenlaufigkeit-erfolgreich-unit-tests-schreiben/">&#8220;Unit Testing &#038; Concurrency&#8221;</a> right last week in Karlsruhe. Very interesting to see the different takes on the topic &#8211; Abstracting away the concurrency altogether for unit testing purposes whereas Martin was leaning towards integration &#038; acceptance testing and giving very sound advice on how to deal with concurrency issues within the tests (polling, callbacks, test doubles).</p>
<p>As you might have imagined, I mostly skipped the Networking part due to my sociophobia.</p>
<p>Overall, a very worthwhile evening and I very much look forward to future Thoughtworks events.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spuriousthoughts.com/2011/10/18/thoughtworks-event-frankfurt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Objektforum Karlsruhe &#8211; &#8220;Trotz Nebenläufigkeit erfolgreich Unit Tests schreiben&#8221;</title>
		<link>http://www.spuriousthoughts.com/2011/10/10/objektforum-karlsruhe-testen-in-der-konkurrenz-situation-trotz-nebenlaufigkeit-erfolgreich-unit-tests-schreiben/</link>
		<comments>http://www.spuriousthoughts.com/2011/10/10/objektforum-karlsruhe-testen-in-der-konkurrenz-situation-trotz-nebenlaufigkeit-erfolgreich-unit-tests-schreiben/#comments</comments>
		<pubDate>Mon, 10 Oct 2011 20:54:57 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://www.spuriousthoughts.com/?p=1356</guid>
		<description><![CDATA[Ein wirklich interessanter Vortrag mit einer nur auf den ersten Blick überraschenden Erkenntnis: Wie erstellt man Unit Tests für nebenläufige Funktionen? Man testet nicht die Nebenläufigkeit. Man abstrahiert von der Nebenläufigkeit, das heißt man erstellt das System so, daß nebenläufige Funktionen über abstrakte Interfaces beschrieben werden. Die nachfolgende Diskussion zeigte wieder einmal, daß der Informatiker [...]]]></description>
			<content:encoded><![CDATA[<p>Ein wirklich interessanter <a href="http://www.andrena.de/veranstaltungen/testen-in-der-konkurrenz-situation-trotz-nebenlaeufigkeit-erfolgreich-unit-tests-sch">Vortrag</a> mit einer nur auf den ersten Blick überraschenden Erkenntnis:</p>
<p>Wie erstellt man Unit Tests für nebenläufige Funktionen? Man testet nicht die Nebenläufigkeit. Man abstrahiert von der Nebenläufigkeit, das heißt man erstellt das System so, daß nebenläufige Funktionen über abstrakte Interfaces beschrieben werden.</p>
<p>Die nachfolgende Diskussion zeigte wieder einmal, daß der Informatiker an sich nicht einer der Flexibelsten oder Lernfähigsten ist (*). Anmerkungen wie: &#8220;Damit testen Sie aber nicht die Aspekte X und Y&#8221;, &#8220;Das ist bei uns so nicht einsetzbar, weil X&#8221; oder &#8220;Bei uns liegt aber Z vor, daher können wir nicht&#8230;&#8221; zeigten, das einige Kollegen wieder exakt die Argumente aufwärmten, die sie in den letzten 10 Jahren  bereits (erfolglos) gegen die Konzepte beim Unit-Testing von Benutzerschnittstellen, Datenbankzugriffen, Netzwerkdiensten und anderem vorgebracht hatten:</p>
<h4>Wie erstellt man Unit Tests für Benutzerschnittstellen?</h4>
<p>Man testet nicht die Benutzerschnittstelle. Man abstrahiert von der eigentlichen Benutzerschnittstelle, indem man beispielsweise MVP (Model View Presenter) nutzt.</p>
<h4>Wie erstellt man Unit Tests für die Datenbank?</h4>
<p>Man testet nicht die Datenbank. Man abstrahiert von den eigentlichen Datenbankzugriffen, indem man diese in eine eigene, möglichst einfache Mapping-Schicht auslagert.</p>
<h4>Wie erstellt man Unit Tests für Netzwerkdienste?</h4>
<p>Man testet nicht die Netzwerkdienste. Man abstrahiert von den Netzwerkdiensten, indem man diese durch abstrakte Interfaces beschreibt.</p>
<p>Um zwei weitere Beispiele aus der täglichen Praxis der extragroup GmbH zu bringen:</p>
<h4>Wie erstellt man Unit Tests für das Erstellen von Objekten in einem CAD-System?</h4>
<p>Man testet nicht das Erstellen der Objekte. Man abstrahiert vom Erstellen der CAD-Objekte, indem das eigentliche Erstellen der CAD-Objekte in eine möglichst einfache Klasse auslagert &#8211; die man im schlimmsten Falle über ein abstraktes Interface beschreibt.</p>
<h4>Wie erstellt man Unit Tests für das Erstellen von Werkzeugen in einem CAD-System?</h4>
</p>
<p>Man testet nicht das Verhalten der Werkzeuge. Man abstrahiert vom den CAD-Werkzeugen, indem die eigentliche Schnittstelle zum API des CAD-System durch ein abstraktes Interface beschreibt.</p>
<p>Der geneigte Leser wird sicher inzwischen ein Muster erkannt haben.</p>
<p>Die entscheidende Erkenntnis (für uns wie für die oben genannten Kollegen) ist, daß all dies nur mit testgetriebener Entwicklung sauber möglich ist. Unit Tests nachträglich zu einem System hinzuzufügen, welches nicht auf solche Tests ausgelegt ist, erweist sich in der Praxis als enorm aufwendig.</p>
<p>(*) Ich zähle mich selbstverständlich auch zu genau dieser Gruppe, die neuen Ideen mit einem gezielten &#8220;Das funktioniert nicht, weil&#8230;.&#8221; begegnet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spuriousthoughts.com/2011/10/10/objektforum-karlsruhe-testen-in-der-konkurrenz-situation-trotz-nebenlaufigkeit-erfolgreich-unit-tests-schreiben/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Developing a Vectorworks 2011 tool plug-in, TDD-style &#8211; Episode 4</title>
		<link>http://www.spuriousthoughts.com/2011/10/03/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-4/</link>
		<comments>http://www.spuriousthoughts.com/2011/10/03/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-4/#comments</comments>
		<pubDate>Mon, 03 Oct 2011 18:53:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Vectorworks]]></category>

		<guid isPermaLink="false">http://www.spuriousthoughts.com/?p=1333</guid>
		<description><![CDATA[Now that we&#8217;re able to create real Vectorworks geometry with our tool, what&#8217;s next? The &#8220;spec&#8221; laid out in Episode 0 calls for creating a red or green line depending on where the user sets the clicks. Tackling the click&#8217;s location test first sounds like an interesting challenge. What&#8217;s the simplest way to start? If [...]]]></description>
			<content:encoded><![CDATA[<p>Now that we&#8217;re able to create real Vectorworks geometry with our tool, what&#8217;s next? The &#8220;spec&#8221; laid out in <a href="http://www.spuriousthoughts.com/2011/06/02/developing-a-v…tyle-episode-0/">Episode 0</a> calls for creating a red or green line depending on where the user sets the clicks. Tackling the click&#8217;s location test first sounds like an interesting challenge.</p>
<p>What&#8217;s the simplest way to start? If the user doesn&#8217;t click on a polygon object, our tool should ignore the clicks. How does <tt>RedGreenLineTool</tt> know if the clicks happen on a polygon object? For know, we let it know by calling <tt>MouseOverPolygonObject()</tt> before adding tool points. Sounds reasonable.</p>
<pre class="brush: cpp; title: ; notranslate">
TEST_N(ToolPointsShouldBeReflectedAsStartEndPointOfLineObject)
{
	MockRedGreenLineTool vwTool;
	vwTool.MouseOverPolygonObject();

	vwTool.AddPoint(WorldPt3(0, 0, 0));
	vwTool.AddPoint(WorldPt3(50, 0, 0));

	CHECK_EQUAL(2, vwTool.GetNumToolPoints());
}
</pre>
<p>If we don&#8217;t call <tt>MouseOverPolygonObject()</tt> before adding points, they shouldn&#8217;t be added to the list of points tracked.</p>
<pre class="brush: cpp; title: ; notranslate">
TEST_N(ToolPointNotOnPolygonShouldBeIgnored)
{
	MockRedGreenLineTool vwTool;

	vwTool.AddPoint(WorldPt3(0, 0, 0));
	vwTool.AddPoint(WorldPt3(50, 0, 0));

	CHECK_EQUAL(0, vwTool.GetNumToolPoints());
}
</pre>
<p>Implementation, of course, is rather trivial (for now <img src='http://www.spuriousthoughts.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> . We just add a <tt>bool fMockMouseOverPolygonObject</tt> to <tt>MockRedGreenLineTool</tt>, set it <tt>MouseOverPolygonObject()</tt>, test it in <tt>AddPoint()</tt> and we&#8217;re done. </p>
<p>Well, not really. We do have an implementation for <tt>MockRedGreenLineTool</tt> only, we need to move the implementation up the inheritance tree to <tt>RedGreenLineTool</tt> to turn it into something useful.</p>
<pre class="brush: cpp; title: ; notranslate">
class RedGreenLineTool {

	virtual bool IsMouseOverPolygonObject() = 0;

	void AddPoint(const WorldPt3&amp; p) {
		if (IsMouseOverPolygonObject())
			fToolPoints.PushData(p);
	}
};
</pre>
<p>Implementation of <tt>IsMouseOverPolygonObject()</tt> is rather trivial for <tt>MockRedGreenLineTool</tt>, we just return <tt>fMockMouseOverPolygonObject</tt>. Of course, <tt>VectorworksRedGreenLineTool</tt> needs a more sophisticated implementation, but (as intended) a rather simple one:</p>
<pre class="brush: cpp; title: ; notranslate">
class VectorworksRedGreenLineTool {

	virtual bool IsMouseOverPolygonObject() {
		MCObjectHandle overObject = NULL;
		short overPart;
		long code;
		gSDK-&gt;TrackTool(overObject, overPart, code);

		return (overObject &amp;&amp; ! VWPolygon2DObj::IsPolygon2DObject(overObject));
	}
};
</pre>
<p>Now this rather straightforward implementation doesn&#8217;t quite work yet, as this code doesn&#8217;t reflect the state Vectorworks is in. every mouse click is registered by Vectorworks first, then an event is sent to the tool to process it. If we choose to ignore the mouse click, we need to notify Vectorworks of this fact. Thus, we need to make some minor changes to the code to accommodate for this behavior. </p>
<pre class="brush: cpp; title: ; notranslate">
class RedGreenLineTool {

	virtual void PopLastToolPoint() = 0;

	void AddPoint(const WorldPt3&amp; p) {
		if (IsMouseOverPolygonObject())
			fToolPoints.PushData(p);
		else
			PopLastToolPoint();
	}
};
</pre>
<p>While <tt>MockRedGreenLineTool</tt> gets away with an empty implementation for <tt>PopLastToolPoint()</tt>, <tt>VectorworksRedGreenLineTool</tt> needs to notify Vectorworks that the last tool point registered should be removed:</p>
<pre class="brush: cpp; title: ; notranslate">
class VectorworksRedGreenLineTool {

	virtual void PopLastToolPoint() {
		gSDK-&gt;PopLastToolPt();
	}
};
</pre>
<p>Where are we at? We do have a basic implementation of mouse tracking in place. <tt>RedGreenLineTool</tt> is able to tell if the mouse is over a polygon object while the mouse is clicked. In the next episode, we will tackle tracking mouse clicks on a single or two different polygons in order to create red or green lines.</p>
<p><a href="http://www.spuriousthoughts.com/2011/07/22/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-3/">Previous Episode</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.spuriousthoughts.com/2011/10/03/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Developing a Vectorworks 2011 tool plug-in, TDD-style &#8211; Episode 3</title>
		<link>http://www.spuriousthoughts.com/2011/07/22/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-3/</link>
		<comments>http://www.spuriousthoughts.com/2011/07/22/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-3/#comments</comments>
		<pubDate>Fri, 22 Jul 2011 19:16:19 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Vectorworks]]></category>

		<guid isPermaLink="false">http://www.spuriousthoughts.com/?p=1256</guid>
		<description><![CDATA[With quite a sound class structure in place (and after returning from a refreshing summer vacation in Turkey), let&#8217;s see if we can put our new class strcuture to good use while trying to create the actual Vectorworks geometry (a line), test first &#8211; of course. Reading through the first series on TDD with Vectorworks, [...]]]></description>
			<content:encoded><![CDATA[<p>With quite a sound class structure in place (and after returning from a refreshing summer vacation in Turkey), let&#8217;s see if we can put our new class strcuture to good use while trying to create the actual Vectorworks geometry (a line), test first &#8211; of course. Reading through the first series on TDD with Vectorworks, we used a model object for representing the geometric properties of the object and a rather thin layer to create the actual Vectorworks geometry from the model. How about trying this approach with a Vectorworks tool plug-in, too?</p>
<pre class="brush: cpp; title: ; notranslate">
TEST_N(ToolPointsShouldBeReflectedAsStartEndPointOfLineObject)
{
	MockRedGreenLineTool vwTool;

	vwTool.AddPoint(WorldPt3(0, 0, 0));
	vwTool.AddPoint(WorldPt3(50, 0, 0));

	MockRedGreenLineObject* vwObject = vwTool.Create();

	CHECK_EQUAL(WorldPt3(0, 0, 0), vwObject-&gt;GetStartPoint());
	CHECK_EQUAL(WorldPt3(50, 0, 0), vwObject-&gt;GetEndPoint());

	delete vwObject;
}
</pre>
<p>We expect that the tool object will be able to create the line object for us and that the tool will take care of making sure that the start &#038; end point of the line object will reflect the tool points.</p>
<p>In order to get the test to compile, we need to implement <tt>Create()</tt> for <tt>MockRedGreenLineTool</tt>.</p>
<pre class="brush: cpp; title: ; notranslate">
class MockRedGreenLineTool : public RedGreenLineTool {

public:

	MockRedGreenLineObject* Create() const {
		MockRedGreenLineObject* lineObject = new MockRedGreenLineObject();

		lineObject-&gt;SetStartPoint(fToolPoints[0].fPoint);
		lineObject-&gt;SetEndPoint(fToolPoints[1].fPoint);

		return lineObject;
	}		

};
</pre>
<p>Now we need to come up with a simple implementation for <tt>MockRedGreenLineObject</tt>. Not a lot to see here &#8211; just a mock implementation.</p>
<pre class="brush: cpp; title: ; notranslate">
class MockRedGreenLineObject {

public:

	void SetStartPoint(const WorldPt3&amp;amp;amp; p) {
		fStartPoint = p;
	}

	void SetEndPoint(const WorldPt3&amp;amp;amp; p) {
		fEndPoint = p;
	}

	virtual WorldPt3 GetStartPoint() const {
		return fStartPoint;
	}

	virtual WorldPt3 GetEndPoint() const {
		return fEndPoint;
	}

private:

	WorldPt3 fStartPoint;
	WorldPt3 fEndPoint;
};
</pre>
<p>Now the code compiles, links and the test passes. As in episode 1, the code is stuck in the &#8220;Mock&#8221; classes, but we need to drive it from Vectorworks. Let&#8217;s refactor us out of this mess.</p>
<p>First, we push the implementation of <tt>Create()</tt> up to the base class, <tt>RedGreenLineTool</tt>. However, <tt>RedGreenLineTool::Create()</tt> shouldn&#8217;t return an instance of <tt>MockRedGreenLineObject</tt>, but an instance of a more generic RedGreenLineObject class in order to accommodate creation of a Vectorworks-specific subclass. Creation of the particular instance is left to the subclasses of <tt>RedGreenLineTool</tt>.</p>
<p>We move the code from <tt>MockRedGreenLineObject</tt> to a new superclass <tt>RedGreenLineObject</tt>.</p>
<pre class="brush: cpp; title: ; notranslate">
class RedGreenLineObject {

public:

	void SetStartPoint(const WorldPt3&amp;amp;amp; p) {
		fStartPoint = p;
	}

	void SetEndPoint(const WorldPt3&amp;amp;amp; p) {
		fEndPoint = p;
	}

	virtual WorldPt3 GetStartPoint() const {
		return fStartPoint;
	}

	virtual WorldPt3 GetEndPoint() const {
		return fEndPoint;
	}

private:

	WorldPt3 fStartPoint;
	WorldPt3 fEndPoint;
};
</pre>
<p>Code still compiles, links and passes the tests. Now for the surgery concerning <tt>RedGreenLineTool::Create()</tt>:</p>
<pre class="brush: cpp; title: ; notranslate">
class VectorworksRedGreenLineTool : public RedGreenLineTool {

	RedGreenLineObject* CreateRedGreenLineObject() const {
		return VectorworksRedGreenLineObject();
	}
};

class MockRedGreenLineTool : public RedGreenLineTool {

	RedGreenLineObject* CreateRedGreenLineObject() const {
		return MockRedGreenLineObject();
	}
};

class RedGreenLineTool {

public:

	RedGreenLineObject* CreateRedGreenLineObject() const = 0;

	RedGreenLineObject* Create() const {
		RedGreenLineObject* lineObject = CreateRedGreenLineObject();

		lineObject-&gt;SetStartPoint(fToolPoints[0].fPoint);
		lineObject-&gt;SetEndPoint(fToolPoints[1].fPoint);

		return lineObject;
	}		

};
</pre>
<p>Again, code compiles, links and our tests pass. What&#8217;s left? We need to hook up the classes to <tt>CTool_EventSink</tt> and create the Vectorworks geometry.</p>
<pre class="brush: cpp; title: ; notranslate">
long CTool_EventSink::LegacyMain(long action, long message1, long message2)
{
	long result = 0;

	switch (action) {

		case kToolHandleComplete:
			fRedGreenLineTool-&gt;Create();
			break;
	}
};
</pre>
<p>Compiles, links. No surprises here. We start Vectorworks, select our tool, click twice to create a line &#8211; but nothing happens&#8230;.yet. Ah, we forgot to create the geometry. How to do that? Here&#8217;s the simplest way of doing it which comes to my mind:</p>
<pre class="brush: cpp; title: ; notranslate">
class RedGreenLineTool {

public:

	RedGreenLineObject* Create() const {
		RedGreenLineObject* lineObject = CreateRedGreenLineObject();

		lineObject-&gt;SetStartPoint(fToolPoints[0].fPoint);
		lineObject-&gt;SetEndPoint(fToolPoints[1].fPoint);

		lineObject-&gt;CreateGeometry();

		return lineObject;
	}		

};
</pre>
<p>Of course, the implementation of <tt>CreateGeometry()</tt> in <tt>MockRedGreenLineObject</tt> will be empty, whereas <tt>VectorworksRedGreenLineObject::CreateGeometry()</tt> is somewhat beefier:</p>
<pre class="brush: cpp; title: ; notranslate">
class VectorworksRedGreenLineObject {

	virtual void CreateGeometry() {
		VWLine2DObj line(fStartPoint.x, fStartPoint.y, fEndPoint.x, fEndPoint.y);
		line.AddObjectToContainer(gSDK-&gt;GetDefaultContainer());
	}

};
</pre>
<p>We can easily deal with the non-testability of <tt>CreateGeometry()</tt>, as all the logic of the line object&#8217;s &#8220;model&#8221; itself is under test. And if something goes horribly wrong in <tt>CreateGeometry()</tt>, it should be easy to figure out.</p>
<p><tt>RedGreenLineObject</tt> doesn&#8217;t feature an awful lot of sophisticated logic so far, but we are not done yet. The &#8220;spec&#8221; calls for creating a red or green line depending on where the user sets the clicks. Sounds like this attribute will find a good home in the <tt>RedGreenLineObject</tt> class. Speaking of it, determining the location of the clicks test first sounds like an interesting challenge. Let&#8217;s try to tackle that one in the next episode.</p>
<p><a href="http://www.spuriousthoughts.com/2011/06/17/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-2/">Previous Episode</a> | <a href="http://www.spuriousthoughts.com/2011/10/03/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-4/">Next Episode</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.spuriousthoughts.com/2011/07/22/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Developing a Vectorworks 2011 tool plug-in, TDD-style &#8211; Episode 2</title>
		<link>http://www.spuriousthoughts.com/2011/06/17/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-2/</link>
		<comments>http://www.spuriousthoughts.com/2011/06/17/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-2/#comments</comments>
		<pubDate>Fri, 17 Jun 2011 21:18:50 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Vectorworks]]></category>

		<guid isPermaLink="false">http://www.spuriousthoughts.com/?p=1227</guid>
		<description><![CDATA[With a basic mock implementation of the tool point collecting part of a Vectorworks tool under our belt, let&#8217;s try to connect this class to a &#8220;real&#8221; Vectorworks tool event sink. Using the MockRedGreenLineTool from within a CTool_EventSink doesn&#8217;t sound quite right. After all it&#8217;s supposed to be a mock implementation. We need to use [...]]]></description>
			<content:encoded><![CDATA[<p>With a <a href="http://www.spuriousthoughts.com/2011/06/08/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-1/">basic mock implementation</a> of the tool point collecting part of a Vectorworks tool under our belt, let&#8217;s try to connect this class to a &#8220;real&#8221; Vectorworks tool event sink.</p>
<p>Using the <tt>MockRedGreenLineTool</tt> from within a <tt>CTool_EventSink</tt> doesn&#8217;t sound quite right. After all it&#8217;s supposed to be a mock implementation. We need to use a real tool implementation in the <tt>CTool_EventSink</tt>. Let&#8217;s do some restructuring to accomplish that. First, create a new class <tt>RedGreenLineTool</tt> with the code from <tt>MockRedGreenLineTool</tt>.</p>
<pre class="brush: cpp; title: ; notranslate">
class RedGreenLineTool {

public:

	virtual ~RedGreenLineTool() {
	}

 	void AddPoint(const WorldPt3&amp;amp;amp;amp; p) {
		fToolPoints.PushData(p);
	}	

	virtual void PopPoint() {
		fToolPoints.PopData();
	}

	short GetNumToolPoints() const {
		return fToolPoints.NumItems();
	}

	TSmallArray&lt;WorldPt3&gt; fToolPoints;

};
</pre>
<p>Now, make <tt>MockRedGreenLineTool</tt> a subclass of <tt>RedGreenLineTool</tt>:</p>
<pre class="brush: cpp; title: ; notranslate">
class MockRedGreenLineTool : public RedGreenLineTool {
}
</pre>
<p>and create <tt>VectorworksRedGreenLineTool</tt>, which is also a subclass of <tt>RedGreenLineTool</tt>.</p>
<pre class="brush: cpp; title: ; notranslate">
class VectorworksRedGreenLineTool : public RedGreenLineTool {
}
</pre>
<p>This sure looks better to our TDD newbie eye. We have a common implementation for both the <tt>MockRedGreenLineTool</tt> used for testing and a <tt>VectorworksRedGreenLineTool</tt> used to connect the code to Vectorworks. Running the tests shows we didn&#8217;t break anything. Now we are able to use <tt>VectorworksRedGreenLineTool</tt> in a <tt>VWToolDefaultLine_EventSink</tt> implementation:</p>
<pre class="brush: cpp; title: ; notranslate">
long CTool_EventSink::LegacyMain(long action, long message1, long message2)
{
	long result = 0;

	switch (action) {

		case kToolDoSetup:
			result = VWToolDefaultLine_EventSink::LegacyMain(action, message1, message2);

			fRedGreenLineTool = new VectorworksRedGreenLineTool();
			break;

		case kToolDoSetDown:
			result = VWToolDefaultLine_EventSink::LegacyMain(action, message1, message2);

			if (fRedGreenLineTool)
				delete fRedGreenLineTool;
			fRedGreenLineTool = NULL;
			break;

		case kToolPointAdded: {

			WorldPt3 toolPoint;
			if (gSDK-&gt;GetToolPt3D(gSDK-&gt;GetNumToolPts() - 1, toolPoint))
				fRedGreenLineTool-&gt;AddPoint(toolPoint);
			break;
		}

		case kToolPointRemoved:
			fRedGreenLineTool-&gt;PopPoint();
			break;

		default:
			result = VWToolDefaultLine_EventSink::LegacyMain(action, message1, message2);
			break;

	}

	return result;
}
</pre>
<p>Using the debugger, we are able to verify that everything is working out as expected.</p>
<p>Not a lot of functional but structural code changes in this episode, but we ended up with a class hierarchy which hints at things to come. We expect to push code common between the mock and Vectorworks implementation of the tool up the class hierarchy and code specific to the mock or Vectorworks implementation of the tool in the subclasses.</p>
<p>Let&#8217;s see how this class hierarchy holds up in the next episode when we tackle creating a line &#8211; test first, of course.  </p>
<p><a href="http://www.spuriousthoughts.com/2011/06/08/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-1/">Previous Episode</a> | <a href="http://www.spuriousthoughts.com/2011/07/22/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-3/">Next Episode</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.spuriousthoughts.com/2011/06/17/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Developing a Vectorworks 2011 tool plug-in, TDD-style &#8211; Episode 1</title>
		<link>http://www.spuriousthoughts.com/2011/06/08/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-1/</link>
		<comments>http://www.spuriousthoughts.com/2011/06/08/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-1/#comments</comments>
		<pubDate>Wed, 08 Jun 2011 21:43:28 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Vectorworks]]></category>

		<guid isPermaLink="false">http://www.spuriousthoughts.com/?p=1217</guid>
		<description><![CDATA[In Episode 0, we set the goal for this series: To develop a Vectorworks plug-in tool which creates a green line if both clicks are on the same Vectorworks polygon and creates a red line if the clicks are on two different polygons. We will be using a slightly modified version of CppUnitLite2, for more [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://www.spuriousthoughts.com/2011/06/02/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-0/">Episode 0</a>, we set the goal for this series: To develop a Vectorworks plug-in tool which creates a green line if both clicks are on the same Vectorworks polygon and creates a red line if the clicks are on two different polygons.</p>
<p>We will be using a slightly modified version of <a href="http://gamesfromwithin.com/cppunitlite2-11">CppUnitLite2</a>, for more details on how the testing targets are integrated in the Xcode projects please refer to <a href="http://www.spuriousthoughts.com/2011/04/16/developing-a-vectorworks-2011-plug-in-tdd-style-episode-0/">Episode 0</a> of the plug-in object series.</p>
<p>As in our plug-in object series, the first challenge is &#8220;How do we start&#8221;? </p>
<p>As our tool will require two clicks, we may get away with subclassing <tt>VWToolDefaultLine_EventSink</tt> to implement the interactive behavior of the tool. Of course, we won&#8217;t be able to use a <tt>VWToolDefaultLine_EventSink</tt> in our testing target, as the testing environment runs as a separate application. So we need to come up with our own &#8220;Vectorworks tool&#8221; class. Let&#8217;s do that and see were it leads us. </p>
<p>What to test first? Our tool will be collecting up to two clicks (&#8220;tool points&#8221; in Vectorworks SDK lingo). Upon initialization, there are no tool point in the collection:</p>
<pre class="brush: cpp; title: ; notranslate">
#include &amp;quot;CppUnitLite2.h&amp;quot;

TEST_N(ToolObjectShouldHaveNoPointsUponInitialization)
{
	MockRedGreenLineTool vwTool;

	CHECK_EQUAL(0, vwTool.GetNumToolPoints());
}
</pre>
<p>Not an awful lot of sophistication here, but we sure know how to make this test pass (doing the simplest thing that could possibly work):</p>
<pre class="brush: cpp; title: ; notranslate">
class MockRedGreenLineTool {

public:

	short GetNumToolPoints() const {
		return 0;
	}

};
</pre>
<p>Compiles, links and even passes the test. Excellent. We&#8217;re off to a great start. Now for some more, ahm, sophistication. The tool should store the tool points (to create the line later on &#8211; we have no clue yet how to do that in a test-first fashion, but let&#8217;s just follow our chosen path of rather trivial steps for a while):</p>
<pre class="brush: cpp; title: ; notranslate">
#include &amp;quot;CppUnitLite2.h&amp;quot;

TEST_N(ToolObjectShouldRememberToolPoints)
{
	MockRedGreenLineTool vwTool;

	vwTool.AddPoint(WorldPt3(0, 0, 0));
	vwTool.AddPoint(WorldPt3(50, 0, 0));

	CHECK_EQUAL(2, vwTool.GetNumToolPoints());
}
</pre>
<p>Making this test pass is no challenge either (even for a small mind like me):</p>
<pre class="brush: cpp; title: ; notranslate">
class MockRedGreenLineTool {

public:

 	void AddPoint(const WorldPt3&amp;amp; p) {
		fToolPoints.PushData(p);
	}	

	short GetNumToolPoints() const {
		return fToolPoints.NumItems();
	}

	TSmallArray&amp;lt;WorldPt3&amp;gt; fToolPoints;

};
</pre>
<p>Now that we&#8217;re on a roll, let&#8217;s add one more &#8220;event&#8221; to our class, removing tool points. Users will be able to back out of a Vectorworks tool step by step by removing the last tool point added.</p>
<pre class="brush: cpp; title: ; notranslate">
TEST_N(ToolObjectPoppingToolPoints)
{
	MockRedGreenLineTool vwTool;

	vwTool.AddPoint(WorldPt3(0, 0, 0));
	vwTool.AddPoint(WorldPt3(50, 0, 0));

	CHECK_EQUAL(2, vwTool.GetNumToolPoints());

	vwTool.PopPoint();

	CHECK_EQUAL(1, vwTool.GetNumToolPoints());

	vwTool.PopPoint();

	CHECK_EQUAL(0, vwTool.GetNumToolPoints());
}
</pre>
<p>Luckily, <tt>TSmallArray</tt> features a method to remove the last entry added, so making the test pass is straightforward:</p>
<pre class="brush: cpp; title: ; notranslate">
class MockRedGreenLineTool {

public:

	virtual void PopPoint() {
		fToolPoints.PopData();
	}

	// ...

};
</pre>
<p>Where are we at? We now have a tool class collecting tool points (with the added bonus of being able to remove those tool points later). There are three questions which come to our mind:</p>
<ul>
<li>We need to somehow connect <tt>MockRedGreenLineTool</tt> to the <tt>VWToolDefaultLine_EventSink</tt>
<li><tt>MockRedGreenLineTool</tt> needs to be able to know about the clicks being on a polygon
<li><tt>MockRedGreenLineTool</tt> needs to create a &#8220;red or green line object&#8221;
</ul>
<p>Let&#8217;s try to tackle connecting <tt>MockRedGreenLineTool</tt> to <tt>VWToolDefaultLine_EventSink</tt> in the next episode.</p>
<p><a href="http://www.spuriousthoughts.com/2011/06/02/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-0/">Previous Episode</a> | <a href="http://www.spuriousthoughts.com/2011/06/17/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-2/">Next Episode</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.spuriousthoughts.com/2011/06/08/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Developing a Vectorworks 2011 tool plug-in, TDD-style &#8211; Episode 0</title>
		<link>http://www.spuriousthoughts.com/2011/06/02/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-0/</link>
		<comments>http://www.spuriousthoughts.com/2011/06/02/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-0/#comments</comments>
		<pubDate>Thu, 02 Jun 2011 19:18:20 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Vectorworks]]></category>

		<guid isPermaLink="false">http://www.spuriousthoughts.com/?p=1208</guid>
		<description><![CDATA[In the epilogue of &#8220;Developing a Vectorworks 2011 plug-in object, TDD style&#8221;, I hinted at some not yet coherent thoughts on how to develop a Vectorworks plug-in tool test first. Creating some Vectorworks geometry test first was reasonably straightforward: Do all calculations in a separate model class and use the pre-calculated model to generate the [...]]]></description>
			<content:encoded><![CDATA[<p>In the <a href="http://www.spuriousthoughts.com/2011/05/02/developing-a-vectorworks-2011-plug-in-tdd-style-epilogue/">epilogue</a> of &#8220;Developing a Vectorworks 2011 plug-in object, TDD style&#8221;, I hinted at some not yet coherent thoughts on how to develop a Vectorworks plug-in tool test first. Creating some Vectorworks geometry test first was reasonably straightforward: Do all calculations in a separate model class and use the pre-calculated model to generate the Vectorworks geometry.</p>
<p>A Vectorworks tool is a more sophisticated problem for a small mind like yours truly: It interacts with the drawing in a series of clicks, objects may be tracked while tool is running etc. How do we capture this potentially rich interaction test-first? Before we tackle these questions, let&#8217;s describe the tool, code named &#8220;Red/Green Line Tool&#8221;:</p>
<p>As the name implies, it will collect two clicks in the document and draw a green line if the start- and endpoint of the line (the first &#038; second &#8220;click&#8221;) are are on a 2D polygon. If the clicks aren&#8217;t on a 2D polygon, they should be ignored. To top things off, a red line should be drawn if the startpoint is located on a different 2D-polygon than the endpoint:</p>
<p><img style="display:block; margin-left:auto; margin-right:auto;" src="http://www.spuriousthoughts.com/wp-content/uploads/2011/06/redgreen.png" alt="Redgreen" border="0" width="600" height="327" /></p>
<p>My goal is neither to cover all bases with the tests (I intend to leave those as an exercise for the reader <img src='http://www.spuriousthoughts.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  nor to develop a shippable, fully Vectorworks-conform tool (my day job takes care of this desire), but to focus on these three questions:</p>
<ul>
<li>How do I isolate the &#8220;interactiveness&#8221; of the tool in a testable class?</p>
<li>How do I isolate &#038; test the creation of Vectorworks geometry?
<li>How do the chosen tests drive the design &#038; architecture of the code?
</ul>
<p>Tune in next week when you&#8217;ll hear Dr. Bob wondering about how to get this thing off the ground.</p>
<p>Episodes so far:</p>
<ul>
<li><a href="http://www.spuriousthoughts.com/2011/04/16/developing-a-vectorworks-2011-plug-in-tdd-style-episode-0/">Episode 0 &#8211; Introduction</a>
<li><a href="http://www.spuriousthoughts.com/2011/06/08/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-1/">Episode 1 &#8211; Starting</a>
<li><a href="http://www.spuriousthoughts.com/2011/06/17/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-2/">Episode 2 &#8211; Structural changes</a>
<li><a href="http://www.spuriousthoughts.com/2011/07/22/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-3/">Episode 3 &#8211; Creating Geometry</a>
<li><a href="http://www.spuriousthoughts.com/?p=1333">Episode 4 &#8211; Tracking mouse movement</a>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.spuriousthoughts.com/2011/06/02/developing-a-vectorworks-2011-tool-plug-in-tdd-style-episode-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Developing a Vectorworks 2011 Plug-in, TDD-style &#8211; Epilogue</title>
		<link>http://www.spuriousthoughts.com/2011/05/02/developing-a-vectorworks-2011-plug-in-tdd-style-epilogue/</link>
		<comments>http://www.spuriousthoughts.com/2011/05/02/developing-a-vectorworks-2011-plug-in-tdd-style-epilogue/#comments</comments>
		<pubDate>Mon, 02 May 2011 18:59:37 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Vectorworks]]></category>

		<guid isPermaLink="false">http://www.spuriousthoughts.com/?p=1175</guid>
		<description><![CDATA[The code Please download the Xcode 3.2.3 project including all the sources here &#8211; SimpleCabinet.zip. The folder SimpleCabinet should be dropped into Vectorworks 2011 SDK&#8217;s Sources folder, like this: The project features two targets, a testing target named &#8220;CppUnitLite2&#8243; and the plug-in module shared library target, which outputs to /Applications/Vectorworks2011/Plug-ins. You will notice that all [...]]]></description>
			<content:encoded><![CDATA[<h2>The code</h2>
<p>Please download the Xcode 3.2.3 project including all the sources here &#8211; <a href='http://www.spuriousthoughts.com/wp-content/uploads/2011/04/SimpleCabinet.zip'>SimpleCabinet.zip</a>. The folder <tt>SimpleCabinet</tt> should be dropped into Vectorworks 2011 SDK&#8217;s <tt>Sources</tt> folder, like this:</p>
<p><a href="http://www.spuriousthoughts.com/wp-content/uploads/2011/04/filelayout.png"><img src="http://www.spuriousthoughts.com/wp-content/uploads/2011/04/filelayout-300x182.png" alt="" title="filelayout" width="300" height="182" class="alignnone size-medium wp-image-1137" /></a></p>
<p>The project features two targets, a testing target named &#8220;CppUnitLite2&#8243; and the plug-in module shared library target, which outputs to <tt>/Applications/Vectorworks2011/Plug-ins</tt>. You will notice that all classes plus tests are contain in <tt>ExtObject.cpp</tt>. I&#8217;m doing this for small spikes like this &#8211; in real life, I would put each class in a separate file, no code in the header file etc.</p>
<p>The code features additional tests, refactorings and more usage of VWFC in <tt>SimpleCabinetCreator</tt>.</p>
<p>I haven&#8217;t gotten around to preparing &#038; cleaning up the Visual Studio project of the Simple Cabinet project. Make sure to bug me so I feel obliged to release it, too.</p>
<h2>Summary</h2>
<p>It&#8217;s possible to create VectorWorks plug-in objects via TDD. In fact, it&#8217;s desirable: Developing the code test-first gave us a very nice separation between the testable model and a very thin layer creating the actual Vectorworks geometry. The SDK stubs (which exist, at this point, for the sole purpose of satisfying the linker) allow us to have a separate testing target and to mix testing code and non-testing code freely.</p>
<p>I found that it&#8217;s also possible to develop Vectorworks Layoutmanager-based dialogs (either straight ISDK or VWUI-based) in a strict TDD fashion, but that&#8217;s another series of posts waiting to be written and code / project files waiting to be cleaned up.</p>
<p>Wether it&#8217;s possible to develop Vectorworks tools in a test-driven fashion remains to be seen (although I&#8217;m pretty optimistic that it can be done quite nicely). I do have some thoughts on this matter but they aren&#8217;t coherent yet.</p>
<p>If you have any feedback regarding this series, please do not hesitate to post comments on the episodes, or contact me at hm dot kern at extragroup dot de, on <a href="http://twitter.com/hmkern99">Twitter</a> or <a href="http://www.facebook.com/people/Hans-Martin-Kern/1040720642">Facebook</a>. I look forward to hearing from you.</p>
<h2>Episodes</h2>
<ul>
<li><a href="http://www.spuriousthoughts.com/2011/04/16/developing-a-vectorworks-2011-plug-in-tdd-style-episode-0/">Episode 0 &#8211; Introduction</a>
<li><a href="http://www.spuriousthoughts.com/2011/04/17/developing-a-vectorworks-2011-plug-in-tdd-style-episode-1/">Episode 1 &#8211; How to start?</a>
<li><a href="http://www.spuriousthoughts.com/2011/04/17/developing-a-vectorworks-2011-plug-in-tdd-style-episode-2/">Episode 2 &#8211; Spicing up our class</a>
<li><a href="http://www.spuriousthoughts.com/2011/04/18/developing-a-vectorworks-2011-plug-in-tdd-style-episode-3/">Episode 3 &#8211; Not doing the same sketch twice</a>
<li><a href="http://www.spuriousthoughts.com/2011/04/19/developing-a-vectorworks-2011-plug-in-tdd-style-episode-4/">Episode 4 &#8211; Creating Vectorworks geometry</a>
<li><a href="http://www.spuriousthoughts.com/2011/04/21/developing-a-vectorworks-2011-plug-in-tdd-style-episode-5/">Episode 5 &#8211; A third class</a>
<li><a href="http://www.spuriousthoughts.com/2011/04/24/developing-a-vectorworks-2011-plug-in-tdd-style-episode-6/">Episode 6 &#8211; Rolled-up newspaper</a>
<li><a href="http://www.spuriousthoughts.com/2011/04/27/developing-a-vectorworks-2011-plug-in-tdd-style-episode-7/">Episode 7 &#8211; A few more additions</a>
<li><a href="http://www.spuriousthoughts.com/2011/05/02/developing-a-vectorworks-2011-plug-in-tdd-style-epilogue/">Epilogue &#038; Code</a>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.spuriousthoughts.com/2011/05/02/developing-a-vectorworks-2011-plug-in-tdd-style-epilogue/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Developing a Vectorworks 2011 Plug-in, TDD-style &#8211; Episode 7</title>
		<link>http://www.spuriousthoughts.com/2011/04/27/developing-a-vectorworks-2011-plug-in-tdd-style-episode-7/</link>
		<comments>http://www.spuriousthoughts.com/2011/04/27/developing-a-vectorworks-2011-plug-in-tdd-style-episode-7/#comments</comments>
		<pubDate>Wed, 27 Apr 2011 19:17:05 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Vectorworks]]></category>

		<guid isPermaLink="false">http://www.spuriousthoughts.com/?p=1166</guid>
		<description><![CDATA[Now that we&#8217;re able to place a grid of front tiles / segments, the only thing left is the placement of the right / top blind front panels &#8211; if the front tiles don&#8217;t fit properly. As always, we&#8217;re starting with a very basic test. The right blind front (if there&#8217;s one) will be placed [...]]]></description>
			<content:encoded><![CDATA[<p>Now that we&#8217;re able to place a grid of front tiles / segments, the only thing left is the placement of the right / top blind front panels &#8211; if the front tiles don&#8217;t fit properly. As always, we&#8217;re starting with a very basic test. The right blind front (if there&#8217;s one) will be placed on the bottom board, therefore start at <tt>z == SimpleCabinetModel::kBoardThickness</tt>.</p>
<pre class="brush: cpp; title: ; notranslate">
TEST_N(FrontModelRightBlindFront)
{
	SimpleCabinetModel simpleCabinet(2 * 200 + 2 * SimpleCabinetModel::kBoardThickness + 50,
									 3 * 150 + 2 * SimpleCabinetModel::kBoardThickness + 70, 800);

	FrontModel frontModel(simpleCabinet.GetFrontModelOrigin(), simpleCabinet.GetFrontWidth(), simpleCabinet.GetFrontHeight());

	CHECK_EQUAL(SimpleCabinetModel::kBoardThickness, frontModel.GetRightZBlindFront());
}
</pre>
<p>Well, you could see that one coming, making the test pass is rather trivial &#8211; but it gets us on the track to more sophisticated functionality.</p>
<pre class="brush: cpp; title: ; notranslate">
	WorldCoord GetRightZBlindFront() const {
		return fOrigin.z;
	}
</pre>
<p>Let&#8217;s add another check to the test. The height of the right blind front should be the height of the front model.</p>
<pre class="brush: cpp; title: ; notranslate">
	CHECK_EQUAL(3 * 150 + 70, frontModel.GetRightBlindFrontHeight());
</pre>
<p>Quite obvious and should be easy to implement. There&#8217;s already an instance variable <tt>fHeight</tt> in the <tt>FrontModel</tt>:</p>
<pre class="brush: cpp; title: ; notranslate">
	WorldCoord frontModel.GetRightBlindFrontHeight() const {
		return fHeight;
	}
</pre>
<p>The third component needed to generate the geometry for the right blind front model is the base rectangular shape for the extrude. Another check for our test. </p>
<pre class="brush: cpp; title: ; notranslate">
	CHECK_EQUAL(WorldRect(SimpleCabinetModel::kBoardThickness + frontModel.GetNumColumns() * FrontModel::kSegmentWidth,
						  FrontModel::kSegmentDepth,
						  SimpleCabinetModel::kBoardThickness + simpleCabinet.GetFrontWidth(), 0),
				frontModel.GetRightBlindFrontBase());
</pre>
<p>Introducing two additional constants for the tile/segment&#8217;s width and depth, making the test pass requires a few lines of code:</p>
<pre class="brush: cpp; title: ; notranslate">
class FrontModel {

	WorldRect GetRightBlindFrontBase() const {
		WorldCoord xStart = fOrigin.x + GetNumColumns() * kSegmentWidth;
		WorldCoord xEnd = fOrigin.x + fWidth;

		WorldRect r(0, 0, 0, 0);
		if (xStart != xEnd)
			r.Set(xStart, kSegmentDepth, xEnd, 0);

		return r;
	}
};
</pre>
<p>The top blind front is tackled the same way &#8211; We need it&#8217;s z position, it&#8217;s x dimensions and it&#8217;s height. Not an awful lot to see there. Now let&#8217;s check if we&#8217;re able to generate Vectorworks geometry with this model.</p>
<pre class="brush: cpp; title: ; notranslate">
	void CreateFrom(const FrontModel&amp; frontModel) {

		// ...

		WorldRect topBlindFrontBase = frontModel.GetTopBlindFrontBase();
		if (topBlindFrontBase != WorldRect(0, 0, 0, 0)) {
			MCObjectHandle topBlindFront = gSDK-&gt;CreateExtrude(frontModel.GetTopZBlindFront(), frontModel.GetTopZBlindFront() + frontModel.GetTopBlindFrontHeight());
			gSDK-&gt;AddObjectToContainer(gSDK-&gt;CreateRectangle(frontModel.GetTopBlindFrontBase()), topBlindFront);
		}

		WorldRect rightBlindFrontBase = frontModel.GetRightBlindFrontBase();
		if (rightBlindFrontBase != WorldRect(0, 0, 0, 0)) {
			MCObjectHandle rightBlindFront = gSDK-&gt;CreateExtrude(frontModel.GetRightZBlindFront(), frontModel.GetRightZBlindFront() + frontModel.GetRightBlindFrontHeight());
			gSDK-&gt;AddObjectToContainer(gSDK-&gt;CreateRectangle(frontModel.GetRightBlindFrontBase()), rightBlindFront);
		}
</pre>
<p>In fact, we are:</p>
<p><img style="display:block; margin-left:auto; margin-right:auto;" src="http://www.spuriousthoughts.com/wp-content/uploads/2011/04/episode-7.png" alt="Episode 7" border="0" width="568" height="600" /></p>
<p>Tune in next weeks when you hear Dr. Bob say: &#8220;Let&#8217;s sum it up, post the code and I&#8217;m outta here&#8221;.</p>
<p><a href="http://www.spuriousthoughts.com/2011/04/24/developing-a-vectorworks-2011-plug-in-tdd-style-episode-6/">Previous Episode</a> | <a href="http://www.spuriousthoughts.com/2011/05/02/developing-a-vectorworks-2011-plug-in-tdd-style-epilogue/">Next Episode</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.spuriousthoughts.com/2011/04/27/developing-a-vectorworks-2011-plug-in-tdd-style-episode-7/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Developing a Vectorworks 2011 Plug-in, TDD-style &#8211; Episode 6</title>
		<link>http://www.spuriousthoughts.com/2011/04/24/developing-a-vectorworks-2011-plug-in-tdd-style-episode-6/</link>
		<comments>http://www.spuriousthoughts.com/2011/04/24/developing-a-vectorworks-2011-plug-in-tdd-style-episode-6/#comments</comments>
		<pubDate>Sun, 24 Apr 2011 13:45:17 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Vectorworks]]></category>

		<guid isPermaLink="false">http://www.spuriousthoughts.com/?p=1148</guid>
		<description><![CDATA[We left off in Episode 5 trying to avoid Dr. Bob hitting us with a rolled-up newspaper as we forgot to account for the front tiles&#8217;s z position. Let&#8217;s see if we can fix this. First, we change the test for the front model origin to expect a WorldPt3 which, obviously, does contain a z-component. [...]]]></description>
			<content:encoded><![CDATA[<p>We left off in <a href="http://www.spuriousthoughts.com/2011/04/21/developing-a-vectorworks-2011-plug-in-tdd-style-episode-5/">Episode 5</a> trying to avoid Dr. Bob hitting us with a rolled-up newspaper as we forgot to account for the front tiles&#8217;s z position. Let&#8217;s see if we can fix this. First, we change the test for the front model origin to expect a <tt>WorldPt3</tt> which, obviously, does contain a z-component.</p>
<pre class="brush: cpp; title: ; notranslate">
TEST_N(FrontModelOrigin)
{
	SimpleCabinetModel simpleCabinet(600, 720, 800);

	FrontModel frontModel(simpleCabinet.GetFrontModelOrigin());

	CHECK_EQUAL(WorldPt3(SimpleCabinetModel::kBoardThickness, 0, SimpleCabinetModel::kBoardThickness), frontModel.GetOrigin());
}
</pre>
<p>Making this test pass requires a series of simple changes to <tt>FrontModel</tt>.</p>
<pre class="brush: cpp; title: ; notranslate">
class FrontModel {

public:

	FrontModel(const WorldPt3&amp; origin) :
		fOrigin(origin) {
	}

	WorldPt3 GetOrigin() const {
		return fOrigin;
	}

private:

	WorldPt3 fOrigin;
}
</pre>
<p>After making these changes gcc tells us that we should probably fix the tests <tt>FrontModelPositionOfFirstSegment</tt> and <tt>FrontModelPositionOfSecondSegment</tt> in order to make this thing compilable again. As in <tt>FrontModelOrigin</tt>, this requires us to replace <tt>WorldPt</tt> with <tt>WorldPt3</tt> and we&#8217;re basically done.</p>
<p>With this out of the way, let&#8217;s concentrate on generalizing our <tt>FrontModel</tt>. So far, we&#8217;re able to calculate the position of the first and second segment / tile (assuming both fit into the cabinet). Looking at the screenshot in episode 0, it sure looks like the front tiles should be arranged in rows &#038; columns. Let&#8217;s see if we can work towards this. How about computing the number of front tile rows &#038; columns which &#8220;fit&#8221; into a given cabinet? Let&#8217;s start with a simple test &#8211; if the cabinet is too small, no front tiles will fit at all.</p>
<pre class="brush: cpp; title: ; notranslate">
TEST_N(FrontModelNoRowsNoColumnsNotWideEnough)
{
	SimpleCabinetModel simpleCabinet(150, 720, 800);

	FrontModel frontModel(simpleCabinet.GetFrontModelOrigin(),
						  simpleCabinet.GetFrontWidth(),
						  simpleCabinet.GetFrontHeight());

	CHECK_EQUAL(0, frontModel.GetNumRows());
	CHECK_EQUAL(0, frontModel.GetNumColumns());
}
</pre>
<p>In order to be able to compute the number of rows &#038; columns, we have to supply the <tt>FrontModel</tt> with the space available for placing front tiles. So, we need tests to for these functions. Let&#8217;s <tt>#if 0</tt> the last test for a moment and write new tests for <tt>GetFrontWidth()</tt> and <tt>GetFrontHeight()</tt>.</p>
<pre class="brush: cpp; title: ; notranslate">
TEST_N(SimpleCabinetFrontWidthHeight)
{
	SimpleCabinetModel simpleCabinet(600, 720, 800);

	CHECK_EQUAL(600 - 2 * SimpleCabinetModel::kBoardThickness,
				simpleCabinet.GetFrontWidth());
	CHECK_EQUAL(720 - 2 * SimpleCabinetModel::kBoardThickness,
				simpleCabinet.GetFrontHeight());
}
</pre>
<p>Let&#8217;s make this test pass.</p>
<pre class="brush: cpp; title: ; notranslate">

class SimpleCabinetModel {

public:

	WorldCoord GetFrontWidth() const {
		return fWidth - 2 * kBoardThickness;
	}

	WorldCoord GetFrontHeight() const {
		return fHeight - 2 * kBoardThickness;
	}
};
</pre>
<p>Backtracking to our test <tt>FrontModelNoRowsNoColumnsNotWideEnough</tt>, we change <tt>FrontModel</tt>&#8216;s constructor (again).</p>
<pre class="brush: cpp; title: ; notranslate">
class FrontModel {

public:

	FrontModel(const WorldPt3&amp; origin, WorldCoord width, WorldCoord height) :
		fOrigin(origin), fWidth(width), fHeight(height) {
	}
};
</pre>
<p>What was our intital goal? Ah, computing the number of rows &#038; columns (in order to make the test pass). Well, that&#8217;s straightforward:</p>
<pre class="brush: cpp; title: ; notranslate">
class FrontModel {

public:

	long GetNumRows() const {
		return 0;
	}

	long GetNumColumns() const {
		return 0;
	}
};
</pre>
<p>Indeed, it&#8217;s pretty straightforward for the test we&#8217;re trying to make pass. We just write enough code to make the test pass. And returning <tt>0</tt> makes the test pass. Let&#8217;s move on to the next test.</p>
<pre class="brush: cpp; title: ; notranslate">
TEST_N(FrontModelThreeRowsTwoColumnsFits)
{
	SimpleCabinetModel simpleCabinet(2 * 200 + 2 * SimpleCabinetModel::kBoardThickness,
									 3 * 150 + 2 * SimpleCabinetModel::kBoardThickness,
									 800);

	FrontModel frontModel(simpleCabinet.GetFrontModelOrigin(),
						  simpleCabinet.GetFrontWidth(),
						  simpleCabinet.GetFrontHeight());

	CHECK_EQUAL(3, frontModel.GetNumRows());
	CHECK_EQUAL(2, frontModel.GetNumColumns());
}
</pre>
<p>Now is the right time to flesh out <tt>GetNumRows()</tt> and <tt>GetNumColumns()</tt>.</p>
<pre class="brush: cpp; title: ; notranslate">
class FrontModel {

public:

	long GetNumRows() const {
		return MyMathUtils::fdiv(fHeight, SimpleCabinetModel::kSegmentHeight);
	}

	long GetNumColumns() const {
		return MyMathUtils::fdiv(fWidth, SimpleCabinetModel::kSegmentWidth);
	}
};
</pre>
<p>In order to get the number of front tiles fitting into a row, we need to divide the overall width available for the front tiles and divide it (as in division of integers) by the width of a segment. Same for the number of front tiles fitting into a column.</p>
<p>Where are we at? We now have code for calculating the number of tiles in x direction (columns) and z direction (rows). If we would have a function computing the x, y &#038; z position of a front tile at a given row &#038; column we could certainly beef up <tt>SimpleCabinetCreator::CreateFrom()</tt> with a nice loop placing all the front tiles. Let&#8217;s write a test for this function computing a tiles position:</p>
<pre class="brush: cpp; title: ; notranslate">
TEST_N(FrontModelPositionOfARowColumn)
{
	SimpleCabinetModel simpleCabinet(1200, 720, 800);

	FrontModel frontModel(simpleCabinet.GetFrontModelOrigin(),
						  simpleCabinet.GetFrontWidth(),
						  simpleCabinet.GetFrontHeight());

	WorldPt3 expectedPosition = frontModel.GetOrigin() +
								WorldPt3(3 * SimpleCabinetModel::kSegmentWidth, 0,
										 2 * SimpleCabinetModel::kSegmentHeight)
	CHECK_EQUAL(expectedPosition,
				frontModel.GetSegmentPosition(3, 2));
}
</pre>
<p>Here&#8217;s the code to make the test pass:</p>
<pre class="brush: cpp; title: ; notranslate">
class FrontModel {

public:

	WorldPt3 GetSegmentPosition(long column, long row) const
	{
		WorldPt3 position(GetOrigin());

		position += WorldPt3(column * fSegmentWidth,
							 0,
							 row * fSegmentHeight);

		return position;
	}
};
</pre>
<p>And for the grand final of this episode, let&#8217;s tackle placing the front tile symbols in <tt>SimpleCabinetCreator::CreateFrom()</tt>. With the preparatory work we&#8217;ve done in this episode it should be pretty straightforward &#8211; and it is:</p>
<pre class="brush: cpp; title: ; notranslate">
	void CreateFrom(const FrontModel&amp; frontModel) {

		for (long i = 0; i  frontModel.GetNumColumns(); i++)
			for (long j = 0; j &lt; frontModel.GetNumRows(); j++) {
				VWObject frontSegment = gSDK-&gt;PlaceSymbolByNameN(frontModel.GetFrontSymbolName(), WorldPt(0, 0));
				frontSegment.MoveObject3D(frontModel.GetSegmentPosition(i, j));
				fSimpleCabinet.AddObject(frontSegment);
			}
	}
</pre>
<p><img style="display:block; margin-left:auto; margin-right:auto;" src="http://www.spuriousthoughts.com/wp-content/uploads/2011/04/episode-6.png" alt="Episode 6" border="0" width="600" height="497" /></p>
<p>Tune in next week when you hear Nurse Piggy say: &#8220;Are we done yet? I have a date with a certain frog for dinner&#8230; &#8220;.</p>
<p><a href="http://www.spuriousthoughts.com/2011/04/21/developing-a-vectorworks-2011-plug-in-tdd-style-episode-5/">Previous Episode</a> | <a href="http://www.spuriousthoughts.com/2011/04/27/developing-a-vectorworks-2011-plug-in-tdd-style-episode-7/">Next Episode</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.spuriousthoughts.com/2011/04/24/developing-a-vectorworks-2011-plug-in-tdd-style-episode-6/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

