tag:blogger.com,1999:blog-40335124927362920342024-03-08T02:59:39.995-05:00Not Your Average DeveloperA place to gather my thoughts about new technologies, new things learned, and what I can do to try to improve "the process".Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-4033512492736292034.post-7694728087813224442011-03-12T00:37:00.002-05:002011-03-12T00:46:25.546-05:00Bad smells<div>As developers, we all do it. We're not proud of it but we do it anyways. I'm talking about writing bad code. Often times, we even know the code is bad while we are writing it. So why do we accept our own subpar code? Let's assume that our skills are such that we could improve the code...after all, that is one of the reasons we feel it is bad code to begin with? So I reiterate, why do we accept it? We usually try to justify it by telling ourselves that we will come and clean it up with the next iteration. The sad reality is that doesn't always happen. I think its a cultural thing. We are too often focused on just getting the code out so we can move onto the next thing. <br />
I think the solution calls for a cultural shift to focus more on quality and maintainability. In the short term, it will appear that we are less productive. In the long run, however, the code will be more robust, scalable, and maintainable which ultimately provides the most value to the company.</div>Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com1tag:blogger.com,1999:blog-4033512492736292034.post-76831279070070264372010-05-27T21:55:00.000-04:002010-05-27T21:56:44.083-04:00Setting up a hosted svn server using tortoise svn and collabnet subversion server<p>Most professional developers use some form of version control at their work but lack such a support system at home.  One of the easiest ways to get up and running is by using TortoiseSVN for Windows.  The best part about it is that it is both intuitive and FREE!  Furthermore, if you have a separate pc that you want to use as a hosted source control server, you can use CollabNet Subversion Server (also a free application). </p> <p>This tutorial is designed to show how to host a subversion server so it is available to other machines on your network.  For my setup, I am running Windows 7 Ultimate edition x64 on my primary machine.  For my secondary machine (named BuildServer), I am running Windows 7 Ultimate x32 in a hosted VMWare virtual machine.  Both systems already have TortoiseSVN installed.  TortoiseSVN is simply one of the best windows clients for subversion.  You can download it from: <a title="http://tortoisesvn.tigris.org/" href="http://tortoisesvn.tigris.org/">http://tortoisesvn.tigris.org/</a></p> <p>The next step is to go to the machine where you want to host your source control server.  Download the CollabNet Subversion Server for Windows from the following link: <a title="http://www.open.collab.net/downloads/subversion/" href="http://www.open.collab.net/downloads/subversion/">http://www.open.collab.net/downloads/subversion/</a></p> <p>Once downloaded, begin your install process.  The following set of screen shots show what you can expect (as you can see, I am currently using CollabNet Subversion Server 1.6.11).</p> <p><a href="http://lh5.ggpht.com/_hDfZjBOHwGo/S_S7_sNGxlI/AAAAAAAAKek/Ujic0tJc0l0/s1600-h/image%5B4%5D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_hDfZjBOHwGo/S_S8AjA9QYI/AAAAAAAAKeo/z4dwsMPFCBA/image_thumb%5B1%5D.png?imgmax=800" width="495" height="388" /></a></p> <p> <a href="http://lh4.ggpht.com/_hDfZjBOHwGo/S_8iUtXGVmI/AAAAAAAAKg0/4_QC4MV-7vA/s1600-h/image5%5B1%5D%5B3%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_hDfZjBOHwGo/S_S8B9cJrlI/AAAAAAAAKg4/lFz7O9mTy98/image5%5B1%5D_thumb%5B2%5D.png?imgmax=800" width="497" height="391" /></a> </p> <p>There are a few options for how you want to host your source control server.  Since I am on a Windows machine that has IIS running, I chose to run CollabNet Subversion Server as a windows service.  The alternative would be to use the included Apache(MOD_DAV_SVN) server.  It has it’s own advantages, but I was not patient enough to get the configuration properly set up side by side with IIS.  I suspect, if I didn’t have IIS on the machine, the Apache install would have been just as easy.</p> <p><a href="http://lh3.ggpht.com/_hDfZjBOHwGo/S_X0p6Z6d3I/AAAAAAAAKg8/ryPXEMfpzKA/s1600-h/image%5B2%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_hDfZjBOHwGo/S_X0q-CGVmI/AAAAAAAAKhA/OqBgt8Osez4/image_thumb%5B1%5D.png?imgmax=800" width="503" height="397" /></a> </p> <p>Here I chose the default port for communication but I modified the Repository Path to a shared network drive.  By default, it prompts to put the repository in C:\svn_repository.  I, however, wanted it on a network path so it can properly be backed up in the event that my virtual machine is turned off.</p> <p><a href="http://lh4.ggpht.com/_hDfZjBOHwGo/S_S8EIOL2CI/AAAAAAAAKhE/hDWIeLNw1Z4/s1600-h/image13%5B1%5D%5B1%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_hDfZjBOHwGo/S_S8EqnOInI/AAAAAAAAKhI/rWYOi55Jdnk/image13%5B1%5D_thumb.png?imgmax=800" width="505" height="395" /></a></p> <p>All of the other selections I chose were the defaults.   </p> <p><a href="http://lh6.ggpht.com/_hDfZjBOHwGo/S_X0rdYbHNI/AAAAAAAAKhM/Fx8H5nbvYGg/s1600-h/image5%5B2%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_hDfZjBOHwGo/S_X0sPF5tnI/AAAAAAAAKhQ/ZEBvTXqM4UQ/image5_thumb.png?imgmax=800" width="504" height="400" /></a></p> <p>Once I initiated the install itself, it also prompted me to enable update notifications.  </p> <p><a href="http://lh3.ggpht.com/_hDfZjBOHwGo/S_S8Hk3IZ1I/AAAAAAAAKhU/ZdJ37mnSCa4/s1600-h/image25%5B1%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_hDfZjBOHwGo/S_S8IpzQVII/AAAAAAAAKhY/2lGTDvKpu-k/image25_thumb.png?imgmax=800" width="505" height="399" /></a> </p> <p>It ran the auto-update and then showed this last prompt to finish.</p> <p> <a href="http://lh5.ggpht.com/_hDfZjBOHwGo/S_S8JN1svSI/AAAAAAAAKhc/iiimUfkkFhk/s1600-h/image29%5B1%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_hDfZjBOHwGo/S_S8J9WkwnI/AAAAAAAAKhg/_z7iQDagu7o/image29_thumb.png?imgmax=800" width="497" height="389" /></a> </p> <p>I don’t recall for certain, but I think the system then prompted me to reboot my machine.  Whether prompted or not, I happened to reboot my machine.  You can then verify it installed by opening the command prompt and running “svnadmin –version”.</p> <p>I recommend running the command line in administrator mode so you can then perform the next step.</p> <p><a href="http://lh4.ggpht.com/_hDfZjBOHwGo/S_X0s2zPsSI/AAAAAAAAKgU/4YbRf93BLEU/s1600-h/image%5B13%5D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_hDfZjBOHwGo/S_X0tnOB-TI/AAAAAAAAKgY/6jlw9aEVPQI/image_thumb%5B7%5D.png?imgmax=800" width="664" height="347" /></a> </p> <p> After confirming the software installed successfully, you need to create the service in windows.  This can be done through the command prompt using the following command: </p> <blockquote> <p><strong><font color="#ffffff">sc create binpath=”\C:\Program Files\CollabNet\Subversion Server\svnserve.exe\” –service –root C:\” displayname= “Subversion” depend= tcpip start= auto</font></strong></p> </blockquote> <p>NOTE: if this command fails to install or you see a different script response, double check that you are running the command prompt in Administrator mode (applicable to Vista & Windows 7 configurations) and that you have administrator rights on the machine.</p> <p><a href="http://lh5.ggpht.com/_hDfZjBOHwGo/S_X0uTPCVPI/AAAAAAAAKgc/PWZWNyYiZ_o/s1600-h/image%5B17%5D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_hDfZjBOHwGo/S_X0vJ-y9_I/AAAAAAAAKgk/wPbePJjxqBw/image_thumb%5B9%5D.png?imgmax=800" width="663" height="379" /></a> </p> <p> Next, go to your system services.  Find “CollabNet Subversion svnserve” and start the service.  A reboot would have been just as effective because the service is set to start automatically.  Alternatively, I could have started the service from command line.</p> <p><a href="http://lh3.ggpht.com/_hDfZjBOHwGo/S_X0vy5ik4I/AAAAAAAAKgo/bxlcWJJ3LgE/s1600-h/image%5B21%5D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_hDfZjBOHwGo/S_X0wuPOm6I/AAAAAAAAKgs/g0alR7kzkY8/image_thumb%5B11%5D.png?imgmax=800" width="677" height="416" /></a>  </p> <p> For curiosity, I examined the properties of the service and the path to the executable was listed as follows: </p> <blockquote> <p><font color="#ffffff"><em>"C:\Program Files\CollabNet\Subversion Server\svnserve.exe" --service -r "\\vmware-host\Shared Folders\S\svn_repository" --listen-port "3690"</em></font></p> </blockquote> <p>Notice the switches specifying the repository path and the listen port.  Depending on how secure you’ve got your machine set, you may need to explicitly open the port the local firewall and/or router. </p> <p>First, verify that the service is working successfully by opening your TortoiseSVN client and entering “svn://localhost” as your repository url.</p> <p><a href="http://lh5.ggpht.com/_hDfZjBOHwGo/S_8iboW_t_I/AAAAAAAAKhk/nqrOhqLw1J0/s1600-h/image%5B6%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_hDfZjBOHwGo/S_8icR5QcfI/AAAAAAAAKho/IRDn80il6yA/image_thumb%5B3%5D.png?imgmax=800" width="502" height="392" /></a> </p> <p>Once you have verified you can access the repository locally, try to access it remotely.  Go to your other machine that is on the same network.  Open the TortoiseSVN repository browser and browse  either by using the machine’s name or direct IP address.  </p> <p><a href="http://lh6.ggpht.com/_hDfZjBOHwGo/S_8idNNaHsI/AAAAAAAAKhs/5UINVrPqC2c/s1600-h/image%5B14%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_hDfZjBOHwGo/S_8id2lQveI/AAAAAAAAKhw/2cJjcWsJoOY/image_thumb%5B9%5D.png?imgmax=800" width="507" height="398" /></a> </p> <p> That’s it!  You are now up and running with your very own hosted source control.  I have even verified that after I configured the port pass through on my firewall, I can access my repository server from outside of my home network!  Consider yourself warned though.  Configuring the port pass through is a definitive security risk.  I recommend before setting up your repository for remote access, you consider seeking help from your friendly network administrator….oh wait.  If you are reading this, you probably are your own network admin!  Just be careful and good luck!  </p> <p>Happy Coding!</p> Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com1tag:blogger.com,1999:blog-4033512492736292034.post-22299241828448084412010-02-23T13:43:00.002-05:002010-04-17T18:11:21.147-04:00Simple Generic Upcast example in vb.net using reflection<p>Here is a quick example of how one can use reflection to perform an upcast in vb.net.  </p><p>In the sample code below, you have  a person class and a contact class.  The contact class inherits from the person class.  Additionally, you have an instance of the Person class which needs to be converted to an instance of the Contact class.  The below code can be used to perform this conversion.  </p><p>This may not be the best way to do this, but it is certainly an easy and quick way of performing the task.</p><p></p><div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:68e76bae-6571-4338-820b-a0142232eee3" class="wlWriterEditableSmartContent"><div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"><div style="background: #ddd; max-height: 500px; overflow: auto"><ol style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px; white-space: nowrap"><li><span style="color:#0000ff">Module</span> Module1</li>
<li style="background: #f3f3f3"> </li>
<li>    <span style="color:#0000ff">Sub</span> Main()</li>
<li style="background: #f3f3f3">        <span style="color:#0000ff">Dim</span> p <span style="color:#0000ff">As</span> <span style="color:#0000ff">New</span> Person() <span style="color:#0000ff">With</span> {.First = <span style="color:#a31515">"Test"</span>, .Last = <span style="color:#a31515">"User"}</span></li>
<li>        Console.WriteLine(<span style="color:#a31515">"{0} {1} {2}"</span>, p.GetType.FullName, p.First, p.Last)</li>
<li style="background: #f3f3f3"> </li>
<li>        <span style="color:#0000ff">Dim</span> c <span style="color:#0000ff">As</span> Contact = Upcast(<span style="color:#0000ff">Of</span> Person, Contact)(p)</li>
<li style="background: #f3f3f3">        c.Phone = <span style="color:#a31515">"555-123-4567"</span></li>
<li>        Console.WriteLine(<span style="color:#a31515">"{0} {1} {2} {3}"</span>, c.GetType.FullName, c.First, c.Last, c.Phone)</li>
<li style="background: #f3f3f3">        c.CallContact()</li>
<li> </li>
<li style="background: #f3f3f3">        Console.ReadLine()</li>
<li>    <span style="color:#0000ff">End</span> <span style="color:#0000ff">Sub</span></li>
<li style="background: #f3f3f3"> </li>
<li>    <span style="color:#0000ff">Public</span> <span style="color:#0000ff">Function</span> Upcast(<span style="color:#0000ff">Of</span> B, S <span style="color:#0000ff">As</span> {<span style="color:#0000ff">New</span>, B})(<span style="color:#0000ff">ByVal</span> baseObj <span style="color:#0000ff">As</span> B) <span style="color:#0000ff">As</span> S</li>
<li style="background: #f3f3f3">        <span style="color:#0000ff">Dim</span> superObj <span style="color:#0000ff">As</span> S = <span style="color:#0000ff">New</span> S()</li>
<li>        <span style="color:#0000ff">Dim</span> superProp <span style="color:#0000ff">As</span> System.Reflection.PropertyInfo = <span style="color:#0000ff">Nothing</span></li>
<li style="background: #f3f3f3"> </li>
<li>        <span style="color:#0000ff">For</span> <span style="color:#0000ff">Each</span> baseProp <span style="color:#0000ff">As</span> System.Reflection.PropertyInfo <span style="color:#0000ff">In</span> baseObj.GetType().GetProperties()</li>
<li style="background: #f3f3f3">            superProp = superObj.GetType().GetProperty(baseProp.Name)</li>
<li>            superProp.SetValue(superObj, baseProp.GetValue(baseObj, <span style="color:#0000ff">Nothing</span>), <span style="color:#0000ff">Nothing</span>)</li>
<li style="background: #f3f3f3">        <span style="color:#0000ff">Next</span></li>
<li> </li>
<li style="background: #f3f3f3">        <span style="color:#0000ff">Return</span> superObj</li>
<li>    <span style="color:#0000ff">End</span> <span style="color:#0000ff">Function</span></li>
<li style="background: #f3f3f3"> </li>
<li>    <span style="color:#0000ff">Public</span> <span style="color:#0000ff">Class</span> Person</li>
<li style="background: #f3f3f3">        <span style="color:#0000ff">Private</span> _First <span style="color:#0000ff">As</span> <span style="color:#0000ff">String</span></li>
<li>        <span style="color:#0000ff">Private</span> _Last <span style="color:#0000ff">As</span> <span style="color:#0000ff">String</span></li>
<li style="background: #f3f3f3"> </li>
<li>        <span style="color:#0000ff">Public</span> <span style="color:#0000ff">Property</span> First() <span style="color:#0000ff">As</span> <span style="color:#0000ff">String</span></li>
<li style="background: #f3f3f3">            <span style="color:#0000ff">Get</span></li>
<li>                <span style="color:#0000ff">Return</span> _First</li>
<li style="background: #f3f3f3">            <span style="color:#0000ff">End</span> <span style="color:#0000ff">Get</span></li>
<li>            <span style="color:#0000ff">Set</span>(<span style="color:#0000ff">ByVal</span> value <span style="color:#0000ff">As</span> <span style="color:#0000ff">String</span>)</li>
<li style="background: #f3f3f3">                _First = value</li>
<li>            <span style="color:#0000ff">End</span> <span style="color:#0000ff">Set</span></li>
<li style="background: #f3f3f3">        <span style="color:#0000ff">End</span> <span style="color:#0000ff">Property</span></li>
<li> </li>
<li style="background: #f3f3f3">        <span style="color:#0000ff">Public</span> <span style="color:#0000ff">Property</span> Last() <span style="color:#0000ff">As</span> <span style="color:#0000ff">String</span></li>
<li>            <span style="color:#0000ff">Get</span></li>
<li style="background: #f3f3f3">                <span style="color:#0000ff">Return</span> _Last</li>
<li>            <span style="color:#0000ff">End</span> <span style="color:#0000ff">Get</span></li>
<li style="background: #f3f3f3">            <span style="color:#0000ff">Set</span>(<span style="color:#0000ff">ByVal</span> value <span style="color:#0000ff">As</span> <span style="color:#0000ff">String</span>)</li>
<li>                _Last = value</li>
<li style="background: #f3f3f3">            <span style="color:#0000ff">End</span> <span style="color:#0000ff">Set</span></li>
<li>        <span style="color:#0000ff">End</span> <span style="color:#0000ff">Property</span></li>
<li style="background: #f3f3f3">    <span style="color:#0000ff">End</span> <span style="color:#0000ff">Class</span></li>
<li> </li>
<li style="background: #f3f3f3">    <span style="color:#0000ff">Public</span> <span style="color:#0000ff">Class</span> Contact</li>
<li>        <span style="color:#0000ff">Inherits</span> Person</li>
<li style="background: #f3f3f3"> </li>
<li>        <span style="color:#0000ff">Private</span> _Phone <span style="color:#0000ff">As</span> <span style="color:#0000ff">String</span></li>
<li style="background: #f3f3f3">        <span style="color:#0000ff">Public</span> <span style="color:#0000ff">Property</span> Phone() <span style="color:#0000ff">As</span> <span style="color:#0000ff">String</span></li>
<li>            <span style="color:#0000ff">Get</span></li>
<li style="background: #f3f3f3">                <span style="color:#0000ff">Return</span> _Phone</li>
<li>            <span style="color:#0000ff">End</span> <span style="color:#0000ff">Get</span></li>
<li style="background: #f3f3f3">            <span style="color:#0000ff">Set</span>(<span style="color:#0000ff">ByVal</span> value <span style="color:#0000ff">As</span> <span style="color:#0000ff">String</span>)</li>
<li>                _Phone = value</li>
<li style="background: #f3f3f3">            <span style="color:#0000ff">End</span> <span style="color:#0000ff">Set</span></li>
<li>        <span style="color:#0000ff">End</span> <span style="color:#0000ff">Property</span></li>
<li style="background: #f3f3f3"> </li>
<li>        <span style="color:#0000ff">Public</span> <span style="color:#0000ff">Sub</span> CallContact()</li>
<li style="background: #f3f3f3">            Console.WriteLine(<span style="color:#a31515">"Calling {0}...."</span>, Phone)</li>
<li>        <span style="color:#0000ff">End</span> <span style="color:#0000ff">Sub</span></li>
<li style="background: #f3f3f3">    <span style="color:#0000ff">End</span> <span style="color:#0000ff">Class</span></li>
<li><span style="color:#0000ff">End</span> <span style="color:#0000ff">Module</span></li>
</ol></div></div></div>Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0tag:blogger.com,1999:blog-4033512492736292034.post-85423849785700024222009-12-02T11:30:00.002-05:002009-12-02T17:46:49.244-05:00My favorite ssms Toolspack snippet<p>Sometimes we all need a good laugh.  One of the tools I use is the SSMS Tools Plug-in for Microsoft SQL Server Management Studio (SSMS).  Today, I learned that there are shortcut snippets for some of the more common SQL commands.  As I was looking through the snippet shortcuts, I had to laugh when I discovered the last default snippet entry.  Check it out and give props to the authors of this tool for creating the tool with a shortcut to express how we all sometimes feel!  </p><p><a href="http://lh4.ggpht.com/_hDfZjBOHwGo/SxaWX7pe2NI/AAAAAAAAJXQ/kmwYI2-QjRM/s1600-h/image%5B3%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_hDfZjBOHwGo/SxaWYFGezII/AAAAAAAAJXU/LKt3EB8kv5Y/image_thumb%5B1%5D.png?imgmax=800" width="564" height="485" /></a> </p><p>SSMS Tools is a free plug-in that you can download from <a href="http://www.ssmstoolspack.com/">http://www.ssmstoolspack.com/</a>.  It does offer many other useful features.  I do recommend this tool as a nice enhancement to SSMS.  It really is a great plug-in and it deserves proper recognition as well.  Thank you for creating such a great tool and maintaining a sense of humor while doing so.  </p>Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0tag:blogger.com,1999:blog-4033512492736292034.post-46191021923115048672009-11-19T13:58:00.002-05:002009-11-19T23:14:28.165-05:00Fun with reflection: Invoking a private method<p>I was recently working on a project where the use of reflection became one of the proposed solutions.  Before I go any further, allow me to preface this by saying that reflection can be costly and have negative performance impacts.  It is not always type safe and may lead to run-time exceptions.  Other alternatives should be considered before committing to using reflection as a solution.  </p><p>The scenario we had was we needed to access a private method inside a legacy .NET assembly.  I'm not going to get into the reasons why.  The alternative was to duplicate all of the logic that was needed from legacy code.  I mentioned to a co-worker that we could use reflection to invoke a private method.  He was skeptical so I provided him with the following spike solution code showing how to do just that. It's a simple, but complete working example that I thought I would share with all of you.</p><div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:17d8067e-ab33-4799-bfea-a4809fcb2758" class="wlWriterEditableSmartContent"><div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"><div style="background: #ddd; max-height: 500px; overflow: auto"><ol style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px; white-space: nowrap"><li><span style="color:#0000ff">using</span> System;</li>
<li style="background: #f3f3f3"><span style="color:#0000ff">using</span> System.Collections.Generic;</li>
<li><span style="color:#0000ff">using</span> System.Reflection;</li>
<li style="background: #f3f3f3"> </li>
<li><span style="color:#0000ff">namespace</span> ConsoleApplication1 {</li>
<li style="background: #f3f3f3">    <span style="color:#0000ff">class</span> <span style="color:#2b91af">Program</span> {</li>
<li>        <span style="color:#0000ff">static</span> <span style="color:#0000ff">void</span> Main(<span style="color:#0000ff">string</span>[] args) {</li>
<li style="background: #f3f3f3">            HelloWorld hw = <span style="color:#0000ff">new</span> HelloWorld();</li>
<li> </li>
<li style="background: #f3f3f3">            hw.SayWhatsUp();</li>
<li>            hw.name = <span style="color:#a31515">"World"</span>;</li>
<li style="background: #f3f3f3"> </li>
<li>            <span style="color:#2b91af">BindingFlags</span> eFlags = <span style="color:#2b91af">BindingFlags</span>.Instance | <span style="color:#2b91af">BindingFlags</span>.Public | <span style="color:#2b91af">BindingFlags</span>.NonPublic;</li>
<li style="background: #f3f3f3">            <span style="color:#2b91af">MethodInfo</span> hi = <span style="color:#0000ff">null</span>;</li>
<li>            </li>
<li style="background: #f3f3f3">            hi = hw.GetType().GetMethod(<span style="color:#a31515">"SayHi"</span>, eFlags);</li>
<li> </li>
<li style="background: #f3f3f3">            <span style="color:#0000ff">object</span>[] a = <span style="color:#0000ff">new</span> <span style="color:#2b91af">List</span><<span style="color:#0000ff">object</span>>().ToArray();</li>
<li>            <span style="color:#0000ff">if</span> (hi != <span style="color:#0000ff">null</span>) {</li>
<li style="background: #f3f3f3">                hi.Invoke(hw, a);</li>
<li>            } <span style="color:#0000ff">else</span> {</li>
<li style="background: #f3f3f3">                <span style="color:#2b91af">Console</span>.WriteLine(<span style="color:#a31515">"Method Not Found."</span>);</li>
<li>            }</li>
<li style="background: #f3f3f3"> </li>
<li>            <span style="color:#2b91af">Console</span>.ReadLine();</li>
<li style="background: #f3f3f3">        }</li>
<li>    }</li>
<li style="background: #f3f3f3"> </li>
<li> </li>
<li style="background: #f3f3f3">    <span style="color:#0000ff">public</span> <span style="color:#0000ff">class</span> <span style="color:#2b91af">HelloWorld</span> {</li>
<li>        <span style="color:#0000ff">public</span> <span style="color:#0000ff">string</span> name { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }</li>
<li style="background: #f3f3f3"> </li>
<li>        <span style="color:#0000ff">public</span> <span style="color:#0000ff">void</span> SayWhatsUp() {</li>
<li style="background: #f3f3f3">            <span style="color:#2b91af">Console</span>.WriteLine(<span style="color:#a31515">"Whats Up"</span>);</li>
<li>        }</li>
<li style="background: #f3f3f3"> </li>
<li>        <span style="color:#0000ff">private</span> <span style="color:#0000ff">void</span> SayHi() {</li>
<li style="background: #f3f3f3">            <span style="color:#2b91af">Console</span>.WriteLine(<span style="color:#a31515">"Hi "</span> + name);</li>
<li>        }</li>
<li style="background: #f3f3f3">    }</li>
<li>}</li>
</ol></div></div></div>Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0tag:blogger.com,1999:blog-4033512492736292034.post-39025246927283288482009-11-06T23:14:00.001-05:002009-11-06T23:18:14.156-05:00When to trust that gut feeling...This week has emphasized some common knowledge that I went against earlier this week. Monday morning I wasn't feeling well but figured I could make it through the day. When I got to work, I was informed of a bug in our production code that I had introduced a few months ago. Though the problem had existed for a few months, it was considered critical and needed to be fixed immediately. Despite not feeling up to par, I began investigating the issue. As my day progressed, I began to feel worse yet I continued to work at the problem. By mid-day, I was nearly complete with a solution one of my team members suggested despite having a gut feeling it wasn't quite right. I couldn't explain how it wasn't right or prove it wasn't the perfect solution so I went with it. I rushed through what I felt was a complete solution and did some quick testing. Everything seemed to work and I needed to go home. I felt like I was beginning to develop a fever.<br />
<br />
I quickly deployed the changes to our TEST environment and updated my team on what I had done. I then went home and went to bed. I basically slept through the night and called in sick on Tuesday. My technical lead confirmed that QA had signed off on the hot fix I prepared and formalized the paperwork for deployment. It went out early Tuesday afternoon seeming to have resolved the existing issue.<br />
<br />
Fast forward a few days to today...Friday. Whatever bug I had earlier in the week has long since passed. Around 2:45pm today, I received an email depicting an exception that the application I had worked on was causing. Again, it was deemed as critical for billing and payroll purposes. Needless to say, it needed to be fixed immediately. Investigating the bug revealed that the hot fix that was pushed out on Tuesday has now caused this new issue which requires a hot fix. I tried my best to resolve the issue by the end of day but with each fix I added a new error occurred. I certainly wasn't going to push out a hot fix that is known to be flawed and hasn't been tested at 5:00pm on a Friday. The fix will have to wait until Monday.<br />
<br />
I think there are a few important lessons to be learned here:<br />
1. Don't be a hero. If you aren't feeling well, just call in sick.<br />
2. Don't work on critical code unless you are thinking clearly.<br />
3. Don't rush critical fixes no matter how trivial they may seem.<br />
4. All code should be tested. Changes resolving a critical issue MUST be tested thoroughly! At the very least, test the fix itself and perform some basic regression testing. A full regression test should be performed if possible.<br />
5. Trust your gut! If you have a bad feeling about something, there is likely a reason for it.Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0tag:blogger.com,1999:blog-4033512492736292034.post-4673081989020393702009-11-02T00:42:00.000-05:002009-11-02T00:42:52.645-05:00Important Lessons!Tonight I experienced the fear that many of my friends and family have felt when they thought they lost everything on their PC. I recently purchased a copy of Windows 7 and was eager to install it. My existing set up was a Tri-boot (Windows 7 RC, Vista, & XP Pro). The XP pro for some reason wouldn't allow me to boot into it after about a month of successfully running all 3 operating systems on the same drive. My machine also has an internal drive partition that I used strictly for data storage amongst all the configurations and a separate partition used for a common "My Documents" folder and some other miscellaneous items. With Windows 7 in hand, I diligently went through the each OS and moved all of the data stored in the OS partitions into my data storage partition for safe keeping. Once I was sure I had everything copied over, I decided I would wipe the existing 3 operating systems and start fresh with a single copy of Windows 7 Ultimate edition. <br />
<br />
I popped the install disc in and booted back to the cd. Upon starting the install, I chose to delete my "XP" partion, my "Vista" partition, and my "Win7RC" partition. I completed the install process on the new unallocated space and booted back into windows. During bootup, something strange caught my eye though. The OS selection briefly appeared asking if I wanted to boot into Windows 7 or Windows 7 indicating that there were 2 operating systems still installed. "Impossible!", I thought. I logged into the fresh install of Windows 7 and immediately went to "My Computer" to access my data storage drive. Much to my surprise, it wasn't there! In its place, however, was my previous Win7RC partition staring right back at me. After the initial panic and wave of nausea passed from thinking I just deleted over 400 GB worth of personal data (of which only 1/2 was properly backed up to an external drive), I started to think it through. <br />
<br />
When a file gets deleted in windows, the data itself is not typically deleted/removed. Instead, windows gets notified that the space that data had occupied is now available for allocation. I began thinking that the deleting a partition would likely follow the same rules since I didn't reformat the disk. The only question was how to access the deleted partition...<br />
<br />
Using my wife's laptop (since I was afraid doing anything on my machine would increase the chance my precious files would be over written), I began to google for free utilities that would retrieve the deleted files. As I was doing that, I figured it would be worth a shot to pull the plug for force a shutdown without saving anything and reboot back into my pre-existing Windows 7 RC install.<br />
<br />
The chance to boot back into the old OS proved to be the perfect solution. After logging in, I opened "My Computer". Though the XP and Vista partitions were no longer showing, the data storage drive appeared to be fully intact!!! I can't even begin to explain the relief I felt knowing that all my photos, music, movies, financial records, and source code were still there. As I write this, all my data is being copied to an external hard drive which will be disconnected to ensure I don't make any more foolish mistakes. Tomorrow, I will finish setting up and customizing the new OS as I want it, then I will decide on a more appropriate and consistent back up strategy to prevent this type of scenario from occurring again.<br />
<br />
So, what I have learned out of all this? First and foremost is that I have been a hypocrite in telling friends and family to implement some sort of data back up plan on a regular basis. Second, that I need to decide on what the best backup strategy is for me and my family....and third, that I need to actually USE the backup strategy that I thought through. Backing up once every 6 - 12 months just doesn't cut it. Tonight I consider myself very fortunate that all was not lost. I hope this may be a learned lesson to all of you as well. Though I got lucky this time, I don't think I would be the next time. I do know this though, I will do everything I can to ensure that I am never in the position again. It's terrifying to think about losing approximately 9 years worth of digital data!Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0tag:blogger.com,1999:blog-4033512492736292034.post-54785887674799516152009-10-01T20:15:00.002-04:002009-10-01T21:08:28.395-04:00PostSharpLast week I ran into a sporadic issue with a WCF service timing out. I was unsure if the timeout was being caused by the network connection, the business processing, or the data access layer. I was unsure if the issue was data related. That led me to the task of profiling my code base. Unfortunately, I have not yet been able to reproduce or find the flaw, but I have learned a lot about our current code base with the help of PostSharp. In case you haven't heard of it, it is an Aspect Oriented Programming (AOP) framework that can be hooked quite easily into any virtually .NET application. <br /><br />I've only just begun to learn about PostSharp myself, but I found it very easy to hook into the code so that it can provide the duration of every method call in the application. I have it set up so it will conditionally log information including the method name, parameter data, and the actually duration if it exceeds a configurable threshold I set. I know that this is just a very minute detail of what this tool offers but I intend to continue exploring with it. From what I can tell, it seems like it will be a priceless tool...one that I would value as much as Lutz Reflector!Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0tag:blogger.com,1999:blog-4033512492736292034.post-4318729983092740512009-07-27T19:14:00.004-04:002009-08-19T12:44:39.692-04:00Requirements from the Developer's perspectiveRequirements. It's not a very ambiguous term though the meaning behind requirements in software development seems to be one of the hardest concepts to grasp. We all know that they are needed for a successful project...yet it seems that they are often a one of the primary reasons for project failure. Whether the requirements simply don't exist, are incomplete, are too vague, or constantly change, they have the ability to make or break a project. <br /><br />One of the issues with requirements is they often self-contradict themselves. The system needs to do perform x, y, & z. It needs to perform at this rate, be dynamic enough to handle any change, be scalable, be database independent, persistent ignorant, etc. Simply put, requirements can't be cast in stone. They are all about compromise one need/feature for another. Perhaps performance is increased by 1% taking on the risk that 1 out of every 100,000 reads against the database might have stale data. Who knows? The fact of the matter is that requirements are similar to a person's growth. Early on, there are lots of changes. They grow to be stagnant for awhile only to be following by a few more spurts of rapid and drastic changes. Eventually, the requirements satisfy most needs and are generally accepted thus becoming stagnant once again. Sooner or later, they will become obsolete and die off only to be replaced by a new set of requirements defining a different scope.<br /><br />So, whose job is it to obtain the requirements? Is it the user, the analyst, architect, project manager, or developer? I think it's everybody's responsibility to contribute. Each person mentioned has some stake in the matter. Granted, a single person may fill more than one role, but that is not the point here. The point is that each role has different needs and wants. Their perspective on the requirements may differ vastly from the next. There needs to be a single person that is the owner of the requirements. All others are just contributors. <br /><br />As a developer in a project that has had been under constant flux, I have felt the pain of changing requirements all too well. I feel that as a developer, I failed in my role as a contributor. Though I didn't own the requirements, I did recognize some potential pitfalls early on and had mentioned them. I had brought them up in a meeting and consensus ruled that they would not be issues. I should have stood up and spoken with more conviction at that point. The pitfalls I suspected were critical in the overall design. These issues have been debated and discussed over numerous meetings since then...each time with a reactive approach instead of proactive. <br /><br />The moral is that, as a developer, I should have recognized the impact the issues I suspected would have and my level of conviction should have followed suit. Instead, I just went along with the consensus. As the issues truly did arise, my pains in trying redesign a core portion of the application have increased exponentially as our deadline approached. Had I done a more thorough design up front, I think I would have noticed more of the inconsistencies in the requirements. The questions I would have uncovered would have clarified the requirements and exposed the risks they presented.Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0tag:blogger.com,1999:blog-4033512492736292034.post-18668714426683056732009-07-18T00:01:00.004-04:002009-07-18T00:21:11.893-04:00Last minute requirement changes....Though I had intended to keep this blog an informative location on the web, I need to rant. I understand that requirements change. I'm a big believer in iterative development cycles for this very reason. There are, however, few things that irritate me more in my professional life than a breaking requirements change at 4:00pm on the Friday there is supposed to be a code freeze. As valid as the case may be, it's a sure way to ruin a person / team's weekend. It is demoralizing to have a working application going into the code freeze without any bugs reported only to have the requirements change 1.5 hours before you plan to leave work...especially after putting in extra time the entire week to accommodate breaking requirements changed the previous Friday. The change in requirements resulted in an extra 4 hours of work today, a broken service, and the need to work through the weekend with hopes of having a fully working and tested service by Monday.<br /><br />I suppose that I need to look at the bright side of things though. I am fortunate enough to be employed at a stable company. Also, I am extremely grateful that last minute breaking requirement changes are rare for my team.Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0tag:blogger.com,1999:blog-4033512492736292034.post-64741051488264289202009-06-19T10:36:00.004-04:002009-08-19T12:45:14.899-04:00System.MissingMethodException while UnitTesting in VS 2008I've run across a strange situation where I have recently modified a WCF service and service contract adding new functionality. All I have done so far is stub in a new method with the appropriate updates to the service, the service contract, & the proxy (which is hand coded). When I try to run my existing unit tests, I am now getting the following error:<br /><br />Class Initialization method <namespace>.<classname>_UnitTests.MyClassInitialize threw exception. System.MissingMethodException: System.MissingMethodException: Method not found: '<namespace>.<returntype> <namespace>.<contractinterface>.<methodname>()'.<br /><namespace><classname><namespace><returntype><namespace><contractinterface><methodname><br /><br />Ironically, the method does exist and if I run the unit test in debug mode, the exception does not occur. If I run all the tests in debug mode, they all pass without a problem (expected result)...but if I just run the tests without being in debug mode, they fail with the MissingMethodException. IF I run the tests in debug mode, get them to all pass, then run them without restarting visual studio and being in debug mode, they pass. This is obviously some kind of a caching issue.<br /><br />As it turns out, the issue appeared to be related to the *.testrunconfig file. Initially, code coverage was enabled. I disabled code coverage then deleted the testrunconfig file. I then cleaned the solution, closed visual studio, re-opened visual studio, & rebuilt the solution. The unit tests then began passing</methodname></contractinterface></namespace></returntype></namespace></classname></namespace></methodname></contractinterface></namespace></returntype></namespace></classname></namespace>Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0tag:blogger.com,1999:blog-4033512492736292034.post-52260979296884957432009-05-01T15:55:00.015-04:002009-11-12T14:47:06.037-05:00Team System Web Access: Time Entry Host Custom Control<p>Previously, Michael Ruminer had created a Silverlight TFS TimeEntry control for use within Team Explorer. His project is hosted within the MSDN Code Gallery at: "http://code.msdn.microsoft.com/SilverlightWITimeEnt". His project creates everything needed for a rudimentary time tracking system within TFS. One of the remaining open issues was how to utilize the same Silverlight TimeEntry control through Team System Web Access (TSWA). <br /> <br />I have created a simple server side web control that will host Michael's TimeEntry control. When I first tried to tackle this issue, I had to learn about the Work Item Templates used by TSWA and what controls already existed. I found the existing controls to be quite limited. As a result, I opted to create my own custom web control. To my surprise, the code changes ended up being extremely simple. First, let me explain what is required to create a custom web control that can be used by a work item template in TSWA. <br /> <br />For TSWA to render a custom control, the control must: <br />1. Inherit from System.Web.UI.WebControls.WebControl <br />2. The control must have a default constructor <br />3. Implement Microsoft.TeamFoundation.WorkItemTracking.Controls.IWorkItemControl * <br />4. Implement Microsoft.TeamFoundation.WebAccess.WorkItemTracking.Controls.IWorkItemWebControl * <br /> <br />* Note: These two interfaces can both be found in: "C:\Program Files\Microsoft Visual Studio 2008 Team System Web Access\Web\bin\". My initial struggles with getting the control render related to the fact I failed to implement BOTH interfaces. Creating a custom windows control only requires the "IWorkItemControl" interface be implemented. <br /> <br />I had wanted to keep the control as simple as possible so all it does is render a simple HTML page with an IFrame. The IFrame source points to the silverlight control. At first, I tried to just render an IFrame on it's own. The control seemed to load and function properly, however, I was getting a javascript error indicating "this.m_buttonsTable.offsetLeft" was null. I found this somewhat confusing since I hadn't written any javascript and the error occured regardless of what the IFrame pointed to. I then realized the script was in a WebResource.axd file, therefore, it must have been generated by the .NET framework. I resolved the javascript issue by wrapping the IFrame in a fully valid HTML page. The control continued to work but without throwing any javascript errors. <br /> <br />Once the control has been built, you have to deploy it. Create a "wicc" file by the same name as the library. Copy both the wicc file and the dll to "C:\Program Files\Microsoft Visual Studio 2008 Team System Web Access\Web\App_Data\CustomControls\" on the server hosting TSWA (assuming you used the default install for TSWA). TSWA will look in the CustomControls folder by default when trying to resolve the assemblies. In my example, my library name was "TimeEntryHost" so my wicc file was titled "TimeEntryHost.wicc". <br /> <br />Its contents are: <br /> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:88f2ab90-47d8-4fe3-80df-312e9752a3e0" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #ddd; max-height: 500px; overflow: auto"> <ol style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"> <li><span style="color:#0000ff"><?</span><span style="color:#a31515">xml</span><span style="color:#0000ff"> </span><span style="color:#ff0000">version</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">1.0</span>"<span style="color:#0000ff">?></span></li> <li style="background: #f3f3f3"><span style="color:#0000ff"><</span><span style="color:#a31515">CustomControl</span><span style="color:#0000ff"> </span><span style="color:#ff0000">xmlns:xsi</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">http://www.w3.org/2001/XMLSchema-instance</span>"<span style="color:#0000ff"> </span><span style="color:#ff0000">xmlns:xsd</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">http://www.w3.org/2001/XMLSchema</span>"<span style="color:#0000ff">></span></li> <li>  <span style="color:#0000ff"><</span><span style="color:#a31515">Assembly</span><span style="color:#0000ff">></span>TimeEntryHost.dll<span style="color:#0000ff"></</span><span style="color:#a31515">Assembly</span><span style="color:#0000ff">></span></li> <li style="background: #f3f3f3">  <span style="color:#0000ff"><</span><span style="color:#a31515">FullClassName</span><span style="color:#0000ff">></span>TFS.TimeEntryHost<span style="color:#0000ff"></</span><span style="color:#a31515">FullClassName</span><span style="color:#0000ff">></span></li> <li><span style="color:#0000ff"></</span><span style="color:#a31515">CustomControl</span><span style="color:#0000ff">></span></li> </ol> </div> </div> </div> <br /> <br /> <br />The template itself renders the control in a tab. Here is the snippet showing how that should be: <br /> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:5b47f2cc-b3e6-4eac-b5ab-d02d90958534" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #ddd; max-height: 500px; overflow: auto"> <ol style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px; white-space: nowrap"> <li><span style="color:#0000ff"><</span><span style="color:#a31515">Tab</span><span style="color:#0000ff"> </span><span style="color:#ff0000">Label</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">Time Entry</span>"<span style="color:#0000ff">></span></li> <li style="background: #f3f3f3">  <span style="color:#0000ff"><</span><span style="color:#a31515">Control</span><span style="color:#0000ff"> </span><span style="color:#ff0000">Type</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">TimeEntryHost</span>"<span style="color:#0000ff"> </span><span style="color:#ff0000">Label</span><span style="color:#0000ff">=</span>""<span style="color:#0000ff"> </span><span style="color:#ff0000">LabelPosition</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">Top</span>"<span style="color:#0000ff"> </span><span style="color:#ff0000">Dock</span><span style="color:#0000ff">=</span>"<span style="color:#0000ff">Left</span>"<span style="color:#0000ff"> /></span></li> <li><span style="color:#0000ff"></</span><span style="color:#a31515">Tab</span><span style="color:#0000ff">></span></li> </ol> </div> </div> </div> <br /> <br />This control could be used to host any web page as well. I'm actually surprised that it wasn't one of the standard pre-built controls due to its simplicity. There is, however, a caveat to the whole thing IF you are rendering DIFFERENT custom controls in Team Explorer (windows) and TSWA (web). Simply put, the work item template has a layout tag. Well, the layout tag needs to be duplicated each with a target attribute. For windows, it should read and for TSWA it should read . I had found this useful tidbit on Shai Raiten's blog at http://blogs.microsoft.co.il/blogs/shair/archive/2008/10/22/how-to-manage-custom-controls-in-team-system-and-web-access.aspx. <br /> <br />The final issue I ran into was importing the template into TFS so it rendered in both Team Explorer and TSWA. If you use the "Process Editor" tool in Visual Studio, you will lose one of the layouts you created causing the control to only render in one of the environments. To get around this issue, import the template from the commmand line. I don't recall where I found that information otherwise I would give proper credit. The import command will look something like the one below: <br />witimport /f "C:\\Task.xml" /t http:// /p "" <br /> <br />Below is the source code to the control itself. I'm sure it is not the most efficient and there is definitely room to improve, but it simple working example of how you can host a Silverlight control in a Work Item Template. <br /> <br /> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:c5e236b7-ad2a-4748-9521-3fce72e525bf" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #ddd; max-height: 300px; overflow: auto"> <ol style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px; white-space: nowrap"> <li><span style="color:#0000ff">using</span> System;</li> <li style="background: #f3f3f3"><span style="color:#0000ff">using</span> System.ComponentModel;</li> <li><span style="color:#0000ff">using</span> System.Web.UI;</li> <li style="background: #f3f3f3"><span style="color:#0000ff">using</span> System.Web.UI.WebControls;</li> <li><span style="color:#0000ff">using</span> Microsoft.TeamFoundation.WorkItemTracking.Controls;</li> <li style="background: #f3f3f3"><span style="color:#0000ff">using</span> Microsoft.TeamFoundation.WebAccess.WorkItemTracking.Controls;</li> <li><span style="color:#0000ff">using</span> Microsoft.TeamFoundation.WorkItemTracking.Client;</li> <li style="background: #f3f3f3"> </li> <li><span style="color:#0000ff">namespace</span> TfsImplementation {</li> <li style="background: #f3f3f3">    [<span style="color:#2b91af">Serializable</span>]</li> <li>    <span style="color:#0000ff">public</span> <span style="color:#0000ff">class</span> <span style="color:#2b91af">TimeEntryHost</span> : WebControl, IWorkItemControl, IWorkItemWebControl {</li> <li style="background: #f3f3f3">        <span style="color:#0000ff">public</span> TimeEntryHost() {</li> <li>            SetDefaults();</li> <li style="background: #f3f3f3">        }</li> <li> </li> <li style="background: #f3f3f3">        <span style="color:#0000ff">private</span> <span style="color:#0000ff">void</span> SetDefaults() {</li> <li>            <span style="color:#0000ff">this</span>.Width = 843;</li> <li style="background: #f3f3f3">            <span style="color:#0000ff">this</span>.Height = 493;</li> <li>        }</li> <li style="background: #f3f3f3"> </li> <li>        <span style="color:#0000ff">protected</span> <span style="color:#0000ff">override</span> <span style="color:#0000ff">void</span> RenderContents(HtmlTextWriter output) {</li> <li style="background: #f3f3f3">            <span style="color:#0000ff">string</span> iframeHtml = <span style="color:#a31515">"<iframe src=\"{0}\" style=\"WIDTH: {1}; HEIGHT: {2};\"></iframe>"</span>;</li> <li>            <span style="color:#0000ff">string</span> urlPath = <span style="color:#0000ff">string</span>.Format(<span style="color:#a31515">"http://TimeControl_TFS.Web/TimeControl_TFSTestPage.aspx?name={0}&wi={1}"</span>,</li> <li style="background: #f3f3f3">                <span style="color:#2b91af">Environment</span>.UserName,</li> <li>                _workItem.Id);</li> <li style="background: #f3f3f3"> </li> <li>            output.Write(<span style="color:#a31515">"<html>"</span>);</li> <li style="background: #f3f3f3">            output.Write(<span style="color:#a31515">"<head>"</span>);</li> <li>            output.Write(<span style="color:#a31515">"<title></title>"</span>);</li> <li style="background: #f3f3f3">            output.Write(<span style="color:#a31515">"</head>"</span>);</li> <li>            output.Write(<span style="color:#a31515">"<body>"</span>);</li> <li style="background: #f3f3f3">            output.Write(<span style="color:#a31515">"<form id=\"form1\">"</span>);</li> <li>            output.Write(<span style="color:#a31515">"<div>"</span>);</li> <li style="background: #f3f3f3">            output.Write(<span style="color:#0000ff">string</span>.Format(iframeHtml, urlPath, Width, Height));</li> <li>            output.Write(<span style="color:#a31515">"</div>"</span>);</li> <li style="background: #f3f3f3">            output.Write(<span style="color:#a31515">"</form>"</span>);</li> <li>            output.Write(<span style="color:#a31515">"</body>"</span>);</li> <li style="background: #f3f3f3">            output.Write(<span style="color:#a31515">"</html>"</span>);</li> <li>        }</li> <li style="background: #f3f3f3"> </li> <li>        <span style="color:#0000ff">#region</span> IWorkItemControl Members</li> <li style="background: #f3f3f3"> </li> <li>        <span style="color:#0000ff">public</span> <span style="color:#0000ff">event</span> <span style="color:#2b91af">EventHandler</span> AfterUpdateDatasource;</li> <li style="background: #f3f3f3">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">event</span> <span style="color:#2b91af">EventHandler</span> BeforeUpdateDatasource;</li> <li> </li> <li style="background: #f3f3f3">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">void</span> Clear() {</li> <li>            RenderContents(<span style="color:#0000ff">new</span> HtmlTextWriter(<span style="color:#0000ff">new</span> System.IO.<span style="color:#2b91af">StringWriter</span>()));</li> <li style="background: #f3f3f3">        }</li> <li> </li> <li style="background: #f3f3f3">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">void</span> FlushToDatasource() {</li> <li>            RenderContents(<span style="color:#0000ff">new</span> HtmlTextWriter(<span style="color:#0000ff">new</span> System.IO.<span style="color:#2b91af">StringWriter</span>()));</li> <li style="background: #f3f3f3">        }</li> <li> </li> <li style="background: #f3f3f3">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">void</span> InvalidateDatasource() {</li> <li>            RenderContents(<span style="color:#0000ff">new</span> HtmlTextWriter(<span style="color:#0000ff">new</span> System.IO.<span style="color:#2b91af">StringWriter</span>()));</li> <li style="background: #f3f3f3">        }</li> <li> </li> <li style="background: #f3f3f3">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">void</span> SetSite(<span style="color:#2b91af">IServiceProvider</span> serviceProvider) {</li> <li>            <span style="color:#008000">//throw new NotImplementedException();</span></li> <li style="background: #f3f3f3">        }</li> <li> </li> <li style="background: #f3f3f3">        <span style="color:#0000ff">public</span> System.Collections.Specialized.<span style="color:#2b91af">StringDictionary</span> Properties { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }</li> <li>        <span style="color:#0000ff">public</span> <span style="color:#0000ff">bool</span> ReadOnly { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }</li> <li style="background: #f3f3f3">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">string</span> WorkItemFieldName { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }</li> <li> </li> <li style="background: #f3f3f3">        <span style="color:#0000ff">private</span> WorkItem _workItem;</li> <li>        <span style="color:#0000ff">public</span> <span style="color:#0000ff">object</span> WorkItemDatasource {</li> <li style="background: #f3f3f3">            <span style="color:#0000ff">get</span> { <span style="color:#0000ff">return</span> _workItem; }</li> <li>            <span style="color:#0000ff">set</span> { _workItem = <span style="color:#0000ff">value</span> <span style="color:#0000ff">as</span> WorkItem; }</li> <li style="background: #f3f3f3">        }</li> <li> </li> <li style="background: #f3f3f3"> </li> <li>        <span style="color:#0000ff">#endregion</span></li> <li style="background: #f3f3f3"> </li> <li>        <span style="color:#0000ff">#region</span> IWorkItemWebControl Members</li> <li style="background: #f3f3f3"> </li> <li>        <span style="color:#0000ff">public</span> <span style="color:#0000ff">string</span> ClientEditorObjectId { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }</li> <li style="background: #f3f3f3">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">string</span> ClientObjectId { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">private</span> <span style="color:#0000ff">set</span>; }</li> <li>        <span style="color:#0000ff">public</span> <span style="color:#0000ff">string</span> ControlId { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }</li> <li style="background: #f3f3f3">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">string</span> Label { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }</li> <li>        <span style="color:#0000ff">public</span> <span style="color:#0000ff">string</span> ThemeUrl { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }</li> <li style="background: #f3f3f3"> </li> <li>        <span style="color:#0000ff">public</span> <span style="color:#0000ff">string</span> GetClientUpdateScript() {</li> <li style="background: #f3f3f3">            <span style="color:#0000ff">return</span> <span style="color:#0000ff">string</span>.Empty;</li> <li>        }</li> <li style="background: #f3f3f3"> </li> <li>        <span style="color:#0000ff">public</span> <span style="color:#0000ff">void</span> InitializeControl() {</li> <li style="background: #f3f3f3">            <span style="color:#008000">//throw new NotImplementedException();</span></li> <li>        }</li> <li style="background: #f3f3f3"> </li> <li>        <span style="color:#0000ff">#endregion</span></li> <li style="background: #f3f3f3">    }</li> <li>}</li> </ol> </div> </div> </div></p> Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0tag:blogger.com,1999:blog-4033512492736292034.post-21482074640263129062009-04-28T15:51:00.003-04:002009-04-28T15:55:50.471-04:00TFS / TSWA Custom Controls - "Unable to create workitem control 'ControlName'." - Part 2As it turns out, I had missed one of the required interfaces. When creating the web control, it requires that it inherits from WebControl and implements IWorkItemControl & IWorkItemWebControl. My initial attempts were missing the IWorkItemWebControl implementation. Once I had that resolved, my control began rendering. Still have some bugs to work out but those should be relatively easy. Once I have the control complete, I will post it with a link to the actual silverlight control I am hosting!Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0tag:blogger.com,1999:blog-4033512492736292034.post-72064947250151093702009-04-28T12:05:00.002-04:002009-04-28T12:19:50.948-04:00TFS / TSWA Custom Controls - "Unable to create workitem control 'ControlName'."I have been trying to create a fairly simple custom control to be used by the TFS Web Access application. At my day job, we use TFS extensively and are working towards a solution that allows us to use it exclusively too. One of the major drawbacks we are currently facing is the lack of a built in time entry control. Another colleague of mine has created a time entry control in Silverlight to facilitate use in the two environments. In Team Explorer, a simple browser control was added to a tab to house the Time Entry component. It works well though it still has some minor quirks. I have been assigned to port the same concept (preferably to use the same Silverlight control) to the web side. <br /><br />The issue I have run into is that the Work Item Template does not have any controls to support Silverlight or any other web site redirection. My thought was to use an IFrame to embed the Silverlight right in but I am not aware of any way to use the existing controls to support it. My next thought was to create a very simple server side control that will just render an IFrame directed to the appropriate URL. The new control is working in test environments (dummy pages), however, when I try to integrate it into the Work Item Template, it fails every time. <br /><br />I have received numerous errors simply indicating that the control can not be created. Using FUSLOGVW.exe, I began to dig into the issue. I've verified in some cases that the library, dependencies, and the .wicc file are all properly located and found. Still, the control can't be created. I've tried modifiying the wicc file, changing namespaces, and updating the web.config (restarting IIS after every change). Every attempt still fails but now I'm getting different errors. <br /><br />In the wicc file for the assembly name, if I include the ".dll" at the end of the assembly name, it searches for "assembly.dll.dll" and/or "assembly.dll.exe". Obviously it will not find a file by either of those names. If I remove the ".dll" at the end of the assembly name, it searches for just the assembly name with no extension at all....which again, it will never find. <br /><br />So the million dollar question is what is going on here? I'm sure it is something stupid that I am overlooking. These things usually turn out that way which only raises the frustrations, but I will figure it out and post my resolution when I do.Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com2tag:blogger.com,1999:blog-4033512492736292034.post-8978306481474895812009-04-07T17:46:00.004-04:002009-04-08T00:39:03.670-04:00The Worst Job I've Had......was likely the best thing possible for my professional career. Though this may seem strange, let me explain the reasoning. I am currently one of the Senior Web Developers within my organization. This is a far cry from the Bachelors Degree in Management I originally graduated with.<br /><br />I started as a self-taught programmer with my first job out of college. I began my career with a small medical software company (2 developers, < 10 employees total) writing low-level communication drivers and APIs (using Delphi, C, & SQL). Being such a small company, alot was demanded from me. I had to design, code, test (with some help), and deploy all of the code I wrote myself to the external customers whom I worked with daily. After 3 years and a greatly expanded set of responsibilities, I was feeling confident. I felt that I knew what I needed to make the next step in my career. With confidence brewing, I moved on to a much larger corporation in the middle of trying to attain Sarbanes-Oxley (SOX) compliance.<br /><br />Needless to say, it was a drastic environmental change for me. I needed to learn to work more as a member of a team rather than being the whole team. I needed to learn new processes and how to formally document my analysis, development plans, and testing plans. The code base was over 100x bigger than anything I had ever worked with deep object inheritance (most of my prior experience had more of a functional form). My manager was new at the role and lacked the experience to recognize how much I struggled...or just didn't have the know how to help me adapt. I worked through it for one year before I moved on again.<br /><br />In preparation for moving on, I recognized that Delphi was a dying language. I wanted to enter the .NET realm and pursue a Masters Degree in Software Engineering. Luck was in my favor and I actually went back to my former employer to work on a new project in .NET with the opportunity to work from home. I found the lackadaisical environment to be comforting having just left a place with significant turbulence. Not to mention, working from home was a great experience and it provided the flexibility I need to attend grad school.<br /><br />Over the next 3 years, I worked towards a Masters in Software Engineering and always found myself reading technical books outside of the classroom. I have taken on the challenge of trying to learn best practices and keep up with new technologies while gaining deeper understanding of existing technologies. I had also discovered how informative podcasts can be (.NET Rocks, Hanselminutes, & ALT.NET to name a few). I recognized that reading the blogs of the industry gurus and my peers provided priceless information, examples, and viewpoints. I've become more of a proponent for open-source and have spent significant time looking at open-source code.<br /><br />Since finishing my Masters, I have moved on to my current employer (which is again a large, highly structured organization). Our development team consists of about 50 employees and contractors. Here I have taken a strong interest in continuous integration, automated builds, and utilizing aspects of agile methodologies in my daily development practices. I am still always reading at least one technical book at a time (often 2 - 3) and follow numerous blogs on a daily basis. I try to be more aware of the things I do not know. I've come to believe that relentless education is the only way to be successful in the software development industry because of it's accellerated rate of growth. For anybody that thinks they know enough to carry them through to retirement, they better plan on retiring soon! Technology is simply changing too fast. If we don't pursue it, we will just be left behind with future prospects fading quickly.<br /><br />So, back to the original statement. The worst job I've had was likely the best thing possible for my professional career. It was quite the humbling experience. I try to remain humble and am always eager to learn something new. I suggest that, you too, implement a relentless pursuit for continued education in the areas you find most interesting. Never consider yourself to THE expert. Be humble, yet confident. There is always something left to be learned no matter how good everything seems.Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0tag:blogger.com,1999:blog-4033512492736292034.post-8041329964192078572009-03-27T10:04:00.007-04:002009-03-27T10:44:07.277-04:00Too Many Stored ProceduresLike many others before me, the code base I am working on has been in existence for many years. It is massive in scope and in actual source code. Behind it all lies a massive database structure with a single common means of accessing all of the data from the application: stored procedures (sprocs). While this may seem like a good idea, there is a point where things get out of control. Our current system has about 2,000 tables and nearly 14,000 sprocs. The only logical grouping of the sprocs is found in the naming conventions used, though this proven itself inconsistent as well. To make matters worse, there is far too much business logic in many of the sprocs. Now, I understand that number of lines of code is not a very reliable metric, but some of the sprocs are in excess of 2,000 lines with many of the sprocs at least 300 - 500 lines long. <br /><br />I recently did a trace through a stored procedure that didn't appear too bad on the surface (it was only 640 lines long). The trace revealed a disturbing revelation. The shortest path through that stored procedure involved calls to 4 additional sprocs. That is acceptable, but that is to determine that it has nothing to do. The shortest functional path through involves calls to over 80 additional sprocs...one of which calls itself recursively. Needless to say, it was a painful experience to trace through to figure out what it is actually doing (oh, I forgot to mention that our specs and documentation are virtually non-existent).<br /><br />So this all brings me to my current point. There is a time when there are too many stored procedures and any benefit gained by them are lost through the loss in maintability. With the exorbitant number of sprocs, most of my co-workers (myself included) will take a short look to see if one already exists meeting our needs, but typically just take the easy road and write a new sproc further propagating the problem. I would like to spearhead an effort to bring some sort of control to this situation and to bring it back to a maintainable state. The million dollar question is simply "How?".Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0tag:blogger.com,1999:blog-4033512492736292034.post-78917376890814077802009-03-24T11:55:00.002-04:002009-03-24T11:58:14.380-04:00Starting my blog...I've been putting off creating my own blog for about a year or so. I've had good intentions but I never seem to give myself the time to do so. So, why now? What makes today so different? Nothing really. I've just become fed up with how I'm utilizing my own time. Life is too short to not go after the things you want in life. My driving motive for this blog is to provide a place for me to document lessons learned (often the hard way), my thoughts on new technologies, and provide a running dialog of my professional growth. I also intend to use this blog as one of many means to help improve my knowledge on any topics discussed while improving my communication skills (hopefully). I tend to be over-ambitious but we will see how this chapter turns out. My goal is to post new messages every few days. I think that is a reasonable expectation but only time will tell.Michael Doyonhttp://www.blogger.com/profile/03817591584050714916noreply@blogger.com0