tag:blogger.com,1999:blog-201890152024-03-13T09:57:00.392-05:00NerdageGaro's musings on nerdage-related things (mostly software development or gadgetry).Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.comBlogger26125tag:blogger.com,1999:blog-20189015.post-11427625789453701402009-04-05T21:37:00.001-05:002012-09-12T22:29:52.725-05:00RefreshedThis weekend I went to the <a href="http://houston.altnetconf.com/">Houston ALT.NET Open Space Conference</a>. It was definitely a refreshing experience. You can check the <a href="http://houstonaltnet.pbwiki.com/">wiki</a> to see what went on and get summaries of the sessions (not all the sessions have summaries yet).<br />
I started to collect a list of <a href="http://houstonaltnet.pbwiki.com/Read-Listen-Watch">things to read, things to listen to, and things to watch</a> that was recommended by anyone in any of the sessions at the conference. If you have any other recommendations for the list, please either send them to me or edit the page and add it yourself. A lot of the entries there still need some explanation on why people should spend their time reading, listening, or watching.<br />
I learned a whole heckuva lot over the weekend. What I really found though was a desire to help build the developer community here in Houston. I saw this weekend that we could have just as stimulating a conference here in Houston as in that other big Texas city up north with all the weirdos. We need to show everyone that Houston is a great city for software developers!<br />
Here are some quick things that I’m going to be exploring in the coming weeks (sooner than later hopefully):<br />
<ul>
<li><a href="http://compositewpf.codeplex.com/">Composite Application Guidance for WPF and Silverlight</a> (aka Prism):</li>
<ul>
<li>I learned that you can use Prism to build any type of application, it’s not completely tied to WPF or Silverlight.</li>
<li>I’d like to see how to apply it to ASP.NET MVC or Windows Forms.</li>
</ul>
<li>Building complex (multiple-solution) software:</li>
<ul>
<li><a href="http://csharptest.net/?p=165">The build is software too.</a></li>
<li>Move away from copy/paste build scripts and towards convention based builds.</li>
</ul>
<li>Data Binding and Transformation:</li>
<ul>
<li>I’m still interested in how to do simple data binding and make it extensible.</li>
<li>This is the basis for rich Windows Forms applications I think.</li>
</ul>
</ul>
All in all, a great weekend. Thank you to <a href="http://flux88.com/">Ben Scheirman</a> and his crew who organized the Houston ALT.NET Open Space Conference, and thanks to <a href="http://www.stevenlist.com/">“Doc”</a> for his expert adult supervision. It was great seeing familiar faces and making new friends, thank you all for an awesome weekend!<br />
<div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:91fa07cf-f66e-483b-b1d2-910a8aebb9a7" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">
Technorati Tags: <a href="http://technorati.com/tags/altnetconf" rel="tag">altnetconf</a>,<a href="http://technorati.com/tags/altnethouston" rel="tag">altnethouston</a></div>
Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-85417622773939907812009-03-23T01:27:00.001-05:002012-09-12T22:30:19.402-05:00RefreshingI’m working on a personal refresh right now. I changed the theme of this site to make it look cleaner. I’m also signed up for the Houston ALT.NET Conference (<a href="http://houston.altnetconf.com/">http://houston.altnetconf.com</a>), which is pretty exciting. The last time I went to one of these open space conferences, it lead to a flurry of blog posts followed by a hiatus (thanks to business with school). I’m guessing something similar will happen here.<br />
I’ve been starting to get active on Twitter (more listening than tweeting). My alias there is <a href="http://twitter.com/garoyeri">@garoyeri</a>. I find it to be a good way to find interesting conversations. My Twitter client of choice (for now) is <a href="http://www.tweetdeck.com/beta/">TweetDeck</a>. I’m going to try and post interesting links for things I’m looking at.<br />
Code-wise, I’m thinking about a more extensible way to do object data binding for desktop applications. For web applications, the data is refreshed once on the server-side when it hits the page, then updated by JavaScript/AJAX on the browser-side. For something like this, <a href="http://www.codeplex.com/AutoMapper">AutoMapper</a> looks like a great way to make it happen. When dealing with desktop applications where the same data could be displayed in several places, the data binding / mapping needs to be “live” instead. I’ll be posting more about this sooner than later.<br />
I’ve also been looking at coding aspect of the software development process in our workgroup and have set up guidelines for our group. I’ll write more on that too.<br />
The StockSample I was writing about earlier got a little stale. We’ll see if I pick that series back up or not.<br />
<div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:4cf6d873-5fc6-4f22-a2ff-06a8cb61c799" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">
Technorati Tags: <a href="http://technorati.com/tags/personal" rel="tag">personal</a></div>
Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-56686068188437192772008-09-01T17:15:00.001-05:002012-09-12T22:30:34.871-05:00StockSample: Simple BindingIn Windows Forms land, it is easy to just use the existing capabilities of the Forms Designer in order to set up the bindings in the View. It would be nice to use this functionality on the model end of things, too. The problem, however, is that the sole purpose of the System.Windows.Forms.Binding class seems to be to bind a property to a control’s property. What we need is a simple way to bind two properties together.<br />
The SimpleBinding class (StockSample.Core.Framework.SimpleBinding) is based on an article from CodeProject: <a href="http://www.codeproject.com/KB/cs/simpledatabinding.aspx">Understanding Simple Data Binding</a> by Marc Clifton. Here is the usage pattern we’re looking for:<br />
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span>SimpleBinding.Bind(obj1, <span class="str">"Property1"</span>, obj2, <span class="str">"Property2"</span>);</pre>
</div>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<br />
This statement will bind obj1.Property1 to obj2.Property2. In terms of garbage collection, the Bind method will link the two objects together so that they will have the same lifetime. In some cases, this is not desirable and we may want to look into using <a href="http://msdn.microsoft.com/en-us/library/system.weakreference.aspx">WeakReference</a>s in the binding. This makes the code more complicated, but will help in cases where we want everything coupled a lot more loosely.<br />
This example statement, however, is not what is actually in the source code right now. I added an extra parameter of type <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.isynchronizeinvoke.aspx">ISynchronizeInvoke</a> that is called “affinity”. This parameter can be null if you don’t care about affinity (I’ll add an extra method overload to make it look prettier later). Affinity in this case refers to thread affinity. This is very important when binding to UI components because if you make any calls into Windows Forms, you have to make those calls on the thread that created the handle for the controls. <br />
Whenever you want to make a call into the UI (or potentially make a call into the UI), you want to follow this pattern:<br />
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span><span class="kwrd">void</span> DoSomething()</pre>
<pre><span class="lnum"> 2: </span>{</pre>
<pre class="alt"><span class="lnum"> 3: </span> <span class="kwrd">if</span> (affinity != <span class="kwrd">null</span> && affinity.InvokeRequired)</pre>
<pre><span class="lnum"> 4: </span> {</pre>
<pre class="alt"><span class="lnum"> 5: </span> affinity.BeginInvoke(<span class="kwrd">new</span> Action(DoSomething), <span class="kwrd">new</span> <span class="kwrd">object</span>[0]);</pre>
<pre><span class="lnum"> 6: </span> <span class="kwrd">return</span>;</pre>
<pre class="alt"><span class="lnum"> 7: </span> }</pre>
<pre><span class="lnum"> 8: </span> </pre>
<pre class="alt"><span class="lnum"> 9: </span> <span class="rem">// action to perform...</span></pre>
<pre><span class="lnum"> 10: </span>}</pre>
</div>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<br />
You could easily substitute Action for an anonymous delegate or some other construct that makes sense. The most important line there is line 6, if you don’t return, then you’ll end up falling through and executing the code anyway. <br />
Looking at the <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.control.aspx">Control</a> type, you’ll see that it implements ISynchronizeInvoke. Once the internal handle for the control is created, you can use Control.Invoke and Control.BeginInvoke to post messages on the UI thread’s message loop to execute delegates. Invoke will wait until the message is processed before returning. BeginInvoke will post the message and return immediately. Unlike calling BeginInvoke on a delegate instance, calling Control.BeginInvoke will not post anything into a thread pool, it uses the message loop. Moreover, if the control handle hasn’t been created yet, this method will fail. The safe bet is to find the topmost container for the control and use it as your ISynchronizeInvoke reference. This will make it more likely that the handle has been created. You can even call Control.CreateHandle to force the handle to be created in a more timely manner.<br />
Now that we know why there’s a fifth parameter in the SimpleBinding.Bind method, we should discuss what the method actually does:<br />
<ul>
<li>Get information about the properties being bound (using reflection).</li>
<ul>
<li>Some properties may not have setters, some properties may not have getters. This implicitly establishes if the binding is two-way or one-way.</li>
<li>We can only bind the properties that we have access to. If you can’t call the getter or setter from your code, then you can’t bind to it.</li>
</ul>
<li>Figure out how the property change is triggered. Right now, the SimpleBinding supports three types of triggers (technically two, but I guess “no trigger” could be construed as a type of trigger… or lack thereof).</li>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx">INotifyPropertyChanged</a>: if the object implements this interface, then the SimpleBinding will subscribe to the PropertyChanged event and use that to trigger the synchronization.</li>
<li><em>PropertyName</em>Changed event: This is a pattern that is evident in Windows Forms as well as in other places. In .NET 1.1, there was no INotifyPropertyChanged interface to implement. If the object does not implement INotifyPropertyChanged, then the SimpleBinding will use reflection to find an accessible event named <em>PropertyName</em>Changed. For example, to look for the change in the “Text” property, we look for an event called “TextChanged”.</li>
<li>No trigger: If the SimpleBinding can’t find any of the other triggers, then it just won’t bother with trying to figure out when the property changes.</li>
</ul>
<li>Force synchronization from obj1.property1 to obj2.property2.</li>
<ul>
<li>The convention is that the left property is pushed to the right. If everything is set up ok, then these two should be synchronized.</li>
<li>A more complete binding will check to see if the binding is one-way and which direction it should go before forcing synchronization.</li>
</ul>
</ul>
Now we know when a property changes and which thread we need to call getters and setters on. However, we’re missing the key part of binding, actually performing the synchronization.<br />
In the current version of the SimpleBinding, I take the naive approach and assume that the types are the same. This is VERY naive and is totally unrealistic, but will work for the time being.<br />
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span><span class="rem">// precondition: _prop1get != null && _prop2set != null</span></pre>
<pre><span class="lnum"> 2: </span><span class="kwrd">object</span> <span class="kwrd">value</span> = _prop1get.Invoke(_object1, <span class="kwrd">new</span> <span class="kwrd">object</span>[0]);</pre>
<pre class="alt"><span class="lnum"> 3: </span>_prop2set.Invoke(_object2, <span class="kwrd">new</span> <span class="kwrd">object</span>[] { <span class="kwrd">value</span> });</pre>
</div>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<br />
This code will definitely throw an exception if the property types don’t match up. It would be totally great if there was some pattern or functionality in the .NET Framework that would help us arbitrarily convert types and add new type conversions as needed. Luckily, such a thing exists: <a href="http://msdn.microsoft.com/en-us/library/system.iconvertible.aspx">IConvertible</a>. All the basic types in .NET implement this interface and we can make the following adjustments:<br />
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span><span class="kwrd">object</span> <span class="kwrd">value</span> = _prop1get.Invoke(_object1, <span class="kwrd">new</span> <span class="kwrd">object</span>[0]);</pre>
<pre><span class="lnum"> 2: </span><span class="kwrd">value</span> = Convert.ChangeType(<span class="kwrd">value</span>, _prop2.PropertyType);</pre>
<pre class="alt"><span class="lnum"> 3: </span>_prop2set.Invoke(_object2, <span class="kwrd">new</span> <span class="kwrd">object</span>[] { <span class="kwrd">value</span> });</pre>
</div>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<br />
This is a simple change (I got rid of the comment though, the precondition is the same as the code snippet above). <a href="http://msdn.microsoft.com/en-us/library/dtb69x08.aspx">Convert.ChangeType</a> will “do the right thing” or throw an exception if the cast is not valid. If you don’t want an exception, you can add the appropriate try/catch and deal with it however you see fit.<br />
The SimpleBinding is just that, simple. It definitely has a lot of room for growth and extension. I purposely made it simple and not very extensible. If someone wanted to really make a flexible binding system, then a pipeline type approach might work. In this way, you can insert a sequence of operations that will be performed when the binding is initialized and when the triggers are hit. The other problem is the strong references between the two objects that are being bound. These are not insurmountable issues and it is not SimpleBinding’s job to solve them all. SimpleBinding is a pattern that I like to follow and it can be adapted to different situations and changed to fit the needs of the application. I find it very useful to be able to use one line of clear code to keep two properties in sync.<br />
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:74d3cc4e-52a1-4de1-a30e-4756640ce604" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">
Technorati Tags: <a href="http://technorati.com/tags/C%23" rel="tag">C#</a>,<a href="http://technorati.com/tags/modelviewpresenter" rel="tag">modelviewpresenter</a>,<a href="http://technorati.com/tags/winforms" rel="tag">winforms</a></div>
Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com1tag:blogger.com,1999:blog-20189015.post-76440444734657870752008-08-22T00:34:00.001-05:002008-08-22T00:34:07.452-05:00StockSample: The View<p>This post is part of my series on the Windows Forms Model View Presenter with Data Binding sample program I wrote I call <a href="http://garoyeri.blogspot.com/2008/08/first-model-view-presenter-sample.html">StockSample</a>.</p> <p>In the 20080818 snapshot of the StockSample program, I have a shell program (the main form) and a single view that is in a module called “StockLister”.  I’m using some of the same terminology from CAB (<a href="http://msdn.microsoft.com/en-us/library/aa480450.aspx">Composite UI Application Block</a>).  The StockSample program doesn’t use anything other than the .NET base class library (and NUnit and DockPanel Suite).  An application such as this might be better hosted on something like CAB, or you can develop your own simpler framework that is specific to your application.  The benefit of going with an application framework that’s already developed is that (1) you don’t have to do it yourself and (2) you can more easily talk to someone else about your application.  For something that will be developed and maintained by multiple developers over time, using something like CAB might be easier to get them trained up since they can troll the Internet for documentation and starter examples.</p> <p>The module and the view represent a feature (or set of features) that tell a story (or part of a story).  The view is what the user sees and interacts with.  Most applications will have at least one view for the user to interact with.  In the StockSample program, the module is called “StockLister” and its purpose is to allow the user to see all the stocks that are available, their prices, and the timestamp of the last price update.  The view interface <em>IStockListerView</em> is very simple:</p> <div class="csharpcode"> <pre class="alt"><span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">interface</span> IStockListerView</pre>
<pre><span class="lnum"> 2: </span>{</pre>
<pre class="alt"><span class="lnum"> 3: </span> IStockList Stocks { get; set; }</pre>
<pre><span class="lnum"> 4: </span>}<br /></pre>
</div>
<p><style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>It accepts the interface reference to the <em>IStockList</em> we have in the model.  For this simple example, I made it so that the view can consume the model interface directly without modification.  In a more complex application, you may need to map the model data into the view data in different ways (this is handled by the Presenter which I will discuss in a later post).  For now, we will work with the simple example.  Notice that there is no reference to anything in WinForms or ASP.NET.  This view interface is a contract for a particular feature of the application (in this case, allowing the user to see a list of stocks with updated prices).</p>
<p>In the StockSample, this view is implemented as a WinForms UserControl.  Here are the steps I took to build this control:</p>
<ol>
<li>In Visual Studio, create a new UserControl and call it “StockListerControl”.</li>
<li>Make the control area bigger and drop a DataGridView on it.  Set the DataGridView DockStyle to Fill.</li>
<li>Click on the “Data” menu, then click “Add New Data Source…”.
<br /><a href="http://lh3.ggpht.com/garo.yeriazarian/SK5PstyerZI/AAAAAAAAAEs/PAGZN3alLMM/s1600-h/VisualStudioAddDataSource%5B3%5D.png"><img title="Add New Data Source option in Visual Studio" style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="155" alt="Add New Data Source option in Visual Studio" src="http://lh3.ggpht.com/garo.yeriazarian/SK5PtJFgFOI/AAAAAAAAAE0/nSa3ZxtCwBM/VisualStudioAddDataSource_thumb%5B1%5D.png?imgmax=800" width="298" border="0" /></a> </li>
<li>Select “Object”, click “Next”.</li>
<li>Drill down the tree (this tree is built from the classes in the project and external references) and select the “IStockList” interface.  Click “Next”.
<br /><a href="http://lh4.ggpht.com/garo.yeriazarian/SK5PtVRAHxI/AAAAAAAAAE4/GoIYDBReYO8/s1600-h/VisualStudioSelectStockListDataSource%5B3%5D.png"><img title="Where to find the IStockList data object to bind to" style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="279" alt="Where to find the IStockList data object to bind to" src="http://lh6.ggpht.com/garo.yeriazarian/SK5PtsrJvaI/AAAAAAAAAE8/MRUaHjUnKxU/VisualStudioSelectStockListDataSource_thumb%5B1%5D.png?imgmax=800" width="344" border="0" /></a> </li>
<li>Click “Finish”.</li>
<li>Now, click on the DataGridView, then find the “Smart Tag” in the top right (the little white box with the black chevron), click it, then click the drop-down that says “Choose Data Source”.</li>
<li>Drill down into “Other Data Sources”, “Project Data Source”, through a namespace or two, then click “IStockList”.
<br /><a href="http://lh6.ggpht.com/garo.yeriazarian/SK5PuYBiBcI/AAAAAAAAAFA/UnlUh7xCnYI/s1600-h/VisualStudioSelectIStockListDataSource%5B3%5D.png"><img title="Where to select the IStockList data source for the DataGridView" style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="337" alt="Where to select the IStockList data source for the DataGridView" src="http://lh5.ggpht.com/garo.yeriazarian/SK5Pu49niRI/AAAAAAAAAFE/qWq-FsGna-8/VisualStudioSelectIStockListDataSource_thumb%5B1%5D.png?imgmax=800" width="333" border="0" /></a> </li>
<li>The grid should be pre-populated with all the properties of <em>IStock</em>.  Based on how I wrote the interface for <em>IStockList</em>, Visual Studio figured out that this is a list of <em>IStock</em> objects.
<br /><a href="http://lh6.ggpht.com/garo.yeriazarian/SK5PyeACWYI/AAAAAAAAAFI/JzY30RjPPFU/s1600-h/VisualStudioIStockListDataSourceDescription%5B2%5D.png"><img title="VisualStudioIStockListDataSourceDescription" style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="180" alt="VisualStudioIStockListDataSourceDescription" src="http://lh5.ggpht.com/garo.yeriazarian/SK5PywEXl-I/AAAAAAAAAFM/jmM9zZZB6i8/VisualStudioIStockListDataSourceDescription_thumb.png?imgmax=800" width="186" border="0" /></a> </li>
<li>You can edit the grid columns to change the titles, data format, and ordering of the columns to make it look pretty.
<br /><a href="http://lh3.ggpht.com/garo.yeriazarian/SK5PzCb0qUI/AAAAAAAAAFQ/TNo6gpdcWqY/s1600-h/VisualStudioStockListerControl%5B6%5D.png"><img title="VisualStudioStockListerControl" style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="278" alt="VisualStudioStockListerControl" src="http://lh4.ggpht.com/garo.yeriazarian/SK5PztdvwEI/AAAAAAAAAFU/VnKpNIxCNMU/VisualStudioStockListerControl_thumb%5B4%5D.png?imgmax=800" width="480" border="0" /></a> </li>
<li>You’ll notice a new component added to your UserControl at the bottom of the screen, I renamed it to “iStockListBindingSource” to look nicer.</li>
</ol>
<p>Now that we have the control created, we write a little bit of code:</p>
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> StockListerControl</pre>
<pre><span class="lnum"> 2: </span> : UserControl, IStockListerView</pre>
<pre class="alt"><span class="lnum"> 3: </span>{</pre>
<pre><span class="lnum"> 4: </span> <span class="kwrd">public</span> StockListerControl()</pre>
<pre class="alt"><span class="lnum"> 5: </span> {</pre>
<pre><span class="lnum"> 6: </span> InitializeComponent();</pre>
<pre class="alt"><span class="lnum"> 7: </span> }</pre>
<pre><span class="lnum"> 8: </span> </pre>
<pre class="alt"><span class="lnum"> 9: </span> StockSample.Core.Data.IStockList _stocks;</pre>
<pre><span class="lnum"> 10: </span> </pre>
<pre class="alt"><span class="lnum"> 11: </span> <span class="kwrd">public</span> StockSample.Core.Data.IStockList Stocks</pre>
<pre><span class="lnum"> 12: </span> {</pre>
<pre class="alt"><span class="lnum"> 13: </span> get { <span class="kwrd">return</span> _stocks; }</pre>
<pre><span class="lnum"> 14: </span> set</pre>
<pre class="alt"><span class="lnum"> 15: </span> {</pre>
<pre><span class="lnum"> 16: </span> <span class="kwrd">if</span> (<span class="kwrd">this</span>.Stocks == <span class="kwrd">value</span>) <span class="kwrd">return</span>;</pre>
<pre class="alt"><span class="lnum"> 17: </span> </pre>
<pre><span class="lnum"> 18: </span> _stocks = <span class="kwrd">value</span>;</pre>
<pre class="alt"><span class="lnum"> 19: </span> iStockListBindingSource.DataSource = _stocks;</pre>
<pre><span class="lnum"> 20: </span> }</pre>
<pre class="alt"><span class="lnum"> 21: </span> }</pre>
<pre><span class="lnum"> 22: </span>}</pre>
</div>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p>The only meat here is line 19.  The “iStockListBindingSource” is what was created when we added the data source to the grid.  The Forms designer already connected the grid to the binding source, now we just need to supply the data source to the binding source to feed to the grid.  Due to the way we implement the model (using <a href="http://msdn.microsoft.com/en-us/library/ms132679.aspx">BindingList<T></a>), we get list update events for free.</p>
<p>At this point, all we’d need to do to show a simple form with just this control is to drop the control on a form, create an instance of the stock list, and pass the <em>IStockList</em> reference to the control.  Coincidentally (or not), that is exactly what the Presenter does.</p>
<p>The Visual Studio Forms Designer has a lot of easy to use features for data binding.  You can perform your own experiments on object data sources in Windows Forms applications.  It makes it super easy to create a functional prototype application as well without touching a database.  At work, I took half a day to create a fairly functional data driven application and not have to write a bunch of UI code.  Most of the work was spent creating the Model layer, then throwing a UI together and wiring everything up was a snap.</p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:2d07087b-28d7-4820-af84-7cd98044867a" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/C%23" rel="tag">C#</a>,<a href="http://technorati.com/tags/modelviewpresenter" rel="tag">modelviewpresenter</a>,<a href="http://technorati.com/tags/winforms" rel="tag">winforms</a></div> Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-46717312360186752142008-08-18T23:26:00.001-05:002008-08-19T00:46:04.939-05:00StockSample: The Model's Interfaces<p>This post is part of my series on the Windows Forms Model View Presenter with Data Binding sample program I wrote I call <a href="http://garoyeri.blogspot.com/2008/08/first-model-view-presenter-sample.html">StockSample</a>.</p> <p>One of the big things that is enabled by following the Model View Presenter pattern is "persistence ignorance".  For the model, I like to have POCO (Plain Old CLR Object) classes that represent the logical model that makes the most sense for the application.  This logical model might be different from the physical model if it makes the application easier to write.  Each of the model objects will also implement an interface that covers all the relevant publicly accessible properties, methods and events on the model types.  Interfaces will help with testability during development as you can create simpler test classes or use a mocking framework to create the desired test behavior.</p> <p>In the current StockSample snapshot (20080818), I have one model, the Stock.  It has the following interface:</p> <div class="csharpcode"> <pre class="alt"><span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">interface</span> IStock</pre>
<pre><span class="lnum"> 2: </span>{</pre>
<pre class="alt"><span class="lnum"> 3: </span> <span class="kwrd">string</span> Name { get; }</pre>
<pre><span class="lnum"> 4: </span> <span class="kwrd">string</span> TickerSymbol { get; }</pre>
<pre class="alt"><span class="lnum"> 5: </span> <span class="kwrd">decimal</span> CurrentPrice { get; }</pre>
<pre><span class="lnum"> 6: </span> DateTime LastUpdate { get; }</pre>
<pre class="alt"><span class="lnum"> 7: </span>}</pre>
</div>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>The Stock is special in that most of the application will not be modifying the stock information, but will be listening to changes to the stock.  I didn't make this interface inherit from INotifyPropertyChanged because the model class could use an alternative trigger for property change notifications (<em>PropertyName</em>Changed events, for example).  The stock information will be populated and updated by the IStockProvider:</p>
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">interface</span> IStockProvider</pre>
<pre><span class="lnum"> 2: </span>{</pre>
<pre class="alt"><span class="lnum"> 3: </span> IStockList Stocks { get; }</pre>
<pre><span class="lnum"> 4: </span>}</pre>
</div>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Now that I think about it, I suppose a better name would be StockListProvider, I'll have to make those tweaks later.  The IStockList represents a collection of IStock objects:</p>
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">interface</span> IStockList : IBindingList</pre>
<pre><span class="lnum"> 2: </span>{</pre>
<pre class="alt"><span class="lnum"> 3: </span> IStock CreateNew(<span class="kwrd">string</span> tickersymbol, <span class="kwrd">string</span> name);</pre>
<pre><span class="lnum"> 4: </span> <span class="kwrd">void</span> Add(IStock stock);</pre>
<pre class="alt"><span class="lnum"> 5: </span> IStock FindByTickerSymbol(<span class="kwrd">string</span> tickersymbol);</pre>
<pre><span class="lnum"> 6: </span> <span class="kwrd">new</span> IStock <span class="kwrd">this</span>[<span class="kwrd">int</span> index] { get; }</pre>
<pre class="alt"><span class="lnum"> 7: </span>}</pre>
</div>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>This interface has some more meat to it.  I inherit from IBindingList because I want to make sure we can bind this collection.  IBindingList is a bundle of interfaces that is necessary for binding a collection to places where a DataSet or DataView would typically go.  I'll go into more details about this later.</p>
<p>So, when dealing with the Model layer looking purely at the interfaces, we start with an IStockProvider.  The implementation of this is not important, all we care is that it provides is with an IStockList.  This list contains all the IStock instances that we will be able to use in our application.  The implementation of the IStockProvider will allow us to determine how we will actually get updated stock information.  The IStockList will tell us how many stocks there are and allow us to iterate on the list, and finally, the IStock will give us information on the stocks themselves.</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:c4b44180-3223-4ea9-a61c-bb1948d007f0" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/C%23" rel="tag">C#</a>,<a href="http://technorati.com/tags/modelviewpresenter" rel="tag">modelviewpresenter</a>,<a href="http://technorati.com/tags/winforms" rel="tag">winforms</a></div> Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-17586690690795143082008-08-18T22:40:00.001-05:002008-08-22T00:36:21.941-05:00StockSample: First Model View Presenter Sample Posted<p>After a long hiatus, I've created a new sample program for Windows Forms Model View Presenter pattern with data binding.  This example is not what I would call "best practices" but rather a simplification of the concepts to break it down to the most basic components.</p> <p>The example is a program that is used to get stock price updates.  I wanted an example that I could do a lot of different visualizations and views / operations that just about anyone can understand.  I know that Glenn Block posted on the Composite UI WPF guidelines here (<a title="http://blogs.msdn.com/gblock/archive/2008/07/03/composite-application-guidance-is-live.aspx" href="http://blogs.msdn.com/gblock/archive/2008/07/03/composite-application-guidance-is-live.aspx">http://blogs.msdn.com/gblock/archive/2008/07/03/composite-application-guidance-is-live.aspx</a>) and they also have a stock trading reference application.  The goal of my sample is to show a very simple example of Model View Presenter with Windows Forms and data binding.  There is no Inversion of Control container, no database, and no extra frills.  The sample is done in Visual Studio 2008 Express Edition (which is all you need to build / run it).  The only external libraries that are referenced are NUnit (<a href="http://www.nunit.org">http://www.nunit.org</a>) and Weifen Luo's DockPanel Suite (<a title="http://sourceforge.net/projects/dockpanelsuite/" href="http://sourceforge.net/projects/dockpanelsuite/">http://sourceforge.net/projects/dockpanelsuite/</a>).</p> <p>You can get the source from my google code project here, see this link for instructions on checking out code from my repository (<a title="http://code.google.com/p/garoyeriazarian/source/checkout" href="http://code.google.com/p/garoyeriazarian/source/checkout">http://code.google.com/p/garoyeriazarian/source/checkout</a>).  The code is in the StockSample/tags/Snapshot20080818 folder.  I'll be updating the trunk periodically with extra functionality.  There are some tests... I'm still trying to get the hang of Test Driven Development.</p> <p>I'll have a series of posts following talking about parts of the sample and as I build more onto it, I'll talk about those and link to the new snapshots.  You can then use your favorite Subversion client to see what exactly is different.  If you have any specific requests on things you want to see, let me know and I'll try to work it into the sample.</p> <p></p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:b6fc59df-6110-47e3-a9af-6b5613d3faf5" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/C%23" rel="tag">C#</a>,<a href="http://technorati.com/tags/modelviewpresenter" rel="tag">modelviewpresenter</a>,<a href="http://technorati.com/tags/winforms" rel="tag">winforms</a></div> Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com2tag:blogger.com,1999:blog-20189015.post-29710988207353538942007-10-23T22:28:00.000-05:002007-10-24T00:06:39.193-05:00Model View Presenter Data Binding Part 2: The ModelIn my Model-View-Presenter application, the Model is fairly simple, but can be extended to be more complicated (I guess that's really true for just about anything). I won't go into details on persistence, I'm going to concentrate on how I do the data binding.
For the Model, I follow the same pattern for properties that I did on the View:
<pre><code>int _nThingy;
public int Thingy
{
get
{
return _nThingy;
}
set
{
bool bChanged = (this.Thingy != value);
_nThingy = value;
if (bChanged) FireDataChanged("Thingy");
}
}</code></pre>
The FireDataChanged(string) method will fire a PropertyChanged event for the specified property.
When I'm working with collections, I create a class that inherits from BindingListBase (my custom .NET 1.1 class that implements IBindingList) or from System.ComponentModel.BindingList<T> (when using .NET 2.0). Both IBindingList implementations will look for changes to each of the elements in the list and translate them to ListChanged events. This will make life really easy when binding to grids and lists.
Oh yea, I almost forgot, there's one more piece that needs to be in place. The data object needs to implement <a href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.ieditableobject.aspx">IEditableObject</a>. The MSDN documentation has an example on how to implement it.
While this is deceptively simple, it does have some interesting consequences. Now, I can make changes to properties (with sheer impunity) and I can notify everyone else of all the changes that happen on the data objects.
Here's an example: I have a program that lets the user define a set of tubular equipment that is laid end to end. Each piece of equipment has the following properties: Inner Diameter, Outer Diameter, Top Depth, Bottom Depth, Length. For the sake of simplicity, lets say they are all integers.
For each equipment, Bottom Depth = Top Depth + Length. The equipment has to enforce this rule all the time. Also, when making adjustments, it should favor keeping the Length property constant. Here's how the properties end up looking:
<pre><code>public int TopDepth
{
get { return _nTopDepth; }
set
{
bool bChanged = (this.TopDepth != value);
_nTopDepth = value;
if (bChanged)
{
this.BottomDepth = this.TopDepth + this.Length;
FireDataChanged("TopDepth");
}
}
}
public int BottomDepth
{
get { return _nBottomDepth; }
set
{
bool bChanged = (this.BottomDepth != value);
_nBottomDepth = value;
if (bChanged)
{
this.Length = this.BottomDepth - this.TopDepth;
FireDataChanged("BottomDepth");
}
}
}
public int Length
{
get { return _nLength; }
set
{
bool bChanged = (this.Length != value);
_nLength = value;
if (bChanged)
{
this.BottomLength = this.TopDepth + this.Length;
FireDataChanged("Length");
}
}
}</code></pre>
If I set any of these three properties, the others will be synced up until the system stabilizes. Also, setting any one property will not only make adjustments to another property, it will fire both notifications automatically.
This is OK for a single piece of equipment, but we need to have some more interaction between the equipment. When the BottomDepth of a piece of equipment changes, the next equipment's TopDepth needs to change. When the TopDepth of a piece of equipment changes, the previous equipment's BottomDepth needs to change. To make this work, we hook into the ListChanged event on the BindingList and look at the ListChangedEventArgs.PropertyDescriptor property. If the change was BottomDepth or TopDepth, we make a change to the appropriate item. We have to take care of all the different types of ListChanged events: ItemAdded, ItemChanged, ItemDeleted, ItemMoved, and Reset. In each case, we make sure the adjacent TopDepth/BottomDepth pairs match up on the changed equipment.
Once all the pieces are in place, I just need to create a list, add some items to it, then set the DataSource property of a DataGridView, sit back, and watch the magic. If you edit the TopDepth, Length, or BottomDepth columns, then the model will make the adjustments and the DataGridView will be automatically updated. Also, you can assign the same list instance to another DataGridView, then the two grids will be synchronized automagically.
This is the basis for the Model layer of the Model View Presenter architecture. Using these techniques, we can bind any collection of data fearlessly to any UI component as well as binding properties with each other.Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com10tag:blogger.com,1999:blog-20189015.post-76112520825705293912007-10-08T21:36:00.000-05:002007-10-11T07:37:44.466-05:00ALT.NET Conference Sessions: ArchitectureI rummaged Technorati and looks like a lot of people already put up their summaries / impressions of the sessions at the <a href="http://www.altnetconf.com/">ALT.NET Conference in Austin, TX</a>. Here's some more about some of the sessions that I'm not seeing much discussion about:
Architecture (Trends and Observations)
The architecture chat started off a little sparse, but fattened up nicely fairly quickly. Aaron Armstrong was driving the conversation to see what people were seeing in architectures. There were a lot of familiar terms on the whiteboard (I can't really remember them all, did anyone write this down?)
I stood up and talked about the Model-View-Presenter architecture of the WinForms application I'm working on at work (<a href="http://www.flickr.com/photos/palermo/1510226988/in/pool-altnetconf/">picture 1</a>, <a href="http://www.flickr.com/photos/palermo/1509370967/in/pool-altnetconf/">picture 2</a>). I have a post about it that I'm planning to turn into a series of posts with some code and stuff. There was some interest in the data binding work I was doing, too. I'll talk more about that later. The main point that I was trying to make was that you can have multiple Models that don't know anything about the Views and are tied together using the Presenters. You can have multiple Models aggregated (in whole or partially) into one or more Views.
Aaron asked how someone would handle the scenario where you have a composite View in a WinForms application. The approach I would use would be to expose the different sub-Views on the composite View as properties and use an Inversion of Control framework to tie it all together. In the application I'm working on, I'm using <a href="http://www.springframework.net/">Spring.NET</a> to tie everything together (coincidentally, <a href="http://www.interface21.com/people/mpollack.html">Mark Pollack</a> was in the back of the room). My property data binding would then keep everything in sync.
The conversation then moved to more distributed architectures and web-related systems. There was some mention of the technique of using commodity hardware and/or software to create cheaply replaceable systems. On a similar note, Amazon released a white paper (papers?) on <a href="http://allthingsdistributed.com/2007/10/amazons_dynamo.html">"Dynamo"</a>, their network architecture. It is designed with the simple fact that hardware will fail and needs to be easily (and cheaply) replaceable.
We also talked about Service-Oriented Architecture and what to do about data. Some people feel compelled to integrate all the databases and data sources into one unified database. This leads to some friction as the different functions of the system move forward. When the data stores are properly separated, then the needs of the different applications (or services) can be met without affecting other applications (or services) that may be using the same data store. Everyone agreed that the database should not be used as an integration tool. Someone (I forget who) also explained the idea of thinking of the data flowing through the distributed system as a "document" instead of just messages going back and forth.
We also talked a little about how to have a good architecture while still doing agile development. Agile development is against "Big Design Up Front", but sometimes you will need to have a vision and an architecture to scale properly. The main idea is to keep the architecture simple at first, get the project working, then make refinements as needed. Don't optimize too early, otherwise you may end up debugging strange issues that would not have risen from a simpler design. Also, you can more easily optimize when you start from a simple design and you can do small steps at a time to keep the system stable as you try to improve performance.
That's all I can remember off the top of my head. I'm sure others will fill in the gaps and make corrections. All in all, it was a very interesting talk. Software Architecture is one of the subjects that I am very interested in and I found it very invigorating to hear from others and their thoughts on architecture.
<span style="font-size:78%;"><a href="http://technorati.com/tag/altnetconf" rel="tag"><img style="border:0;vertical-align:middle;margin-left:.4em" src="http://static.technorati.com/static/img/pub/icon-utag-16x13.png?tag=altnetconf" alt=" " />altnetconf</a></span>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-19877547739263058802007-10-08T20:56:00.000-05:002007-10-11T07:37:33.573-05:00ALT.NET Conference Sessions: DSLI rummaged Technorati and looks like a lot of people already put up their summaries / impressions of the sessions at the <a href="http://www.altnetconf.com/">ALT.NET Conference in Austin, TX</a>. Here's some more about some of the sessions that I'm not seeing much discussion about:
Domain-Specific Languages for Business Users / Developers
The DSL talk started off a little rough (the organizer wasn't there), but Arafat Mohamed stepped up and started the conversation. Just about everyone in the room was there to learn about DSLs and were not really using them in their projects.
We talked about what we thought a DSL really was. It seems that just about anything can be a DSL (depending on how specific you are to what domain). According to Martin Fowler, "a domain-specific language is a veneer over an API" (I think that's the verbage he used). He differentiates between an internal DSL (one that is consumed by developers) versus an external DSL (one that is consumed by the users). Martin Fowler has some more information on his <a href="http://www.martinfowler.com/">website</a>. There is also some information on <a href="http://en.wikipedia.org/wiki/Domain-specific_programming_language">Wikipedia</a>.
One of the primary applications for DSLs that I can think of is a business rules engine. For example, you have a cell phone provider who has complex billing semantics and wants to be able to add new rules easily. There are a lot of concerns with this, however. Developers may not want the analysts modifying the behavior of the system as they may not be as disciplined. On the flip side, managers want the analysts to do the work to keep the developer freed up. It is a delicate balance that can only really be helped by properly training the analysts so that they know the proper practices. You can also avoid problems by creating the proper tooling.
Going to the more practical side... Scott Guthrie pointed out that IL had some pragmas that could be used to give the debugger hints on what the original source file was and what line of that source file corresponds to the generated code. He said that they used this mechanism for debugging the generated code from XAML, XOML and the other declarative constructs.
You could also use <a href="http://boo.codehaus.org/">Boo</a> as a meta-language to construct your DSL. In theory, Visual Studio should be able to debug Boo since Boo compiled to IL and _should_ have the line numbers and source file information embedded in the PDB files. (in theory). Boo is also the source of <a href="http://www.ayende.com/Blog/archive/2007/09/22/Introducing-Boobs-Boo-Build-System.aspx">Boobs</a> (the build system with an oral fixation) and <a href="http://www.ayende.com/Blog/category/451.aspx">Binsor</a>. Oren (<a href="http://www.blogger.com/www.ayende.com">Ayende</a>) has a lot of posts regarding Boo. Also, if you want good IDE support for Boo, look at <a href="http://www.icsharpcode.net/OpenSource/SD/Default.aspx">SharpDevelop</a>.
If you need to develop your own language from scratch, <a href="http://www.antlr.org/">Antlr</a> seems to be the way to go. The people in the room who had used it said it was better than the old-school lexx / yacc approach.
There are a lot of concerns though in creating a DSL in that you would have to maintain it and train everyone how to use it. This reminds me of two things:
1) Wasabi, the language created by Joel Spolsky for FogBugz (<a href="http://www.joelonsoftware.com/items/2006/09/01b.html">linky</a>)
2) The MUMPS System (<a href="http://worsethanfailure.com/Articles/A_Case_of_the_MUMPS.aspx">linky</a>)
In both cases, developers will basically have a bunch of work that they can't really put on their resume because their expertise is in an in-house language. A DSL may create the same sort of situation. Also, whoever develops the DSL will be the authority on it and if he/she decides to leave the company without properly documenting it, the DSL will be useless.
At the end of the session, I think everyone got a good feel for the positives and negatives of creating and using domain-specific languages. I learned that I would need to think long and hard before considering implementing a DSL and that there are a lot of solutions (Boo, Ruby, scripting) that would require a lot less work up front and would provide fellow developers with some take-aways.
Another summary on the DSL session: <a href="http://blogs.solidhouse.com/david.woods/PermaLink,guid,d578e144-1f1d-44c4-badd-f4e5e22f9110.aspx">David Woods</a>
<span style="font-size:78%;"><a href="http://technorati.com/tag/altnetconf" rel="tag"><img style="border:0;vertical-align:middle;margin-left:.4em" src="http://static.technorati.com/static/img/pub/icon-utag-16x13.png?tag=altnetconf" alt=" " />altnetconf</a></span>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-24639513690222919352007-10-07T20:20:00.000-05:002007-10-11T07:37:14.811-05:00Back from ALT.NET ConferenceI just got back from ALT.NET Conference (<a href="http://www.altnetconf.com/">http://www.altnetconf.com/</a>) in Austin and it was a blast. I've only been to a few other "conferences" but this is the only one that I would actually consider a "conference" more than a one-way brain dump.
I met a lot of interesting people who I've been reading about, but didn't really know. Everyone is really passionate about their work and they have strong opinions (that are not really set in stone). Everyone was very receptive to alternative techniques, theories and interpretations. I'm looking forward to participating more in this community. I would also like to thank everyone for being there and making my weekend spectacular! And also to thank the organizers for giving us such a unique and fulfilling opportunity.
I think a few people were interested in the WinForms MVP data binding work I've been doing, I'll try to continue that series of posts as soon as possible (I started one a month ago, but haven't really continued it). I'll get some recreated code samples up too.
<span style="font-size:78%;"><a href="http://technorati.com/tag/altnetconf" rel="tag"><img style="border:0;vertical-align:middle;margin-left:.4em" src="http://static.technorati.com/static/img/pub/icon-utag-16x13.png?tag=altnetconf" alt=" " />altnetconf</a></span>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-52790597421120300542007-09-04T17:20:00.001-05:002008-03-04T22:08:59.388-06:00Model View Presenter Data Binding Part 1: The ViewWhen I first started using Windows Forms, I immediately realized that it doesn't scale unless you put forth some effort and discipline in building some infrastructure. The built-in data binding is dodgy unless you just use the Forms Designer to do everything in Visual Studio. There's no definitive documentation on how you can do data binding on something that's not a DataSet or DataTable. There are some unofficial guidelines (can't find the link now, but will post when I do), but nothing that really serves as a reference. (If there is some documentation... then I guess I just didn't look deep enough on the Internet).
I went down this route because at work I was trying to bind a POCO (Plain Old CLR Object) to a third-party grid (<a href="http://xceed.com/Grid_Winforms_Intro.html">http://xceed.com/Grid_Winforms_Intro.html</a>). Luckily, the documentation that Xceed distributes with their product pointed me in the right direction and gave me some sample code as a start. The key is IBindingList, which has its own manual of rules. I got a little bit of a start and managed to create a base class to make life as easy as possible.
One issue to note is that I'm still using .NET Framework 1.1, which doesn't have generics. .NET 2.0 has a generic BindingListBase type that will work a lot better than my simplified approach. The nice thing is that I'll be ready for the jump to 2.0 since I'm already using this brand of collection. The other nicety that .NET 2.0 provides is INotifyPropertyChanged. .NET 1.1 has the delegate type (PropertyChangeEventHandler) and the EventArgs type (PropertyChangeEventArgs), but is just missing the interface to tie it all together. Again, I'm thinking ahead and I'll be ready for the jump to 2.0.
Back to Forms data binding: Windows Forms has a really extensive set of APIs and helpers and types (oh my) to bind controls to DataSets which are, in turn, tied to databases directly using ADO.NET, but doesn't play as well with POCOs that are common with having a business layer or with ORM scenarios. I tried to get it to work... but there was always something missing. To make life easier, I created my own set of binding methods based partly on this CodeProject article (<a href="http://www.codeproject.com/csharp/simpledatabinding.asp">http://www.codeproject.com/csharp/simpledatabinding.asp</a>). The article describes a simpler binding mechanism that is able to bind any property to any other property. It tried to take advantage of IConvertible to change types that are compatible but not exactly the same. This approach is super easy because custom types can just implement IConvertible and they'll "just work" with the binding. Also, if you bind properties of the same type, then you don't even need IConvertible, it will just assign the value. I added some extra capabilities to the binding and allowed it to take a reference to an ISynchronizeInvoke object that will make sure that the synchronizing code is executed on the right thread when dealing with UI objects. The basic syntax is as follows:
<code>ThreadAwareBinding.Bind(myDataObject, "Property1", myTextField, "Text", myTextField);</code>
The really neat thing (and this is from the article) is that at bind-time, the binder will examine both properties and look for an event named "<propertyname>Changed", where PropertyName is the property that is bound. In my version, I allow the user to specify a trigger event explicitly, or it will look for my version of the INotifyPropertyChanged interface. Whichever it finds first, it will use that mechanism for binding. If more than one is provided, it will prioritize.
On the data objects, I specify properties with the following pattern:
<pre><code>int _nThingy;
public int Thingy
{
get
{
return _nThingy;
}
set
{
bool bChanged = (this.Thingy != value);
_nThingy = value;
if (bChanged) FireDataChanged("Thingy");
}
}</code></pre>
I made a macro in Visual Studio so that all I had to do was type the name of the property and it would be expanded into this template.
So, for the "View" aspect of the Model-View-Presenter, I do the following things:
</propertyname><ol><li>Create a Form or UserControl called "MyView".
</li><li>Create an interface called "IMyView" that has all the properties declared that we want to display on the control / form.</li><li>Implement the "IMyView" interface on the form or user control, also implement the INotifyPropertyChanged interface.</li><li>In the Load event, bind the properties to the desired controls (I have automated this step somewhat, I'll talk about it in another post).</li></ol>The end result is that the View can be modified through its interface properties and can be swapped out for a mock object or something else if we want to do some testing.Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-58657370964551055292007-02-24T12:58:00.000-06:002007-02-24T13:07:11.541-06:00Linux LoveA while back I posted about my Gentoo Linux Laptop. It served me well, but it was becoming a hassle keeping it up to date. I was checking for updates like daily and then watching all the updates compile. It was an addiction. I found myself visiting http://packages.gentoo.org several times a day to see what new stuff was out, then I would curse myself for not being able to remotely SSH into the box to do upgrades. I'm admitting that I have a problem, and that I have addressed it. I wiped my Linux partition on the laptop and installed Ubuntu 6.10 (Edgy). The update process only includes necessary security / bugfix updates (not full system upgrades). The release process is every 6 months, so I can expect a full system upgrade every 6 months. That's manageable. Plus, all the updates are binary so they'll just install smoothly. Someone else has already done all the footwork for me. THIS is what Linux is all about, making life easy.
However, don't get me wrong, I'm still a big Gentoo fan, but just not for my primary laptop that has a Pentium M 1.7GHz with 512MB RAM. It's not a beast, but does the job. Compiling stuff takes time and I don't want to have to deal with it. My desktop, on the other hand, is (well, was) a beast. Now it is slowly becoming obsolete. I need to replace it with a sexy Core 2 Duo system. Mmmmmm.... tasty. But that will have to wait. Right now I don't really use it all that much, favoring the laptop for day-to-day stuff. I don't do much independent development either. Plus, the northbridge and GPU fans are crapping out on me and I need to replace (or supplement) them. I think I should put the graphics card (Radeon 9800 All-In-Wonder) in my brother's desktop and then sell the motherboard (dead NIC, messed up NB fan), and processor (2.4GHz with a big-ass heat-sink and fan) on eBay or something.
Speaking of Linux love, my girlfriend is teasing me with thoughts of putting together a Linux-based multimedia system for streaming Chinese soap operas into the living room. That's hot.Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-78041756412414669082007-02-24T10:09:00.000-06:002007-02-24T10:44:10.208-06:002 double-oh 7All right, it's already two months into 2-double-oh-7 and I'm finally updating my blog. Blogger had a huge upgrade and (as you can see) I switched over to a new template. It's also nice that I can log in using my Gmail instead of something else...
First, I'd like to look at last year and see how I did on my New Year's resolutions...
<ul><li>Get my weight below 200 pounds: d'oh. I think I gained a little weight. I must have plateaued. I'm still fitting into my clothes though, so it's not bad. I'm holding at about 215 to 220 (with clothes and shoes and after work).</li><li>Keeping in touch with my extended family: Woo hoo! I got to know my cousins more and the six of us got a lot closer this year. We're all busy busy, but we keep in touch more.</li><li>Learning Armenian: umm... didn't get around to this. Boo on me.</li><li>Attending an Armenian youth event: My brother and I attended a few AYF (Armenian Youth Federation) meetings. It was... interesting... It wasn't our cup of tea, although now we can say that we went and tried. I got some good reading materials out of it though (although I haven't even read any of it yet).</li></ul>Observations about 2006:
<ul><li>On the love front, I'm in love, been in love, gonna remain in love. Hoo-Yeah!</li><li>On the home front, I'm keeping in touch with family and being a good son.
</li><li>On the work front, I think I vastly improved my people skills. I believe I have been making great strides in being easier to work with and recognizing other people's contributions. The fact remains though that I am hard to impress (in software terms).</li><li>I started working on my MBA in the fall. It's tough doing the school + work thing, I have utmost respect (always have) for people who do the school + work (or work + school, the additive property holds here) thing. The work is easy, but tedious, and it burns me out. Luckily it is only 2 nights a week. It's manageable. I've been trying to go to the gym on campus for those days, but work's been really busy and they've needed me to stay to 4 to help out instead of leaving at 3 to go to school. It's worth it though, bonus time is coming around and I know that my contributions will be recognized.</li></ul>Forward-Looking Statements for 2-double-oh-7
<ul><li>I want to get my weight down. Below 200 may not work, but at least near 200. I plan to go to the gym for longer sessions, try to attend some of those classes they have. I also plan to consistently go to the gym at school. Finally, I need to know my limits with food. I'm finding that my body tells me when its full, but I keep eating anyway (this goes for dinner mainly). I think I can manage it. I think starting school messed me up a bit, but I can adjust and persevere.</li><li>I want to learn to read and write Armenian. I have resources, and I just need to set a schedule for myself. It's going to be tougher now that I have my MBA classes as well (until 2009), but I think I can manage.</li><li>I want to learn to speak / understand Cantonese, at least on a basic level. It's an interesting language, but I feel I have an obligation to myself and my family to master my own language first. There are 10 months left in the year, plenty of time.</li></ul>I think that's a good start. I may add to the list as I see fit.Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-1158480356661260352006-09-17T03:04:00.000-05:002007-02-24T10:43:56.968-06:00Life is Good<span style="font-size:85%;"><span style="font-family:arial;">Life is good. I could qualify that, but it would detract from the simplicity of the statement.</span></span>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-1155689643847974932006-08-15T19:47:00.000-05:002007-02-24T10:43:39.892-06:00Yikes, it's been a while<span style="font-size:85%;">Hmm, it's been a while... it seems that life has gotten in the way of me updating my blog. No matter. Things are going very well according to plan. I'm starting working on my MBA (at the University of Houston, GO COOGS!) next week. (YAY!) Aaaaand... work is really great. I got back from the Dr. Dobbs Journal Architecture and Design World (learned a lot and met some interesting people). Umm... other than that, things are pretty much going steady and nice.
My laptop battery (Dell 600m) is one of the recalled ones (kinda makes sense, the side of the computer where the battery is heats up a bit). Still, Dell is making it super easy, just type in your battery serial number, then fill in your address info and "voila" you will have your new battery (and instructions on disposing of your old one) within 20 days (ish). We'll see how long it REALLY takes.
I'm finally starting to use Visual Studio 2005 (good grief, it's about time!). I wish Microsoft would hurry up and release their SP1 patches for Visual Studio 2003 and 2005. I'm also starting to learn more about web services and such. Very interesting.
Oh, my abstract was accepted for the Baker Hughes Technology Forum 2006! Party on! I'm going to talk about how Inversion of Control can streamline the build / debug / test process. I'm also going to give a presentation for my group about all the goodies I learned at the Dr. Dobb's AD World thingy.
I went to my last HDNUG (<a href="http://www.hdnug.org/">www.hdnug.org</a>) (Houston Dot Net Users Group) meeting that I'll be able to attend for a while. I won a book (Test Driven Development (the NUnit book)), and a Best Buy gift card (shweeeeet). TDD is very interesting, I need to finish that book and send the HDNUGgers a review.
I really want to start an independent project (been wanting to for a loooong whiles now). I'm thinking either an email-based game engine or perhaps a good subversion (<a href="http://subversion.tigris.org/">subversion.tigris.org</a>) client for GNOME. Not sure yet. Both would be fun projects. The former would be a .NET 2.o project using Windows Forms (or GTK#) and the latter would be GTK+ and C/C++. Oooooh... tasty. But... alas. School will take up a lot of my time I believe (and I really want to make sure I have enough time to get back into running).
At one time, I was able to run almost 3 miles straight... I need to work back up to that. I've been going to the gym on a very regular basis now so far this year. I need to get my run on Tuesdays and Thursdays so I can keep up the burn. My goal of being under 200 lbs by end of the year doesn't seem like its going to happen. But hey, my clothes all fit better and I can wear some brand size 34 jeans, so that's a huge step in the right direction.
In Nerdage news... I'm toying with the idea of upgrading my computer to the behemoth gaming machine worthy of an uber-nerd. Mmmmm.... silicon wafery goodness. Vee shall see how that little plan goes...
Ah... hopefully I'll be keeping up with this blog more. It is very refreshing being able to dump my brain out here for my own posterity.</span>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-1140413313408759392006-02-19T23:33:00.000-06:002007-02-24T10:42:58.854-06:00Fun at Work<div xmlns="http://www.w3.org/1999/xhtml"><small>I've been having some crazy fun at work! Our project is progressing very well and I've added some really sexy features to it. I found that I enjoy writing tools / scripts for developers more than writing applications for customers. (Unfortunately, the latter are more prone to paying for software than the former) ',;-) I am the resident build-master in my department. I manage the build scripts and make sure that people don't check in stuff that breaks the build. I could call myself a "Build Nazi", but that may carry the wrong connotation. I think of myself more like the "Soup Nazi", but with software builds instead of jambalaya. What is this commit? Huh? NO BUILD FOR YOU! Heh heh heh...
</small><div xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml"><small>Yea, so. Fun at work. I think it's very important to have fun at work irregardless (not a real word) of anything. My modus operandi is that if I'm not having fun at work at the moment, I need to get up, walk around, and go bug some of my coworkers. After all, what good is having coworkers if you don't go bother them everyone once in a while to let them know you're still around.
</small>
<div xmlns="http://www.w3.org/1999/xhtml"><small>I know there's some nerdage in this post somewhere... heh. Oh yea, the software I'm working on! Great stuff. I wrote a GUI framework a whiles back for this application and I'm finally getting some integration work done to pull pieces into it. Basically, you start with a skeleton application that has some menus predefined, a toolbar, a sidebar, and a main work area. You can define plugins via .xml files that exist in the distribution tree. These files are pulled in automatically when the application starts. I've been using Spring (for .NET) [linky: <a href="http://www.springframework.net/">http://www.springframework.net</a>]. They still have some bugs in there, but it's coming along really well. I think I had a post about it before... [<a href="http://garoyeri.blogspot.com/2006/01/back-to-work.html">linky</a>]. Anyhoo, Spring is an "Inversion of Control" or "Dependency Injection" container. You describe objects in xml files and how to instantiate them. Each object may require other objects in the container to be set in the constructor or via properties (this determines the instantiation order). Check out the website, they have links to some articles regarding the topic. I may even write a paper or something about my GUI framework... oooh... great idea. So yea, the nerdage part of this is that you can drop new pieces into the application by dropping a folder into any subfolder of the application and then restarting the application. It will automagically pull in the new pieces and fire up the application. My boss liked it, I did a short demo where I pulled in a few pieces and showed how they were in the app, then deleted a folder, restarted the app and showed that the features were missing. So, the great part is that when I do a "debug" build, it will pull in all our testing plugins that test the individual controls or features as well as the whole application. When we want to do a "release" build, it won't pull those folders in. If we wanted to update a feature, we could just remove the folder and put the new one in. If we wanted to add a new feature, all we do is push the folder into the filesystem. Sexy!
My job satisfaction has been skyrocketing these last two weeks. I owe it to my overdue vacation in California. (Nice place to visit, but I wouldn't live there unless I got some crazy crazy job offer or something I couldn't pass up). I couldn't move there though... I would miss my family and my girlfriend. I dunno what it was, but after I got back from my vacation, my fingers had a mind of their own (don't think dirty thoughts, I'm talking about typing). I think I'm going to need a new keyboard soon... my old one at work is a biohazard area. I've spilled coffee, orange juice (both from an orange and from a bottle), milk, water, and random bits of food on it. It contains 2.5 years of hair, flecks of skin and boogers. I'm not afraid to admit that when I'm deep in thought, I pick my nose (I'm trying to pick my brain, but haven't been quite able to reach it). I have hairy hands and they like to shed. Back to job satisfaction... Yea. We have a really small group (4 developers) so I get a lot of freedom when it comes to what tools to use and I have a say in how the project goes programming-wise (15%... the manager has more pull than me, go figure). All this work on the build script and integrating into my GUI framework have been very invigorating. There's some thing beautiful about pulling a source tree, running one command, then firing up a working application. Mmmm... hotness. This high should last until mid to late June, at which time I hope to start up another high (with a new project). Ahhhh.... yummy.</small><big>
</big></div></div></div></div>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-1139210822164655792006-02-06T01:20:00.000-06:002007-02-24T10:41:27.419-06:00Super Bowl!!! (in HD)<span style="font-size:85%;">Hanging out in California at a friend of the family's house... I got to watch the Super Bowl on a big (BIG) screen in HD. It was nice! On one of the commercials, I could see the guy's contact lens, it was THAT detailed!
Also... it seems that picking bad (really bad) movie rentals is a Korean thing. I have a friend (who happens to be Korean) who is notorious for picking terrible movies to rent (when they are out of the mainstream). We went to Blockbuster today to rent some movies and my friend said a friend recommended a movie called "Old Boy". It was a Korean movie (dubbed). It was very strange. Very. Strange. Strange.... Yea. It was like watching a Steven Segal movie. You don't really watch the movie, you just comment on it and make jokes about the main character's bad choice of lines and weapons. This movie had a common carpenter's hammer as the interesting weapon of choice. The first scene had the main character urinating in the lobby of the police station. Like I said... strange. Anyhoo, now we're gonna watch "Red Eye" with a bigger group (I think we should scratch the "Old Boy" disc as a service to Blockbuster and their customers). I'm fairly sure that the two guys working there laughed at us when we left with this particular movie. ',;-)
</span>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-1138487452794227812006-01-28T16:30:00.000-06:002007-02-24T10:40:23.825-06:00Cleaning out the closet<div xmlns="http://www.w3.org/1999/xhtml"><span style="font-size:85%;">Maaaaaaaaaan... today I decided to clean out my closet, removing all the clothes that don't fit anymore. Last year I lost like 20 pounds and dropped two inches from my waist (party on Gar!)
I didnt realize that I had 10 years of clothes in my closet. There were a lot of shirts that I hadn't touched in a long long time. In the end, I now have a two foot high pile of shirts and pants (many more shirts than pants) that are way too big for me. These are either going to get handed up to my dad or donated. We usually take our donation stuff to Katy Christian Ministries, and they either distribute it or sell it I think. I can see the back of my closet now, it's much more manageable.
I just wanted to share that personal victory with the internet. ',;-)
</span></div>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-1138419614053942182006-01-27T21:40:00.000-06:002007-02-24T10:40:09.028-06:00Email Clients... revenge of the suck!<div xmlns="http://www.w3.org/1999/xhtml"><span style="font-size:85%;">Waaaaaaaaah... ok. I'm really frustrated with email clients right now on Windows. On Linux, I use Evolution (which is not perfect, but close). On Windows, I don't use an email client, but my mom does. She needs an email program that's easy to use and also a calendar application.
<span style="font-weight: bold;">Outlook 2000</span>
She used to use Outlook 2000, but she had a lot of problems with spam. Outlook 2000 has a really stupid spam filter that just filters the sender (which is totally ineffective since spammers swap out their from addresses frequently). Outlook 2000 also has some inherent problems in how it deals with messages. If you get an email with images that are pulled from the internet, it will automatically display those images (suck!). If there are hyperlinks in a message, there is no way to see where they point until you click them (suck!). When you are composing a message and you want to select addressees, there is no clear way as to how it generates the autocompletion list. I have yet to figure it out. SUCK! Yea...
<span style="font-weight: bold;">Roadrunner email</span>
We have roadrunner and I set my mom up with a roadrunner email address a long while ago. Back then, GMail didn't exist and Yahoo had a really cruddy interface. What I wanted to do was let her use Outlook which she was used to using. Little did I know the entire valley of suck that awaited my mom in that email account. No spam filtering, 20 MB limit, an absolutely excremental webmail interface. Boo. So, many spam messages later, I decided to try and be creative. I got her a GMail account (which is great, by the way) and set up roadrunner to forward all mail to GMail, then set up Outlook to pull messages from GMail. Yay, it was working great! Except... in a few days, her roadrunner mailbox filled up and started bouncing messages. Apparently, roadrunner email doesn't believe in deleting messages that it forwards (even though EVERY other email service will remove / archive / trash messages that are auto-forwarded to another email account. SUCK! So, that idea was shot down... which leads me to......
<span style="font-weight: bold;">Thunderbird</span>
Mozilla Thunderbird is hotness. 1.5 RC1 was out and I installed that. It was updated to RC2 and that becamse the final 1.5. Great, party down. Thunderbird has integrated spam filtering, a sane address book, a sane message composition system, and a nice simple interface. It detects phishing, doesn't automatically show internet images, deals with attachments in a totally sexy way. Thunderbird is great. Except... when it comes to dealing with messages sent from Outlook. Most of the people who send my mom mail (or at least the source of the chain mail, jokes, funny attachments, whatever) use Outlook (2000, 2002 or 2003). Outlook viciously mangles messages when they get forwarded by everyone. The HTML messages get totally messed up with the tables in tables in div's in tables in div's in whatever. Clicking "forward" makes Thunderbird cry. Sometimes, when Outlook forwards an inline image, it doesn't show up in other email clients. Also, when you try to forward an email with an inline image in Thunderbird, it doesn't send the image along. For some reason, the IMG tag has a "moz-do-not-send=true" attribute which tells Thunderbird to not send the image (even though I told Thunderbird to always send images instead of just linking them). Hmm. Apparently this is a known bug in Thunderbird and will be fixed in mid-February when 1.5.0.1 is released. Hmm... waiting sucks, and I don't want to subject my mom to nightly builds that may cause her to grumble curses in my general direction. Also, Thunderbird doesn't have a built-in calendar (yet) that works well. Sunbird is still a ways off (still very unstable). Mozilla Lightning (Thunderbird + Sunbird) is something I'm really looking forward to. But... alas, I needed a calendar too... which leads me to....
<span style="font-weight: bold;">Outlook 2003</span>
I decided to bite the bullet and put Outlook 2003 on my mom's computer. Installation was easy (a few hundred megs for an email client does sound a bit excessive, though). It has email, calendar, tasks, the works. Sounds good. However... I quickly realized that Outlook 2003 is not a big jump from Outlook 2000. It had a few of the nasties fixed such as blocking messages from the internet and showing hyperlink destinations. But... without installing Microsoft Word, the email composition is dismal. Entering addressees sucks as bad as in Outlook 2000. In fact, it is exactly the same. The whole application looks like a patchwork. There are pieces that look new and flashy, and there are a lot of pieces that look like they were left in there from Outlook 2000. Suck. Suck. Suck. I was thoroughly unimpressed. Suck. It has a few nice features in the email component, but nothing that Thunderbird didn't do (except for dealing with messages sent from Outlook well). On the bright side, my mom is now able to forward all the messages she wants without incident. She also has a decent calendar app that she can use to set reminders and stuff. But... she's stuck with a substandard spam filter and a clunky interface. She got used to Thunderbird's hotness and going to Outlook is like jumping 6 years into the past. Suck.
Chances are that we'll put Thunderbird back on there sooner or later... then I'll be happy again. Or, we can wait until Evolution gets ported to Win32 and she'll have the hotness of Evolution (with calendaring as well). It will be a happy day for me when I can share the hotness of Evolution with the Win32ers.
I don't know why this whole episode got me all worked up... I guess it's just that I get so frustrated with bad software. I'm a bit of a selective perfectionist when it comes to software, you could say. ',;-) /></span></div>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com1tag:blogger.com,1999:blog-20189015.post-1136776123205426692006-01-08T21:05:00.000-06:002007-02-24T10:39:50.554-06:00Gentoo Linux Laptop<span style="font-size:85%;"><span style="font-family:arial;">Yay! My new laptop is in and it's HOT! I spent the last 24+ hours (awake and asleep) setting it all up. Now it is built up and stable, party on! I'm running Gentoo Linux built from Stage 3, but I had to rebuild everything because GCC 3.3 was on the LiveCD but it doesn't support a Pentium M architecture directly. I had to build stuff with GCC 3.3 to get it to boot on its own, then I upgraded to GCC 3.4 and rebuilt everything with the proper optimizations. It runs like a dream! I'll post some screenshots later...</span></span>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-1136511107813863752006-01-05T19:25:00.000-06:002007-02-24T10:39:31.473-06:00Sinus Infection<span style="font-size:85%;"><span style="font-family:arial;">Blah. Sinus infection sucks... but I'm on Z-Pac (sp?) It's some good stuff. It is a 5-day antibiotic, so by Sunday I'll be totally clear of little critters. In practice, I'm usually cleared by day 3 (sometimes 4) but you gotta make sure you finish up the prescription.</span>
<span style="font-family:arial;"> </span>
<span style="font-family:arial;">I get these sinus infections whenever the weather changes. 2005, however, has been a very weird weather year and the last time I got hit was March. To add insult to injury... my insurance changed from a copay system to a deductible system, and I didn't have my HSA debit card yet, so I had to pay for the doctor's visit out of pocket, more so than I would have about a week ago. <blows></blows></span>
<span style="font-family:arial;">Ah, but life is good, I took a sick day and stayed home from work. ',;-)</span>
</span>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-1136261558513428052006-01-02T22:07:00.000-06:002007-02-24T10:39:08.113-06:00Back to work...<span style="font-size:85%;"><span style="font-family:arial;">Well, the holidays are officially over, time to get back to the daily grind. I'm looking forward to it, actually. That means I'll have more nerdy things to report on! (When I'm home, I try to nerd out as much as possible, but the holidays are usually very busy with non-nerdy things) ',;-)</span>
<span style="font-family:arial;">Right now at work I'm working on a GUI framework based on the Spring Framework for .NET (</span><a style="font-family: arial;" href="http://www.springframework.net/">http://www.springframework.net</a><span style="font-family:arial;">). It's an "Inversion of Control" (IoC) container that is a port of the same framework for java (which seems to be popular). It allows us to develop software in parallel and forces us to take a component-oriented approach to development. I'll post some more juicy bits about it later, right now I need to get to bed because I'll be waking up at 4:30am tomorrow... gnight!</span>
</span>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-1136108672554333792006-01-01T03:21:00.000-06:002007-02-24T10:36:19.415-06:00Happy New Year!<span style="font-size:100%;"><span>Ok, it's now 2006 for all US time zones (I think). Happy New Year to everyone! I wish you all the best in the coming year and may it be as good (if not better) than 2005!</span>
<span>New Year is a great time to reflect on the past year and see how you feel about it. Yes, that's a bit cliche, but it's just one of those things that people do. This year has been an incredible year for me! Let's do a quick recap...</span>
</span><ul><li><span style="font-size:100%;">I had a new year's resolution to lose weight last year. I ended up losing 20ish pounds and dropped two inches off the waist. I'm fitting in my size 36 pants now and most of the clothes in my closet don't fit me anymore.</span></li><li><span style="font-size:100%;">I'm in a great relationship with a great girl! Our closeness has only increased over the year (does that make any sense?) We're always finding things that bring to light just how alike we are in our ideals, dogmas, and methodologies. It's great to be able to talk to someone about a situation and have them say "Yea, I feel exactly the same way!" That's a cool feeling.</span></li><li><span style="font-size:100%;">My work has gotten more fun. I have been given fairly free reign over how I do my job (programming). I can pick my tools and feel free to explore new things. We have new and interesting projects that people want to use and are itching to use. We're making our company oodles of cash money and they are compensating me fairly well. (I could always use more money, though... that goes without saying).</span></li></ul><span style="font-size:100%;"><span style="font-family:arial;">So yea, it's been a great year. But now, time to think about 2006. I have made some resolutions that I plan to keep for 2006. I'm gonna put them on the internet now to make them permanent!</span>
</span><ul style="font-family:arial;"><li><span style="font-size:100%;">I want to push my weight below 200 lbs. I plan on being more consistent with my running regiment. I have been going to the gym on a very regular basis (3x a week), but I want to start taking the aerobics classes to do some fat burning.</span></li><li><span style="font-size:100%;">I want to keep more in touch with my extended family. My cousin is getting married in February and I feel like I don't know him anymore. I haven't really been as close with my cousins as I would like. I plan on hanging out with them whenever I can and plan some family outings and such. Also, I would like to get closer to my brother. We don't really do much together and it would be nice to just hang with him.
</span></li><li><span style="font-size:100%;">I want to learn to read and write Armenian. I can speak (well enough). But my vocabulary sucks and I can't read or write very well. There are some great websites that have lots of good info... I'll post some links later. One comes to mind: <a href="http://www.armeniapedia.org/index.php?title=Main_Page">Armeniapedia</a>. I would also like to at least attend one Armenian youth function / gathering / party.
</span></li></ul><span style="font-size:100%;"><span>That's about it. Not a long list, but it has all the important things. These are goals I feel I can attain. This year I also plan on starting on my MBA. I have a GMAT study guide now and I just have to schedule my GMATs, then fill out my application. That should be interesting. I think I will need to start working from home a bit (instead of going all the way down to the office) to make sure I don't burn myself out.</span>
<span>Ah, so yea. I'm ready for 2-double-oh-6. How about you?</span>
</span>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-1135906891845339322005-12-29T19:09:00.000-06:002007-02-24T10:33:10.422-06:00She's baaaaaaack<span style="font-size:85%;"><div style="font-family: arial;">Yay, my honey's back in town! I wrapped up her present really nicely... brown paper packages tied up with string... these are a few of her favorite things! ',;-)</div>
<div>
<a style="font-family: arial;" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://static.flickr.com/40/79148328_820001fba2.jpg"><img style="cursor: pointer; width: 320px;" src="http://static.flickr.com/40/79148328_820001fba2.jpg" alt="" border="0" /></a>
</div>
<div>
<a style="font-family: arial;" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://static.flickr.com/41/79148330_f5184ddb1a.jpg"><img style="margin: 0pt 10px 10px 0pt; float: none; cursor: pointer; width: 320px;" src="http://static.flickr.com/41/79148330_f5184ddb1a.jpg" alt="" border="0" /></a>
</div>
<div style="font-family: arial;">These took me about two hours to meticulously wrap... (ssssssh, don't tell her, there are a few boxes inside wrapped similarly) ',;-) I can think of this as a type of "nerdage" appropriate for my blog. There is no tape showing on the outside of any of the boxes. It's beautimous!</div>
</span>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0tag:blogger.com,1999:blog-20189015.post-1135584656642355352005-12-26T02:06:00.000-06:002005-12-26T02:10:56.643-06:00Linkage...<span style="font-size:85%;"><span style="font-family: arial;">I wanted to take a second and link up to my friends:
<a href="http://whatscookingjackie.blogspot.com/">http://whatscookingjackie.blogspot.com/</a>
<a href="http://thespacemonkeyrepublic.blogspot.com/">http://thespacemonkeyrepublic.blogspot.com/</a></span></span>
<span style="font-size:85%;"><span style="font-family: arial;">Howdy ya'll.</span></span><span class="" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"></span>
<span class="down" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"></span>Anonymoushttp://www.blogger.com/profile/02237615942295409687noreply@blogger.com0